Spaces:
Sleeping
Sleeping
| import re | |
| import logging | |
| from app.repositories.cache_repository import get_otp, set_otp | |
| from app.repositories.db_repository import get_customer_by_email, get_customer_by_mobile, save_customer | |
| from app.models.customer import CustomerRegister | |
| from app.utils.auth_utils import validate_email, validate_mobile | |
| import random | |
| logger = logging.getLogger(__name__) | |
| async def validate_email_mobile(email: str, mobile: str) -> dict: | |
| """ | |
| Validate email and mobile format and check if they already exist in the database. | |
| Args: | |
| email (str): The email address to validate. | |
| mobile (str): The mobile number to validate. | |
| Returns: | |
| dict: Validation result with consolidated error messages or success message. | |
| """ | |
| errors = [] | |
| # Validate email format | |
| if not validate_email(email): | |
| errors.append("Invalid email format") | |
| # Validate mobile format | |
| if not validate_mobile(mobile): | |
| errors.append("Invalid mobile number format") | |
| # Check if email already exists in the database | |
| existing_email = await get_customer_by_email(email) | |
| if existing_email: | |
| errors.append("Email is already registered") | |
| # Check if mobile already exists in the database | |
| existing_mobile = await get_customer_by_mobile(mobile) | |
| if existing_mobile: | |
| errors.append("Mobile number is already registered") | |
| # Return errors if any | |
| if errors: | |
| return {"status": "error", "errors": errors} | |
| else: | |
| # Send verification emails and SMS if no errors | |
| await send_email_verification(email) | |
| await send_sms_verification(mobile) | |
| # If all validations pass | |
| return {"status": "success", "message": "Email and mobile are valid"} | |
| async def save_customer_to_db(user: CustomerRegister) -> dict: | |
| """ | |
| Save customer details to MongoDB after checking for duplicates. | |
| Args: | |
| user (CustomerRegister): The customer details to save. | |
| Returns: | |
| dict: Success message or error message if email or mobile already exists. | |
| """ | |
| # Check if email already exists in the database | |
| existing_email = await get_customer_by_email(user.email) | |
| if existing_email: | |
| return {"status": "error", "message": "Email is already registered"} | |
| # Check if mobile already exists in the database | |
| existing_mobile = await get_customer_by_mobile(user.mobile) | |
| if existing_mobile: | |
| return {"status": "error", "message": "Mobile number is already registered"} | |
| # Save customer details to the database | |
| await save_customer(user.dict()) | |
| return {"status": "success", "message": "Customer registered successfully"} | |
| async def send_email_verification(email: str): | |
| """ | |
| Send an email verification link or code. | |
| Args: | |
| email (str): The email address to send the verification to. | |
| """ | |
| # Implement your email sending logic here | |
| # Generate a 6-digit OTP | |
| otp = ''.join(random.choices("0123456789", k=6)) | |
| # Store OTP in cache with a 15-minute expiry | |
| await set_otp(email, {"otp": otp, "expiry_duration": 15 * 60}) # 15 minutes in seconds | |
| # Send the OTP to the email address | |
| # (You would typically use an email service here) | |
| # For demonstration, we'll just log the OTP | |
| logger.info("Sending email verification to: %s with OTP: %s", email, otp) | |
| logger.info("Sending email verification to: %s", email) | |
| async def send_sms_verification(mobile: str): | |
| """ | |
| Send an SMS verification code. | |
| Args: | |
| mobile (str): The mobile number to send the verification to. | |
| """ | |
| # Implement your SMS sending logic here | |
| # Generate a 6-digit OTP | |
| otp = ''.join(random.choices("0123456789", k=6)) | |
| # Store OTP in cache with a 15-minute expiry | |
| await set_otp(mobile, {"otp": otp, "expiry_duration": 15 * 60}) # 15 minutes in seconds | |
| # Send the OTP to the mobile number | |
| # (You would typically use an SMS service here) | |
| # For demonstration, we'll just log the OTP | |
| logger.info("Sending SMS verification to: %s with OTP: %s", mobile, otp) | |
| logger.info("Sending SMS verification to: %s", mobile) | |
| async def verify_otp_and_save_customer(user: CustomerRegister) -> dict: | |
| """ | |
| Verify SMS OTP and email OTP, and save the complete customer object in the database. | |
| Args: | |
| user (CustomerRegister): The complete customer object including email, mobile, and OTPs. | |
| Returns: | |
| dict: Result indicating success or failure. | |
| """ | |
| errors = [] | |
| # Retrieve OTPs from cache | |
| email_otp_data = await get_otp(user.email) | |
| mobile_otp_data = await get_otp(user.mobile) | |
| # Verify email OTP | |
| if not email_otp_data or email_otp_data["otp"] != user.email_ver_code: | |
| errors.append("Invalid or expired email OTP") | |
| # Verify mobile OTP | |
| if not mobile_otp_data or mobile_otp_data["otp"] != user.mobile_ver_code: | |
| errors.append("Invalid or expired mobile OTP") | |
| # Return errors if any | |
| if errors: | |
| return {"status": "error", "errors": errors} | |
| # Save the complete customer object to the database | |
| customer_data = user.dict() | |
| customer_data["status"] = "completed" # Update status to completed | |
| await save_customer(customer_data) | |
| return {"status": "success", "message": "Customer successfully registered and verified"} | |
| async def get_otp_from_cache(key: str) -> dict: | |
| """ | |
| Retrieve OTP data for the given key (email or mobile) from the cache. | |
| Args: | |
| key (str): The email or mobile number to retrieve the OTP for. | |
| Returns: | |
| dict: The OTP data if found, or None if not found. | |
| """ | |
| try: | |
| # Call the get_otp function from the cache repository | |
| otp_data = await get_otp(key) | |
| return otp_data | |
| except Exception as e: | |
| # Log the error and re-raise it | |
| logger.error(f"Failed to retrieve OTP for key {key}: {e}") | |
| raise |