"""회원가입, 이메일 인증 및 회사 검색 API.""" from datetime import datetime from fastapi import APIRouter, HTTPException, Query from common_util.common_util_auth import generate_otp, hash_password, verify_password from common_util.common_util_auth_repository import ( company_master_email, complete_registration, consume_otp, create_registration, get_active_otp, get_user_by_email, replace_otp, search_companies, ) from common_util.common_util_email import send_email_background from common_util.common_util_email_templates import join_request_email, otp_email from .A07_Register_Schema import RegisterRequest, RegisterVerifyRequest router = APIRouter(prefix="/api/auth", tags=["Authentication"]) @router.get("/companies") async def find_companies(q: str = Query(min_length=1, max_length=100)): return {"status": "success", "companies": await search_companies(q.strip())} @router.post("/register/request", status_code=202) async def request_registration(payload: RegisterRequest): email = str(payload.email).lower() if await get_user_by_email(email): raise HTTPException(status_code=409, detail="이미 등록된 이메일입니다.") data = payload.model_dump() data["email"] = email user_id = await create_registration(data, hash_password(payload.password)) code = generate_otp() await replace_otp(user_id, "REGISTER", hash_password(code)) subject, html = otp_email(code, "회원가입") send_email_background(email, subject, html) return {"status": "success", "message": "인증 코드를 발송했습니다."} @router.post("/register/verify") async def verify_registration(payload: RegisterVerifyRequest): user = await get_user_by_email(str(payload.email).lower()) if not user or user["status"] != "PENDING_EMAIL": raise HTTPException(status_code=400, detail="인증 대기 중인 가입 요청이 없습니다.") otp = await get_active_otp(user["id"], "REGISTER") if ( not otp or otp["expires_at"] < datetime.utcnow() or not verify_password(payload.otp_code, otp["otp_hash"]) ): raise HTTPException(status_code=400, detail="인증 코드가 유효하지 않습니다.") await consume_otp(otp["id"]) await complete_registration(user["id"], bool(user["is_master"])) if not user["is_master"]: master_email = await company_master_email(user["company_id"]) if master_email: subject, html = join_request_email(user["name"], user["email"]) send_email_background(master_email, subject, html) return { "status": "success", "account_status": "ACTIVE" if user["is_master"] else "PENDING", }