Add subcription feature 5

This commit is contained in:
Urtzi Alfaro
2026-01-16 09:55:54 +01:00
parent 483a9f64cd
commit 6b43116efd
51 changed files with 1428 additions and 312 deletions

View File

@@ -351,6 +351,8 @@ class AuthService:
'subscription_id': result['subscription_id'],
'payment_customer_id': result['payment_customer_id'],
'status': result['status'],
'access_token': result.get('access_token'),
'refresh_token': result.get('refresh_token'),
'message': 'Registration completed successfully after 3DS verification'
}
@@ -593,9 +595,129 @@ class AuthService:
detail=f"Token generation failed: {str(e)}"
) from e
async def request_password_reset(self, email: str) -> bool:
"""
Request a password reset for a user
Args:
email: User's email address
Returns:
True if request was processed (whether user exists or not)
"""
try:
logger.info(f"Processing password reset request for email: {email}")
async with self.database_manager.get_session() as session:
user_repo = UserRepository(User, session)
# Find user by email (don't reveal if user exists)
user = await user_repo.get_by_field("email", email)
if not user:
logger.info(f"Password reset request for non-existent email: {email}")
return True # Don't reveal if email exists
# Generate reset token
reset_token = SecurityManager.generate_reset_token()
# Set expiration (1 hour)
from datetime import datetime, timedelta, timezone
expires_at = datetime.now(timezone.utc) + timedelta(hours=1)
# Store reset token
token_repo = PasswordResetTokenRepository(session)
# Clean up expired tokens
await token_repo.cleanup_expired_tokens()
# Create new token
await token_repo.create_token(
user_id=str(user.id),
token=reset_token,
expires_at=expires_at
)
# Commit transaction
await session.commit()
logger.info(f"Password reset token created for user: {email}")
return True
except Exception as e:
logger.error(f"Password reset request failed: {str(e)}", exc_info=True)
return False
async def reset_password_with_token(self, token: str, new_password: str) -> bool:
"""
Reset password using a valid reset token
Args:
token: Password reset token
new_password: New password to set
Returns:
True if password was successfully reset
"""
try:
logger.info(f"Processing password reset with token: {token[:10]}...")
# Validate password strength
if not SecurityManager.validate_password(new_password):
errors = SecurityManager.get_password_validation_errors(new_password)
logger.warning(f"Password validation failed: {errors}")
raise ValueError(f"Password does not meet requirements: {'; '.join(errors)}")
async with self.database_manager.get_session() as session:
# Find the reset token
token_repo = PasswordResetTokenRepository(session)
reset_token_obj = await token_repo.get_token_by_value(token)
if not reset_token_obj:
logger.warning(f"Invalid or expired password reset token: {token[:10]}...")
raise ValueError("Invalid or expired reset token")
# Get the user
user_repo = UserRepository(User, session)
user = await user_repo.get_by_id(str(reset_token_obj.user_id))
if not user:
logger.error(f"User not found for reset token: {token[:10]}...")
raise ValueError("Invalid reset token")
# Hash the new password
hashed_password = SecurityManager.hash_password(new_password)
# Update user's password
await user_repo.update(str(user.id), {
"hashed_password": hashed_password
})
# Mark token as used
await token_repo.mark_token_as_used(str(reset_token_obj.id))
# Commit transaction
await session.commit()
logger.info(f"Password successfully reset for user: {user.email}")
return True
except ValueError:
# Re-raise value errors (validation errors)
raise
except Exception as e:
logger.error(f"Password reset failed: {str(e)}", exc_info=True)
return False
# Import database manager for singleton instance
from app.core.database import database_manager
# Import required modules for the password reset functionality
from app.repositories.password_reset_repository import PasswordResetTokenRepository
from shared.clients.notification_client import NotificationServiceClient
# Singleton instance for dependency injection
auth_service = AuthService(database_manager=database_manager)