- 登录链路改为用户名 + 密码 + 短信验证码 + DCAuth v2 设备签名 - 新增 login_sms_codes / user_devices / device_challenges 三张表,迁移 0063/0064 - 设备绑定只比对 deviceId + publicKey,每账号一个 active 设备,管理员可重置 - 保留未绑定手机号账号的密码登录兜底,绑定后强制安全登录 - 登录页与用户管理页支持验证码、DCAuth 轮询、手机号绑定与设备重置
40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
"""DCAuth v2 客户端协议入口。
|
|
|
|
客户端(DCAuth.exe / dcauth)把 authorize 路径硬编码为
|
|
``POST {apiBase}/api/dcauth/authorize``,因此这里的路径不能改。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, Header, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..database import get_db
|
|
from ..schemas import DeviceAuthorizeRequest
|
|
from ..services.dc_auth_service import (
|
|
authorize_device,
|
|
get_challenge_status,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/dcauth", tags=["设备认证"])
|
|
|
|
|
|
@router.post("/authorize")
|
|
def authorize(
|
|
payload: DeviceAuthorizeRequest,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
result = authorize_device(db, payload.model_dump(by_alias=True))
|
|
return {"success": True, **result}
|
|
|
|
|
|
@router.get("/challenge/{challenge_id}/status")
|
|
def challenge_status(
|
|
challenge_id: str,
|
|
poll_token: str | None = Query(None, alias="pollToken"),
|
|
header_poll_token: str | None = Header(None, alias="X-Poll-Token"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
token = header_poll_token or poll_token or ""
|
|
return get_challenge_status(db, challenge_id, token)
|