from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.orm import Session from app.core.security import create_access_token from app.db import get_db from app.deps import get_current_user from app.integrations.sms_client import SmsClient from app.models import Permission, User from app.schemas.auth import CurrentUserResponse, LoginRequest, SmsCodeRequest, TokenResponse from app.services.audit_service import write_audit from app.services.user_service import get_or_create_login_user router = APIRouter() def _build_current_user(db: Session, user: User) -> CurrentUserResponse: if user.is_superuser: permissions = sorted(db.scalars(select(Permission.code)).all()) else: permissions = sorted({ p.code for role in user.roles for p in role.permissions }) return CurrentUserResponse( id=user.id, phone=user.phone, name=user.name, department=user.department, unit_id=user.unit_id, unit_name=user.unit.name if user.unit else None, status=user.status, roles=[role.code for role in user.roles], permissions=permissions, is_superuser=user.is_superuser, ) @router.post("/sms-code") def send_sms_code(payload: SmsCodeRequest) -> dict: code = "123456" SmsClient().send_code(payload.phone, code) return {"message": "验证码已发送", "mock_code": code} @router.post("/login", response_model=TokenResponse) def login(payload: LoginRequest, db: Session = Depends(get_db)) -> TokenResponse: if payload.code != "123456": raise HTTPException(status_code=400, detail="验证码错误或已过期") user = get_or_create_login_user(db, payload.phone) if user.status != "active": raise HTTPException(status_code=403, detail="账号已禁用") write_audit(db, "auth.login", actor_id=user.id, target_type="user", target_id=str(user.id)) db.commit() db.refresh(user) return TokenResponse( access_token=create_access_token(str(user.id)), user=_build_current_user(db, user), ) @router.post("/logout") def logout(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)) -> dict: write_audit(db, "auth.logout", actor_id=current_user.id, target_type="user", target_id=str(current_user.id)) db.commit() return {"message": "已退出"} @router.get("/me", response_model=CurrentUserResponse) def me( current_user: User = Depends(get_current_user), db: Session = Depends(get_db), ) -> CurrentUserResponse: return _build_current_user(db, current_user)