finai/backend/app/api/auth.py

76 lines
2.6 KiB
Python

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)