from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.orm import Session from app.db.session import get_db from app.models.org import User from app.schemas.database import ( AuthChangePasswordRequest, AuthLoginKeyResponse, AuthLoginRequest, AuthResetPasswordRequest, AuthSession, LoginUser, ) from app.services.auth import ( build_login_user, get_current_auth_context, hash_password, login_with_password, require_system_admin, verify_password, ) from app.services.login_crypto import decrypt_login_password, get_login_public_key router = APIRouter() @router.get("/login-key", response_model=AuthLoginKeyResponse) def login_key() -> AuthLoginKeyResponse: return AuthLoginKeyResponse(**get_login_public_key().__dict__) @router.post("/login", response_model=AuthSession) def login(payload: AuthLoginRequest, db: Session = Depends(get_db)) -> AuthSession: password = decrypt_login_password(payload.password_ciphertext, payload.login_key_id) return login_with_password(db, payload.username, password) @router.get("/me", response_model=LoginUser) def profile(context=Depends(get_current_auth_context)) -> LoginUser: return build_login_user(context) @router.post("/password/change") def change_password( payload: AuthChangePasswordRequest, context=Depends(get_current_auth_context), db: Session = Depends(get_db), ) -> dict[str, str]: user = db.get(User, context.user.id) if not user: raise HTTPException(status_code=404, detail="当前用户不存在") if not verify_password(payload.old_password, user.password_hash): raise HTTPException(status_code=400, detail="原密码不正确") if verify_password(payload.new_password, user.password_hash): raise HTTPException(status_code=400, detail="新密码不能与原密码相同") user.password_hash = hash_password(payload.new_password) db.add(user) db.commit() return {"message": "密码已修改"} @router.post("/password/reset") def reset_password( payload: AuthResetPasswordRequest, context=Depends(require_system_admin), db: Session = Depends(get_db), ) -> dict[str, str]: user = db.scalar(select(User).where(User.username == payload.username)) if not user: raise HTTPException(status_code=404, detail="账号不存在") user.password_hash = hash_password(payload.new_password) db.add(user) db.commit() return {"message": f"账号 {payload.username} 密码已重置"}