Files
shaguabijia-app-server/app/api/v1/device_profile.py
T
unknown afc55ab910 feat(device): 新增设备信息表 device + 上报接口
- 新建 device 设备表(设备/系统信息 + 网络/时区/模拟器/位置 + 关联用户 + 状态/时间戳),
  以客户端 device_id 唯一标识;登录后回填 user_id,游客态可空
- 原 device 模型改名 device_liveness(实为无障碍存活表),腾出 device 名给新表并保持
  表名与实体名一致;同步更新 __init__ / repositories / admin queries / 文档引用
- 新增 POST /api/v1/device/report:软鉴权(带 JWT 绑用户、游客也收),按 device_id upsert;
  设备信息非空才覆盖,位置 latitude/longitude 整字段覆盖含清空(以本次上报实际为准)
- 新增 alembic migration bb47051068c8 建 device 表(裁掉 autogenerate 带出的无关表漂移)
- 补 /device/report 端点与 upsert 单元测试 4 例
2026-07-17 09:46:59 +08:00

52 lines
1.7 KiB
Python

"""设备档案上报 endpoint(device 表)。
POST /api/v1/device/report — 客户端上报设备当前信息,按 device_id upsert 到 device 表。
软鉴权:带合法 Bearer → 设备关联到该用户;游客态(无 token)也接受,user_id 暂空。
注意与 /api/v1/device/register(app/api/v1/device.py)区分:那个是无障碍存活注册,写
device_liveness 表、硬鉴权;本端点是设备信息档案,写 device 表、软鉴权。
"""
from __future__ import annotations
import logging
from fastapi import APIRouter, Request
from app.api.deps import DbSession, OptionalUser
from app.repositories import device_profile as device_profile_repo
from app.schemas.device_profile import DeviceReportOut, DeviceReportRequest
logger = logging.getLogger("shagua.device_profile")
router = APIRouter(prefix="/api/v1/device", tags=["device"])
def _client_ip(request: Request) -> str | None:
"""客户端 IP:生产经 nginx 反代优先 X-Forwarded-For 第一段,否则直连 IP。"""
xff = request.headers.get("x-forwarded-for")
if xff:
return xff.split(",")[0].strip()
return request.client.host if request.client else None
@router.post("/report", response_model=DeviceReportOut, summary="上报设备信息(设备档案 upsert)")
def report_device(
req: DeviceReportRequest,
request: Request,
user: OptionalUser,
db: DbSession,
) -> DeviceReportOut:
device = device_profile_repo.upsert_device(
db,
req,
user_id=user.id if user else None,
last_ip=_client_ip(request),
)
logger.info(
"device report device_id=%s user_id=%s has_loc=%s",
req.device_id,
device.user_id,
req.latitude is not None,
)
return DeviceReportOut()