70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
"""회원가입, 이메일 인증 및 회사 검색 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",
|
|
}
|