11from datetime import datetime , timezone
22
3- from flask import Blueprint , jsonify , request , g , render_template , redirect
3+ from flask import Blueprint , jsonify , request , g
44
55from .limiter import limiter
66from utils .auth_utils import (
2121 users_collection ,
2222)
2323from utils .url_utils import get_client_ip
24+ from utils .auth_utils import get_user_profile
2425import jwt
25-
26+ from bson import ObjectId
2627
2728auth = Blueprint ("auth" , __name__ )
2829
2930
30- def _minimal_user_profile (user_doc ):
31- return {
32- "id" : str (user_doc ["_id" ]),
33- "email" : user_doc .get ("email" ),
34- "user_name" : user_doc .get ("user_name" ),
35- "plan" : user_doc .get ("plan" , "free" ),
36- }
37-
38-
3931@auth .route ("/auth/login" , methods = ["POST" ])
4032@limiter .limit ("5/minute" )
4133@limiter .limit ("50/day" )
@@ -47,16 +39,16 @@ def login():
4739 return jsonify ({"error" : "email and password are required" }), 400
4840
4941 user = get_user_by_email (email )
50- if not user or not user .get ("password " ):
42+ if not user or not user .get ("password_hash " ):
5143 # Do not reveal which part failed
5244 return jsonify ({"error" : "invalid credentials" }), 401
5345
54- if not verify_password (password , user ["password " ]):
46+ if not verify_password (password , user ["password_hash " ]):
5547 return jsonify ({"error" : "invalid credentials" }), 401
5648
5749 access_token = generate_access_jwt (str (user ["_id" ]))
5850 refresh_token = generate_refresh_jwt (str (user ["_id" ]))
59- resp = jsonify ({"access_token" : access_token , "user" : _minimal_user_profile (user )})
51+ resp = jsonify ({"access_token" : access_token , "user" : get_user_profile (user )})
6052 set_refresh_cookie (resp , refresh_token )
6153 set_access_cookie (resp , access_token )
6254 return resp , 200
@@ -105,7 +97,7 @@ def me():
10597 user = get_user_by_id (user_id )
10698 if not user :
10799 return jsonify ({"error" : "user not found" }), 404
108- return jsonify ({"user" : _minimal_user_profile (user )})
100+ return jsonify ({"user" : get_user_profile (user )})
109101
110102
111103@auth .route ("/auth/register" , methods = ["POST" ])
@@ -129,12 +121,17 @@ def register():
129121 password_hash = hash_password (password )
130122 user_doc = {
131123 "email" : email ,
132- "password" : password_hash ,
124+ "email_verified" : False , # Email not verified initially
125+ "password_hash" : password_hash ,
126+ "password_set" : True ,
133127 "user_name" : user_name ,
128+ "pfp" : None ,
129+ "auth_providers" : [],
134130 "plan" : "free" ,
135131 "signup_ip" : get_client_ip (),
136132 "created_at" : datetime .now (timezone .utc ),
137133 "updated_at" : datetime .now (timezone .utc ),
134+ "status" : "ACTIVE" ,
138135 }
139136 try :
140137 insert_result = users_collection .insert_one (user_doc )
@@ -148,68 +145,54 @@ def register():
148145 resp = jsonify (
149146 {
150147 "access_token" : access_token ,
151- "user" : _minimal_user_profile ({"_id" : user_id , ** user_doc }),
148+ "user" : get_user_profile ({"_id" : user_id , ** user_doc }),
152149 }
153150 )
154151 set_refresh_cookie (resp , refresh_token )
155152 set_access_cookie (resp , access_token )
156153 return resp , 201
157154
158155
159- @auth .route ("/dashboard " , methods = ["GET " ])
156+ @auth .route ("/auth/set-password " , methods = ["POST " ])
160157@requires_auth
161- def dashboard ():
162- # Redirect to links page as the default dashboard view
163- return redirect ("/dashboard/links" )
164-
165-
166- @auth .route ("/dashboard/links" , methods = ["GET" ])
167- @requires_auth
168- def dashboard_links ():
158+ @limiter .limit ("5/minute" )
159+ def set_password ():
160+ """Set password for OAuth-only users"""
169161 user = get_user_by_id (g .user_id )
170162 if not user :
171163 return jsonify ({"error" : "user not found" }), 404
172- return render_template (
173- "dashboard/links.html" ,
174- host_url = request .host_url ,
175- user = _minimal_user_profile (user ),
176- )
177-
178164
179- @auth .route ("/dashboard/keys" , methods = ["GET" ])
180- @requires_auth
181- def dashboard_keys ():
182- user = get_user_by_id (g .user_id )
183- if not user :
184- return jsonify ({"error" : "user not found" }), 404
185- return render_template (
186- "dashboard/keys.html" ,
187- host_url = request .host_url ,
188- user = _minimal_user_profile (user ),
189- )
165+ if user .get ("password_set" , False ):
166+ return jsonify ({"error" : "password already set" }), 400
190167
168+ body = request .get_json (silent = True ) or {}
169+ password = body .get ("password" ) or ""
191170
192- @auth .route ("/dashboard/statistics" , methods = ["GET" ])
193- @requires_auth
194- def dashboard_statistics ():
195- user = get_user_by_id (g .user_id )
196- if not user :
197- return jsonify ({"error" : "user not found" }), 404
198- return render_template (
199- "dashboard/statistics.html" ,
200- host_url = request .host_url ,
201- user = _minimal_user_profile (user ),
202- )
171+ if not password :
172+ return jsonify ({"error" : "password is required" }), 400
203173
174+ if len (password ) < 8 :
175+ return jsonify ({"error" : "password must be at least 8 characters" }), 400
204176
205- @auth .route ("/dashboard/settings" , methods = ["GET" ])
206- @requires_auth
207- def dashboard_settings ():
208- user = get_user_by_id (g .user_id )
209- if not user :
210- return jsonify ({"error" : "user not found" }), 404
211- return render_template (
212- "dashboard/settings.html" ,
213- host_url = request .host_url ,
214- user = _minimal_user_profile (user ),
215- )
177+ try :
178+ password_hash = hash_password (password )
179+
180+ result = users_collection .update_one (
181+ {"_id" : ObjectId (g .user_id )},
182+ {
183+ "$set" : {
184+ "password_hash" : password_hash ,
185+ "password_set" : True ,
186+ "updated_at" : datetime .now (timezone .utc ),
187+ }
188+ },
189+ )
190+
191+ if result .modified_count > 0 :
192+ return jsonify ({"success" : True , "message" : "password set successfully" })
193+ else :
194+ return jsonify ({"error" : "failed to set password" }), 500
195+
196+ except Exception as e :
197+ print (f"Error setting password: { e } " )
198+ return jsonify ({"error" : "failed to set password" }), 500
0 commit comments