# app/modules/tenancy/routes/api/email_verification.py """ Email verification API endpoints. Public endpoints (no auth required): - POST /resend-verification - Resend verification email """ import logging from fastapi import APIRouter, Depends, Request from pydantic import BaseModel from sqlalchemy.orm import Session from app.core.database import get_db from app.core.environment import should_use_secure_cookies from app.modules.tenancy.models.email_verification_token import ( EmailVerificationToken, # noqa: API-007 ) from app.modules.tenancy.services.user_auth_service import user_auth_service email_verification_api_router = APIRouter() logger = logging.getLogger(__name__) class ResendVerificationRequest(BaseModel): email: str class ResendVerificationResponse(BaseModel): message: str @email_verification_api_router.post( "/resend-verification", response_model=ResendVerificationResponse ) def resend_verification( request: Request, body: ResendVerificationRequest, db: Session = Depends(get_db), ): """ Resend email verification link. Always returns success to prevent email enumeration. """ user, plaintext_token = user_auth_service.request_verification_resend(db, body.email) if user and plaintext_token: try: scheme = "https" if should_use_secure_cookies() else "http" host = request.headers.get("host", "localhost:8000") verification_link = f"{scheme}://{host}/verify-email?token={plaintext_token}" from app.modules.messaging.services.email_service import EmailService email_service = EmailService(db) email_service.send_template( template_code="email_verification", to_email=user.email, to_name=user.username, language="en", variables={ "first_name": user.username, "verification_link": verification_link, "expiry_hours": str(EmailVerificationToken.TOKEN_EXPIRY_HOURS), "platform_name": "Orion", }, ) db.commit() logger.info(f"Verification email resent to {user.email}") except Exception as e: db.rollback() logger.error(f"Failed to resend verification email: {e}") # noqa: SEC021 else: logger.info(f"Resend verification requested for {body.email} (not found or already verified)") return ResendVerificationResponse( message="If an account exists with this email and is not yet verified, a verification link has been sent." )