Add subcription feature 5
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user