@@ -20,6 +20,11 @@ def inject_globals():
2020
2121@main .route ('/' )
2222def dashboard ():
23+ # require login to view dashboard
24+ user_id = session .get ('user_id' )
25+ if not user_id :
26+ flash ('Please log in to access the dashboard.' , 'error' )
27+ return redirect (url_for ('main.login' , next = url_for ('main.dashboard' )))
2328 return render_template ('dashboard.html' )
2429
2530@main .route ('/upload' , methods = ['POST' ])
@@ -74,13 +79,101 @@ def login():
7479 # If profile incomplete, redirect to complete profile
7580 if not user .get ('full_name' ) or not user .get ('company' ):
7681 return redirect (url_for ('main.complete_profile' ))
82+ # Respect optional `next` param so we can redirect to dashboard or original page
83+ next_url = request .args .get ('next' ) or request .form .get ('next' )
84+ if next_url :
85+ return redirect (next_url )
7786 return redirect (url_for ('main.dashboard' ))
7887 else :
7988 flash ('Invalid credentials.' , 'error' )
8089 return render_template ('login.html' )
8190 return render_template ('login.html' )
8291
8392
93+ @main .route ('/login/<provider>' )
94+ def oauth_login (provider ):
95+ # start oauth login flow
96+ oauth = current_app .oauth
97+ if provider not in oauth ._registry :
98+ flash ('Unknown OAuth provider.' , 'error' )
99+ return redirect (url_for ('main.login' ))
100+ redirect_uri = url_for ('main.oauth_callback' , provider = provider , _external = True )
101+ return oauth .create_client (provider ).authorize_redirect (redirect_uri )
102+
103+
104+ @main .route ('/auth/<provider>/callback' )
105+ def oauth_callback (provider ):
106+ oauth = current_app .oauth
107+ client = oauth .create_client (provider )
108+ if not client :
109+ flash ('OAuth client not configured.' , 'error' )
110+ return redirect (url_for ('main.login' ))
111+ token = client .authorize_access_token ()
112+ if not token :
113+ flash ('Authentication failed.' , 'error' )
114+ return redirect (url_for ('main.login' ))
115+ # fetch basic profile information depending on provider
116+ profile = {}
117+ if provider == 'github' :
118+ profile = client .get ('user' ).json ()
119+ email = profile .get ('email' ) or (client .get ('user/emails' ).json ()[0 ].get ('email' ) if client .get ('user/emails' ) else None )
120+ elif provider == 'gitlab' :
121+ profile = client .get ('user' ).json ()
122+ email = profile .get ('email' )
123+ elif provider == 'linkedin' :
124+ # LinkedIn requires separate endpoints for email and profile
125+ profile = client .get ('me' ).json ()
126+ email_resp = client .get ('emailAddress?q=members&projection=(elements*(handle~))' )
127+ email = None
128+ try :
129+ email = email_resp .json ().get ('elements' , [])[0 ].get ('handle~' , {}).get ('emailAddress' )
130+ except Exception :
131+ email = None
132+ elif provider == 'facebook' :
133+ profile = client .get ('me?fields=id,name,email' ).json ()
134+ email = profile .get ('email' )
135+ else :
136+ email = None
137+
138+ if not email :
139+ flash ('Could not retrieve email from provider. Please sign up with email/password.' , 'error' )
140+ return redirect (url_for ('main.signup' ))
141+
142+ # If user exists, log them in; otherwise create an account (random password)
143+ user = authenticate_user (email , '' )
144+ # authenticate_user expects a password; instead we'll check existence directly
145+ from dbkamp .db import get_connection
146+ conn = get_connection ()
147+ cur = conn .cursor ()
148+ cur .execute ('SELECT * FROM users WHERE email = ?' , (email ,))
149+ row = cur .fetchone ()
150+ conn .close ()
151+ if row :
152+ session ['user_id' ] = row ['id' ]
153+ session ['user_email' ] = row ['email' ]
154+ flash ('Logged in with ' + provider .capitalize (), 'success' )
155+ return redirect (url_for ('main.dashboard' ))
156+ else :
157+ # create user with a random password placeholder
158+ import secrets
159+ pw = secrets .token_urlsafe (16 )
160+ created = create_user (email , pw )
161+ if created :
162+ # fetch new user id
163+ conn = get_connection ()
164+ cur = conn .cursor ()
165+ cur .execute ('SELECT * FROM users WHERE email = ?' , (email ,))
166+ new = cur .fetchone ()
167+ conn .close ()
168+ session ['user_id' ] = new ['id' ]
169+ session ['user_email' ] = new ['email' ]
170+ flash ('Account created via ' + provider .capitalize (), 'success' )
171+ return redirect (url_for ('main.complete_profile' ))
172+ else :
173+ flash ('Unable to create account.' , 'error' )
174+ return redirect (url_for ('main.signup' ))
175+
176+
84177@main .route ('/resources' )
85178def resources ():
86179 return render_template ('resources.html' )
0 commit comments