This commit is contained in:
fengchuanhn@gmail.com
2026-05-22 14:59:33 +08:00
parent 3c91a52aff
commit 5aafba8eb9
5 changed files with 40 additions and 2 deletions

View File

@@ -89,6 +89,24 @@ async def update_user(
) )
@router.post("/{user_id}/clear-device-serial", response_model=ApiResponse[AdminUserOut])
async def clear_device_serial(
user_id: int,
_admin: AdminUser,
db: DbSession,
) -> ApiResponse[AdminUserOut]:
try:
user = await admin_user_service.clear_device_serial(db, user_id)
except admin_user_service.AdminUserError as exc:
return ApiResponse(ok=False, message=exc.message)
return ApiResponse(
ok=True,
message="设备已解绑",
data=AdminUserOut.model_validate(user),
)
@router.delete("/{user_id}", response_model=ApiResponse[None]) @router.delete("/{user_id}", response_model=ApiResponse[None])
async def delete_user( async def delete_user(
user_id: int, user_id: int,

View File

@@ -25,4 +25,4 @@ class User(Base):
) )
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
device_serial: Mapped[str] = mapped_column(String(255), default="", server_default="") device_serial: Mapped[str] = mapped_column(String(255), default="", server_default="",index=True)

View File

@@ -13,6 +13,7 @@ class AdminUserOut(BaseModel):
oem_id: int | None = None oem_id: int | None = None
agent_id: int | None = None agent_id: int | None = None
vip_end_time: datetime | None = None vip_end_time: datetime | None = None
device_serial: str = ""
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime

View File

@@ -163,6 +163,19 @@ async def update_user(
return user return user
async def clear_device_serial(db: AsyncSession, user_id: int) -> User:
"""管理员解绑:将用户 device_serial 置空。"""
user = await db.get(User, user_id)
if user is None:
raise AdminUserError("用户不存在")
if not (user.device_serial or "").strip():
raise AdminUserError("该用户未绑定设备")
user.device_serial = ""
await db.flush()
await db.refresh(user)
return user
async def delete_user(db: AsyncSession, oem: User, user_id: int, *, actor_id: int) -> None: async def delete_user(db: AsyncSession, oem: User, user_id: int, *, actor_id: int) -> None:
if user_id == actor_id: if user_id == actor_id:
raise AdminUserError("不能删除当前登录账号") raise AdminUserError("不能删除当前登录账号")

View File

@@ -66,12 +66,18 @@ async def register_user(
if existing is not None: if existing is not None:
raise AuthError("用户名已存在") raise AuthError("用户名已存在")
serial = _normalize_device_serial(device_serial)
if serial:
bound = await db.scalar(select(User).where(User.device_serial == serial))
if bound is not None:
raise AuthError("该电脑已绑定其它用户")
user = User( user = User(
username=username, username=username,
password_hash=hash_password(password), password_hash=hash_password(password),
role_id=0, role_id=0,
phone=None, phone=None,
device_serial=_normalize_device_serial(device_serial), device_serial=serial,
) )
db.add(user) db.add(user)
await db.flush() await db.flush()