mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-05-11 18:10:10 +08:00
191 lines
6.6 KiB
Python
191 lines
6.6 KiB
Python
from typing import List
|
|
|
|
from fastapi import HTTPException
|
|
|
|
from domain.auth.service import AuthService
|
|
from domain.permission.service import PermissionService
|
|
from models.database import Role, UserAccount, UserRole
|
|
|
|
from .types import UserCreate, UserDetail, UserInfo, UserUpdate
|
|
|
|
|
|
class UserService:
|
|
"""用户管理服务"""
|
|
|
|
@classmethod
|
|
async def get_all_users(cls) -> List[UserInfo]:
|
|
users = await UserAccount.all().order_by("id")
|
|
return [
|
|
UserInfo(
|
|
id=u.id,
|
|
username=u.username,
|
|
email=u.email,
|
|
full_name=u.full_name,
|
|
disabled=u.disabled,
|
|
is_admin=u.is_admin,
|
|
created_at=u.created_at,
|
|
last_login=u.last_login,
|
|
)
|
|
for u in users
|
|
]
|
|
|
|
@classmethod
|
|
async def get_user(cls, user_id: int) -> UserDetail:
|
|
user = await UserAccount.get_or_none(id=user_id).prefetch_related("created_by")
|
|
if not user:
|
|
raise HTTPException(404, detail="用户不存在")
|
|
|
|
user_roles = await UserRole.filter(user_id=user_id).prefetch_related("role")
|
|
roles = [ur.role.name for ur in user_roles]
|
|
|
|
created_by_username = None
|
|
if user.created_by_id:
|
|
creator = await UserAccount.get_or_none(id=user.created_by_id)
|
|
if creator:
|
|
created_by_username = creator.username
|
|
|
|
return UserDetail(
|
|
id=user.id,
|
|
username=user.username,
|
|
email=user.email,
|
|
full_name=user.full_name,
|
|
disabled=user.disabled,
|
|
is_admin=user.is_admin,
|
|
created_at=user.created_at,
|
|
last_login=user.last_login,
|
|
roles=roles,
|
|
created_by_username=created_by_username,
|
|
)
|
|
|
|
@classmethod
|
|
async def get_users_by_role(cls, role_id: int) -> List[UserInfo]:
|
|
role = await Role.get_or_none(id=role_id)
|
|
if not role:
|
|
raise HTTPException(404, detail="角色不存在")
|
|
|
|
user_roles = await UserRole.filter(role_id=role_id).prefetch_related("user")
|
|
users = [ur.user for ur in user_roles if ur.user]
|
|
users.sort(key=lambda u: u.id)
|
|
return [
|
|
UserInfo(
|
|
id=u.id,
|
|
username=u.username,
|
|
email=u.email,
|
|
full_name=u.full_name,
|
|
disabled=u.disabled,
|
|
is_admin=u.is_admin,
|
|
created_at=u.created_at,
|
|
last_login=u.last_login,
|
|
)
|
|
for u in users
|
|
]
|
|
|
|
@classmethod
|
|
async def create_user(cls, data: UserCreate, creator_id: int) -> UserDetail:
|
|
existing = await UserAccount.get_or_none(username=data.username)
|
|
if existing:
|
|
raise HTTPException(400, detail="用户名已存在")
|
|
|
|
if data.email:
|
|
existing_email = await UserAccount.get_or_none(email=data.email)
|
|
if existing_email:
|
|
raise HTTPException(400, detail="邮箱已被使用")
|
|
|
|
hashed_password = AuthService.get_password_hash(data.password)
|
|
user = await UserAccount.create(
|
|
username=data.username,
|
|
email=data.email,
|
|
full_name=data.full_name,
|
|
hashed_password=hashed_password,
|
|
disabled=data.disabled,
|
|
is_admin=data.is_admin,
|
|
created_by_id=creator_id,
|
|
)
|
|
|
|
if data.role_ids:
|
|
for role_id in data.role_ids:
|
|
role = await Role.get_or_none(id=role_id)
|
|
if role:
|
|
await UserRole.create(user_id=user.id, role_id=role_id)
|
|
|
|
return await cls.get_user(user.id)
|
|
|
|
@classmethod
|
|
async def update_user(cls, user_id: int, data: UserUpdate, operator_id: int) -> UserDetail:
|
|
user = await UserAccount.get_or_none(id=user_id)
|
|
if not user:
|
|
raise HTTPException(404, detail="用户不存在")
|
|
|
|
if data.is_admin is not None and user_id == operator_id:
|
|
raise HTTPException(400, detail="不能修改自己的管理员状态")
|
|
|
|
if data.email is not None:
|
|
existing = await UserAccount.filter(email=data.email).exclude(id=user_id).first()
|
|
if existing:
|
|
raise HTTPException(400, detail="邮箱已被使用")
|
|
user.email = data.email
|
|
|
|
if data.full_name is not None:
|
|
user.full_name = data.full_name
|
|
|
|
if data.password is not None:
|
|
user.hashed_password = AuthService.get_password_hash(data.password)
|
|
|
|
if data.is_admin is not None:
|
|
user.is_admin = data.is_admin
|
|
|
|
if data.disabled is not None:
|
|
if user_id == operator_id and data.disabled:
|
|
raise HTTPException(400, detail="不能禁用自己")
|
|
user.disabled = data.disabled
|
|
|
|
await user.save()
|
|
|
|
PermissionService.clear_cache(user_id)
|
|
return await cls.get_user(user_id)
|
|
|
|
@classmethod
|
|
async def delete_user(cls, user_id: int, operator_id: int) -> None:
|
|
if user_id == operator_id:
|
|
raise HTTPException(400, detail="不能删除自己")
|
|
|
|
user = await UserAccount.get_or_none(id=user_id)
|
|
if not user:
|
|
raise HTTPException(404, detail="用户不存在")
|
|
|
|
await UserRole.filter(user_id=user_id).delete()
|
|
await user.delete()
|
|
PermissionService.clear_cache(user_id)
|
|
|
|
@classmethod
|
|
async def set_user_roles(cls, user_id: int, role_ids: List[int]) -> List[str]:
|
|
user = await UserAccount.get_or_none(id=user_id)
|
|
if not user:
|
|
raise HTTPException(404, detail="用户不存在")
|
|
|
|
roles = await Role.filter(id__in=role_ids)
|
|
valid_role_ids = {r.id for r in roles}
|
|
invalid_ids = set(role_ids) - valid_role_ids
|
|
if invalid_ids:
|
|
raise HTTPException(400, detail=f"无效的角色ID: {invalid_ids}")
|
|
|
|
await UserRole.filter(user_id=user_id).delete()
|
|
for role_id in role_ids:
|
|
await UserRole.create(user_id=user_id, role_id=role_id)
|
|
|
|
PermissionService.clear_cache(user_id)
|
|
return [r.name for r in roles if r.id in role_ids]
|
|
|
|
@classmethod
|
|
async def remove_user_role(cls, user_id: int, role_id: int) -> List[str]:
|
|
user = await UserAccount.get_or_none(id=user_id)
|
|
if not user:
|
|
raise HTTPException(404, detail="用户不存在")
|
|
|
|
await UserRole.filter(user_id=user_id, role_id=role_id).delete()
|
|
PermissionService.clear_cache(user_id)
|
|
|
|
user_roles = await UserRole.filter(user_id=user_id).prefetch_related("role")
|
|
return [ur.role.name for ur in user_roles]
|
|
|