Files
shaguabijia-app-server/app/repositories/user.py
T
marco e8bd12cc1f feat(onboarding): force_onboarding 改设备维度 + admin 设备管理 + status 查询
废弃 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>
2026-06-12 00:51:47 +08:00

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()