auth-service / app /services /customer_services.py
Prabha-AIMLOPS's picture
Upload 24 files
2cd3d4e verified
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