49379fd045
- /api/v1/user: PATCH 改昵称、POST 上传头像、DELETE 注销账号(软删除+匿名化) - /api/v1/feedback: 提交反馈(内容/联系方式/截图入库) - 新增 media 模块(图片落盘+魔数校验)+ /media 静态服务 - feedback 表 + Alembic 迁移(部署需 alembic upgrade head) Co-Authored-By: Claude Opus 4.7 <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()
|