feat(auth): 账号唯一性+清理多余账号 —— 迁移0011加phone/微信openid非空部分唯一索引

- users.phone/wx_openid/wx_mini_openid/wx_unionid 各自唯一(非空部分唯一索引)
- 创建账号必生成ID(create用new_id);find_by_phone/find_by_wx 唯一校验
- cleanup_accounts.py 清理旧accounts已被users接管的重复账号;seed不再重复造账号、迁移后删旧行
This commit is contained in:
Pine
2026-08-25 22:47:27 +08:00
parent 8a00712750
commit c2f4c13ab3
4 changed files with 210 additions and 7 deletions
+24
View File
@@ -219,6 +219,30 @@ class UserRepository:
u = await self.session.get(User, user_id)
return _user_to_dict(u) if u else None
async def find_by_phone(self, phone: str) -> dict | None:
"""按已绑定手机号精准查找(唯一,非空;用户ID/登录名/手机号三者独立各唯一)。"""
p = (phone or "").strip()
if not p:
return None
u = await self.session.scalar(select(User).where(User.phone == p))
return _user_to_dict(u) if u else None
async def find_by_wx(self, *, openid: str = "", mini_openid: str = "") -> dict | None:
"""按微信身份(网页开放平台 openid / 小程序 openid)查找用户。"""
if mini_openid:
u = await self.session.scalar(
select(User).where(User.wx_mini_openid == mini_openid.strip()),
)
if u:
return _user_to_dict(u)
if openid:
u = await self.session.scalar(
select(User).where(User.wx_openid == openid.strip()),
)
if u:
return _user_to_dict(u)
return None
async def list(self) -> list[dict]:
return [_user_to_dict(u) for u in await self.session.scalars(select(User).order_by(User.created_at))]