Files
HSAP/platform/as_platform/api/auth_routes.py
Chengfang Lu 7c43b44c57 feat: initial HSAP platform
Huaxu Sentinel Active Safety Platform with embedded algorithm code,
Docker Compose setup, and vendored dataset scaffolds for clone-and-run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 16:59:59 +08:00

99 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""认证与用户管理 API。"""
from __future__ import annotations
from typing import Annotated, Any
from urllib.parse import urlencode
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import RedirectResponse
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
from as_platform.auth.deps import get_current_user, require_permission
from as_platform.auth.feishu import build_authorize_url, exchange_code, is_feishu_configured, verify_state
from as_platform.auth.jwt import create_access_token
from as_platform.auth.users import get_or_create_dev_user, list_users, set_user_roles, upsert_feishu_user
from as_platform.config import DEV_AUTH_ENABLED, FRONTEND_URL
from as_platform.db.engine import get_db
from as_platform.db.init_db import user_to_dict
from as_platform.db.models import User
router = APIRouter(prefix="/api/v1/auth", tags=["auth"])
class DevLoginBody(BaseModel):
name: str = "开发用户"
class SetRolesBody(BaseModel):
role_codes: list[str] = Field(default_factory=list)
@router.get("/config")
def auth_config() -> dict[str, Any]:
return {
"feishu_enabled": is_feishu_configured(),
"dev_auth_enabled": DEV_AUTH_ENABLED and not is_feishu_configured(),
}
@router.get("/feishu/authorize")
def feishu_authorize():
if not is_feishu_configured():
raise HTTPException(503, "未配置飞书应用,请设置 FEISHU_APP_ID / FEISHU_APP_SECRET")
url, _ = build_authorize_url()
return RedirectResponse(url)
@router.get("/feishu/callback")
def feishu_callback(code: str, state: str, db: Annotated[Session, Depends(get_db)]):
if not verify_state(state):
raise HTTPException(400, "无效的 state请重新登录")
try:
info = exchange_code(code)
except Exception as e:
raise HTTPException(502, f"飞书登录失败: {e}") from e
user = upsert_feishu_user(db, info)
db.commit()
token = create_access_token(user.id)
# 避免 BrowserRouter 直达路径 404统一回根路径并附带 token
qs = urlencode({"token": token})
return RedirectResponse(f"{FRONTEND_URL}/?{qs}")
@router.post("/dev/login")
def dev_login(body: DevLoginBody, db: Annotated[Session, Depends(get_db)]):
if not DEV_AUTH_ENABLED or is_feishu_configured():
raise HTTPException(403, "开发登录未启用")
user = get_or_create_dev_user(db, body.name)
db.commit()
token = create_access_token(user.id)
return {"access_token": token, "user": user_to_dict(user)}
@router.get("/me")
def auth_me(user: Annotated[User, Depends(get_current_user)]):
return user_to_dict(user)
@router.get("/users")
def auth_list_users(
_user: Annotated[User, Depends(require_permission("admin:users"))],
db: Annotated[Session, Depends(get_db)],
):
return {"items": [user_to_dict(u) for u in list_users(db)]}
@router.put("/users/{user_id}/roles")
def auth_set_roles(
user_id: int,
body: SetRolesBody,
_user: Annotated[User, Depends(require_permission("admin:users"))],
db: Annotated[Session, Depends(get_db)],
):
user = set_user_roles(db, user_id, body.role_codes)
if not user:
raise HTTPException(404, "用户不存在")
db.commit()
return user_to_dict(user)