e8bd12cc1f
废弃 force_onboarding(运营按用户强制引导,客户端不认——被 onboarding_completed 压过), 改用 onboarding_completion(设备+账号 维度),admin 直接增删该表记录控制重走。 - 删 force_onboarding: User 列 + auth/admin schema + admin 接口 + mutations + repo clear + /onboarding/complete 调用 + 3 测试;新增 alembic 迁移删列 - admin 设备管理: 列设备(按 device 聚合) / 重置单设备 / 全部重置(清 onboarding_completion) - 新增 GET /api/v1/user/onboarding/status: 客户端已登录启动查"本设备是否要重走引导" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
77 lines
2.0 KiB
Python
77 lines
2.0 KiB
Python
"""user 表的 CRUD 工具函数。
|
|
|
|
业务策略 = "注册即登录":phone 不存在则 insert,存在则更新 last_login_at。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.user import User
|
|
|
|
|
|
def get_user_by_id(db: Session, user_id: int) -> User | None:
|
|
return db.get(User, user_id)
|
|
|
|
|
|
def get_user_by_phone(db: Session, phone: str) -> User | None:
|
|
stmt = select(User).where(User.phone == phone)
|
|
return db.execute(stmt).scalar_one_or_none()
|
|
|
|
|
|
def upsert_user_for_login(
|
|
db: Session,
|
|
*,
|
|
phone: str,
|
|
register_channel: str,
|
|
) -> User:
|
|
"""登录入口统一调:有则更新 last_login_at,无则新建。
|
|
|
|
返回 commit 后的 user。调用方拿到 user.id 直接签 JWT。
|
|
"""
|
|
user = get_user_by_phone(db, phone)
|
|
now = datetime.now(timezone.utc)
|
|
if user is None:
|
|
user = User(
|
|
phone=phone,
|
|
register_channel=register_channel,
|
|
last_login_at=now,
|
|
)
|
|
db.add(user)
|
|
else:
|
|
user.last_login_at = now
|
|
# 被禁用的账号被尝试登录时,不自动启用,直接抛(在调用方处理)
|
|
db.commit()
|
|
db.refresh(user)
|
|
return user
|
|
|
|
|
|
def update_nickname(db: Session, user: User, *, nickname: str) -> User:
|
|
user.nickname = nickname
|
|
db.commit()
|
|
db.refresh(user)
|
|
return user
|
|
|
|
|
|
def set_avatar_url(db: Session, user: User, *, avatar_url: str) -> User:
|
|
user.avatar_url = avatar_url
|
|
db.commit()
|
|
db.refresh(user)
|
|
return user
|
|
|
|
|
|
def soft_delete_account(db: Session, user: User) -> None:
|
|
"""注销账号:软删除 + 匿名化。
|
|
|
|
把 phone 改成 `deleted_<id>` 释放唯一约束,允许同号码重新注册成全新账号;
|
|
清空 PII(昵称/头像),保留行用于审计。status=deleted 后将无法再登录该行
|
|
(登录接口校验 status==active)。
|
|
"""
|
|
user.status = "deleted"
|
|
user.phone = f"deleted_{user.id}"
|
|
user.nickname = None
|
|
user.avatar_url = None
|
|
db.commit()
|