|
|
@@ -13,6 +13,7 @@ from dependencies import get_current_user, require_admin
|
|
|
import config
|
|
|
import secrets
|
|
|
from services.email_service import send_verification_email, send_password_reset_email
|
|
|
+from services.token_service import token_service
|
|
|
|
|
|
try:
|
|
|
from google.oauth2 import id_token
|
|
|
@@ -40,10 +41,8 @@ async def register(request: Request, user: schemas.UserCreate, lang: str = "en")
|
|
|
|
|
|
user_id = db.execute_commit(query, params)
|
|
|
|
|
|
- # Generate Verification Token
|
|
|
- token = secrets.token_urlsafe(32)
|
|
|
- expires_at = datetime.utcnow() + timedelta(hours=24)
|
|
|
- db.execute_commit("INSERT INTO email_verification_tokens (user_id, token, expires_at) VALUES (%s, %s, %s)", (user_id, token, expires_at))
|
|
|
+ # Generate Verification Token (Redis)
|
|
|
+ token = token_service.create_verification_token(user_id)
|
|
|
|
|
|
# Send Email
|
|
|
send_verification_email(user.email, token, user.preferred_language or lang)
|
|
|
@@ -53,16 +52,12 @@ async def register(request: Request, user: schemas.UserCreate, lang: str = "en")
|
|
|
|
|
|
@router.get("/verify-email")
|
|
|
async def verify_email(token: str, lang: str = "en"):
|
|
|
- res = db.execute_query("SELECT user_id, expires_at FROM email_verification_tokens WHERE token = %s", (token,))
|
|
|
- if not res:
|
|
|
- raise HTTPException(status_code=400, detail="Invalid verification token")
|
|
|
-
|
|
|
- user_id, expires_at = res[0]['user_id'], res[0]['expires_at']
|
|
|
- if expires_at < datetime.utcnow():
|
|
|
- raise HTTPException(status_code=400, detail="Verification token expired")
|
|
|
+ user_id = token_service.verify_email_token(token)
|
|
|
+ if not user_id:
|
|
|
+ raise HTTPException(status_code=400, detail="Invalid or expired verification token")
|
|
|
|
|
|
db.execute_commit("UPDATE users SET is_active = 1 WHERE id = %s", (user_id,))
|
|
|
- db.execute_commit("DELETE FROM email_verification_tokens WHERE user_id = %s", (user_id,))
|
|
|
+ token_service.delete_verification_token(token)
|
|
|
|
|
|
return {"message": "Email verified successfully. You can now log in."}
|
|
|
|
|
|
@@ -182,9 +177,8 @@ async def forgot_password(request: schemas.ForgotPassword, lang: str = "en"):
|
|
|
user = db.execute_query("SELECT id, preferred_language FROM users WHERE email = %s", (request.email,))
|
|
|
if not user: raise HTTPException(status_code=404, detail="Email not found")
|
|
|
|
|
|
- token = secrets.token_urlsafe(32)
|
|
|
- expires_at = datetime.utcnow() + timedelta(minutes=10)
|
|
|
- db.execute_commit("INSERT INTO password_reset_tokens (user_id, token, expires_at) VALUES (%s, %s, %s)", (user[0]['id'], token, expires_at))
|
|
|
+ # Generate Reset Token (Redis - 10 min TTL)
|
|
|
+ token = token_service.create_reset_token(user[0]['id'])
|
|
|
|
|
|
# Send Email
|
|
|
user_lang = user[0]['preferred_language'] or lang
|
|
|
@@ -194,18 +188,17 @@ async def forgot_password(request: schemas.ForgotPassword, lang: str = "en"):
|
|
|
|
|
|
@router.post("/reset-password")
|
|
|
async def reset_password(request: schemas.ResetPassword):
|
|
|
- reset_data = db.execute_query("SELECT user_id, expires_at FROM password_reset_tokens WHERE token = %s", (request.token,))
|
|
|
- if not reset_data: raise HTTPException(status_code=400, detail="Invalid token")
|
|
|
- if reset_data[0]['expires_at'] < datetime.utcnow(): raise HTTPException(status_code=400, detail="Token expired")
|
|
|
+ user_id = token_service.verify_reset_token(request.token)
|
|
|
+ if not user_id:
|
|
|
+ raise HTTPException(status_code=400, detail="Invalid or expired reset token")
|
|
|
|
|
|
- user_id = reset_data[0]['user_id']
|
|
|
hashed_password = auth_utils.get_password_hash(request.new_password)
|
|
|
db.execute_commit("UPDATE users SET password_hash = %s WHERE id = %s", (hashed_password, user_id))
|
|
|
|
|
|
- # IMPORTANT: Delete ALL tokens for this user after successful reset
|
|
|
- db.execute_commit("DELETE FROM password_reset_tokens WHERE user_id = %s", (user_id,))
|
|
|
+ # Successful reset - Cleanup ALL reset tokens for this user
|
|
|
+ token_service.cleanup_reset_tokens(user_id)
|
|
|
|
|
|
- return {"message": "Password reset successfully"}
|
|
|
+ return {"message": "Password updated successfully"}
|
|
|
|
|
|
@router.get("/me", response_model=schemas.UserResponse)
|
|
|
async def get_me(user: dict = Depends(get_current_user)):
|