51521fc0dd
- 微信支付从 APIv3 降级为 APIv2(MD5/XML) - 积分系统:充值下单、微信回调、消费冻结/结算/退款 - SMS B2M 短信验证码服务 - 双 Token 认证(Access 30min + Refresh 30days) - SSE 单设备踢人 - 用户设备管理、积分账户模型 - Alembic 迁移脚本
92 lines
2.3 KiB
Python
92 lines
2.3 KiB
Python
"""
|
||
用户 CRUD 操作
|
||
==============
|
||
|
||
用户认证相关的数据访问。
|
||
"""
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.crud.base import CRUDBase
|
||
from app.models.user import User
|
||
|
||
|
||
class UserCRUD(CRUDBase[User]):
|
||
"""用户数据访问对象"""
|
||
|
||
def __init__(self) -> None:
|
||
super().__init__(User)
|
||
|
||
async def get_by_mobile(self, db: AsyncSession, *, mobile: str) -> User | None:
|
||
"""根据手机号获取用户"""
|
||
result = await db.execute(select(User).where(User.mobile == mobile))
|
||
return result.scalar_one_or_none()
|
||
|
||
async def get_or_create_by_mobile(
|
||
self, db: AsyncSession, *, mobile: str, nickname: str | None = None, source: str = "unknown"
|
||
) -> User:
|
||
"""
|
||
根据手机号获取或创建用户
|
||
|
||
Returns:
|
||
已存在或新创建的用户
|
||
"""
|
||
user = await self.get_by_mobile(db, mobile=mobile)
|
||
|
||
if user is None:
|
||
# 创建新用户
|
||
user = await self.create(
|
||
db,
|
||
obj_in={
|
||
"mobile": mobile,
|
||
"nickname": nickname or f"用户_{mobile[-4:]}",
|
||
"source": source,
|
||
},
|
||
)
|
||
|
||
return user
|
||
|
||
async def update_login_info(
|
||
self, db: AsyncSession, *, user_id: str, ip: str | None = None
|
||
) -> User | None:
|
||
"""
|
||
更新用户最后登录信息
|
||
"""
|
||
from datetime import UTC, datetime
|
||
|
||
user = await self.get(db, id=user_id)
|
||
if user is None:
|
||
return None
|
||
|
||
user.last_login_at = datetime.now(UTC)
|
||
if ip:
|
||
user.last_login_ip = ip
|
||
|
||
await db.commit()
|
||
await db.refresh(user)
|
||
return user
|
||
|
||
async def update_extra(
|
||
self, db: AsyncSession, *, user_id: str, extra: dict
|
||
) -> bool:
|
||
"""
|
||
原子更新用户 extra 字段(JSONB)
|
||
|
||
使用 SQLAlchemy 的 update 语句避免读-改-写的竞态条件。
|
||
"""
|
||
from sqlalchemy import update
|
||
|
||
stmt = (
|
||
update(User)
|
||
.where(User.id == user_id)
|
||
.values(extra=extra)
|
||
)
|
||
result = await db.execute(stmt)
|
||
await db.commit()
|
||
return result.rowcount > 0
|
||
|
||
|
||
# 导出实例
|
||
user = UserCRUD()
|