feat: Add user profile management and password change endpoints
Some checks failed
Backend CI / lint (push) Failing after 4m51s
Backend CI / test (push) Successful in 3m38s

This commit is contained in:
JSC
2025-08-09 23:43:20 +02:00
parent 9e07ce393f
commit 0a8b50a0be
4 changed files with 195 additions and 0 deletions

View File

@@ -430,3 +430,85 @@ class AuthService:
oauth_user_info.email,
)
return AuthResponse(user=user_response, token=token)
async def update_user_profile(self, user: User, data: dict) -> User:
"""Update user profile information."""
logger.info("Updating profile for user: %s", user.email)
# Only allow updating specific fields
allowed_fields = {"name"}
update_data = {k: v for k, v in data.items() if k in allowed_fields}
if not update_data:
return user
# Update user
for field, value in update_data.items():
setattr(user, field, value)
self.session.add(user)
await self.session.commit()
await self.session.refresh(user, ["plan"])
logger.info("Profile updated successfully for user: %s", user.email)
return user
async def change_user_password(
self, user: User, current_password: str | None, new_password: str
) -> None:
"""Change user's password."""
# Store user email before any operations to avoid session detachment issues
user_email = user.email
logger.info("Changing password for user: %s", user_email)
# Store whether user had existing password before we modify it
had_existing_password = user.password_hash is not None
# If user has existing password, verify it
if had_existing_password:
if not current_password:
raise ValueError("Current password is required when changing existing password")
if not PasswordUtils.verify_password(current_password, user.password_hash):
raise ValueError("Current password is incorrect")
else:
# User doesn't have a password (OAuth-only user), so we're setting their first password
logger.info("Setting first password for OAuth user: %s", user_email)
# Hash new password
new_password_hash = PasswordUtils.hash_password(new_password)
# Update user
user.password_hash = new_password_hash
self.session.add(user)
await self.session.commit()
logger.info("Password %s successfully for user: %s",
"changed" if had_existing_password else "set", user_email)
async def user_to_response(self, user: User) -> UserResponse:
"""Convert User model to UserResponse with plan information."""
# Load plan relationship if not already loaded
if not hasattr(user, 'plan') or not user.plan:
await self.session.refresh(user, ["plan"])
return UserResponse(
id=user.id,
email=user.email,
name=user.name,
picture=user.picture,
role=user.role,
credits=user.credits,
is_active=user.is_active,
plan={
"id": user.plan.id,
"name": user.plan.name,
"max_credits": user.plan.max_credits,
"features": [], # Add features if needed
},
created_at=user.created_at,
updated_at=user.updated_at,
)
async def get_user_oauth_providers(self, user: User):
"""Get OAuth providers connected to the user."""
return await self.oauth_repo.get_by_user_id(user.id)