feat(auth): add profile update and password change endpoints; enhance provider list handling

This commit is contained in:
JSC
2025-06-29 22:00:59 +02:00
parent 91648a858e
commit a7210a8d50
4 changed files with 129 additions and 4 deletions

View File

@@ -272,3 +272,115 @@ def me():
"""Get current user information."""
user = get_current_user()
return {"user": user}
@bp.route("/profile", methods=["PATCH"])
@require_auth
def update_profile():
"""Update current user profile information."""
from flask import request
from app.database import db
from app.models.user import User
data = request.get_json()
if not data:
return {"error": "No data provided"}, 400
user_data = get_current_user()
if not user_data:
return {"error": "User not authenticated"}, 401
user = User.query.get(int(user_data["id"]))
if not user:
return {"error": "User not found"}, 404
# Update allowed fields
if "name" in data:
name = data["name"].strip()
if not name:
return {"error": "Name cannot be empty"}, 400
if len(name) > 100:
return {"error": "Name too long (max 100 characters)"}, 400
user.name = name
try:
db.session.commit()
# Return fresh user data from database
updated_user = {
"id": str(user.id),
"email": user.email,
"name": user.name,
"picture": user.picture,
"role": user.role,
"is_active": user.is_active,
"provider": "password", # This endpoint is only for password users
"providers": [p.provider for p in user.oauth_providers],
"plan": user.plan.to_dict() if user.plan else None,
"credits": user.credits,
}
return {
"message": "Profile updated successfully",
"user": updated_user
}
except Exception as e:
db.session.rollback()
return {"error": f"Failed to update profile: {str(e)}"}, 500
@bp.route("/password", methods=["PUT"])
@require_auth
def change_password():
"""Change or set user password."""
from flask import request
from app.database import db
from app.models.user import User
from werkzeug.security import check_password_hash
data = request.get_json()
if not data:
return {"error": "No data provided"}, 400
user_data = get_current_user()
if not user_data:
return {"error": "User not authenticated"}, 401
user = User.query.get(int(user_data["id"]))
if not user:
return {"error": "User not found"}, 404
new_password = data.get("new_password")
current_password = data.get("current_password")
if not new_password:
return {"error": "New password is required"}, 400
# Password validation
if len(new_password) < 6:
return {"error": "Password must be at least 6 characters long"}, 400
# Check authentication method: if user logged in via password, require current password
# If user logged in via OAuth, they can change password without current password
current_auth_method = user_data.get("provider", "unknown")
if user.password_hash and current_auth_method == "password":
# User has a password AND logged in via password, require current password for verification
if not current_password:
return {"error": "Current password is required to change password"}, 400
if not check_password_hash(user.password_hash, current_password):
return {"error": "Current password is incorrect"}, 400
# If user logged in via OAuth (google, github, etc.), they can change password without current password
# Set the new password
try:
user.set_password(new_password)
db.session.commit()
return {
"message": "Password updated successfully"
}
except Exception as e:
db.session.rollback()
return {"error": f"Failed to update password: {str(e)}"}, 500