mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 21:15:13 +00:00
Simplify the user info update business (#638)
This commit is contained in:
@@ -6,13 +6,11 @@ from fastapi import APIRouter, Depends, Path, Query, Request
|
||||
|
||||
from backend.app.admin.schema.user import (
|
||||
AddUserParam,
|
||||
AvatarParam,
|
||||
GetCurrentUserInfoWithRelationDetail,
|
||||
GetUserInfoWithRelationDetail,
|
||||
RegisterUserParam,
|
||||
ResetPasswordParam,
|
||||
UpdateUserParam,
|
||||
UpdateUserRoleParam,
|
||||
)
|
||||
from backend.app.admin.service.user_service import user_service
|
||||
from backend.common.pagination import DependsPagination, PageData, paging_data
|
||||
@@ -70,31 +68,6 @@ async def update_user(
|
||||
return response_base.fail()
|
||||
|
||||
|
||||
@router.put(
|
||||
'/{username}/role',
|
||||
summary='更新用户角色',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:user:role:edit')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_user_role(
|
||||
request: Request, username: Annotated[str, Path(description='用户名')], obj: UpdateUserRoleParam
|
||||
) -> ResponseModel:
|
||||
await user_service.update_roles(request=request, username=username, obj=obj)
|
||||
return response_base.success()
|
||||
|
||||
|
||||
@router.put('/{username}/avatar', summary='更新头像', dependencies=[DependsJwtAuth])
|
||||
async def update_avatar(
|
||||
request: Request, username: Annotated[str, Path(description='用户名')], avatar: AvatarParam
|
||||
) -> ResponseModel:
|
||||
count = await user_service.update_avatar(request=request, username=username, avatar=avatar)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='分页获取所有用户',
|
||||
|
||||
@@ -11,10 +11,8 @@ from sqlalchemy_crud_plus import CRUDPlus
|
||||
from backend.app.admin.model import Dept, Role, User
|
||||
from backend.app.admin.schema.user import (
|
||||
AddUserParam,
|
||||
AvatarParam,
|
||||
RegisterUserParam,
|
||||
UpdateUserParam,
|
||||
UpdateUserRoleParam,
|
||||
)
|
||||
from backend.common.security.jwt import get_hash_password
|
||||
from backend.utils.timezone import timezone
|
||||
@@ -97,14 +95,13 @@ class CRUDUser(CRUDPlus[User]):
|
||||
dict_obj.update({'salt': salt})
|
||||
new_user = self.model(**dict_obj)
|
||||
|
||||
role_list = []
|
||||
for role_id in obj.roles:
|
||||
role_list.append(await db.get(Role, role_id))
|
||||
new_user.roles.extend(role_list)
|
||||
stmt = select(Role).where(Role.id.in_(obj.roles))
|
||||
roles = await db.execute(stmt)
|
||||
new_user.roles = roles.scalars().all()
|
||||
|
||||
db.add(new_user)
|
||||
|
||||
async def update_userinfo(self, db: AsyncSession, input_user: int, obj: UpdateUserParam) -> int:
|
||||
async def update(self, db: AsyncSession, input_user: User, obj: UpdateUserParam) -> int:
|
||||
"""
|
||||
更新用户信息
|
||||
|
||||
@@ -113,36 +110,14 @@ class CRUDUser(CRUDPlus[User]):
|
||||
:param obj: 更新用户参数
|
||||
:return:
|
||||
"""
|
||||
return await self.update_model(db, input_user, obj)
|
||||
role_ids = obj.roles
|
||||
del obj.roles
|
||||
count = await self.update_model(db, input_user.id, obj)
|
||||
|
||||
@staticmethod
|
||||
async def update_role(db: AsyncSession, input_user: User, obj: UpdateUserRoleParam) -> None:
|
||||
"""
|
||||
更新用户角色
|
||||
|
||||
:param db: 数据库会话
|
||||
:param input_user: 用户对象
|
||||
:param obj: 更新角色参数
|
||||
:return:
|
||||
"""
|
||||
for i in list(input_user.roles):
|
||||
input_user.roles.remove(i)
|
||||
|
||||
role_list = []
|
||||
for role_id in obj.roles:
|
||||
role_list.append(await db.get(Role, role_id))
|
||||
input_user.roles.extend(role_list)
|
||||
|
||||
async def update_avatar(self, db: AsyncSession, input_user: int, avatar: AvatarParam) -> int:
|
||||
"""
|
||||
更新用户头像
|
||||
|
||||
:param db: 数据库会话
|
||||
:param input_user: 用户 ID
|
||||
:param avatar: 头像地址
|
||||
:return:
|
||||
"""
|
||||
return await self.update_model(db, input_user, {'avatar': str(avatar.url)})
|
||||
stmt = select(Role).where(Role.id.in_(role_ids))
|
||||
roles = await db.execute(stmt)
|
||||
input_user.roles = roles.scalars().all()
|
||||
return count
|
||||
|
||||
async def delete(self, db: AsyncSession, user_id: int) -> int:
|
||||
"""
|
||||
|
||||
@@ -55,6 +55,7 @@ class UserInfoSchemaBase(SchemaBase):
|
||||
dept_id: int | None = Field(None, description='部门 ID')
|
||||
username: str = Field(description='用户名')
|
||||
nickname: str = Field(description='昵称')
|
||||
avatar: HttpUrl | None = Field(None, description='头像')
|
||||
email: EmailStr = Field(examples=['user@example.com'], description='邮箱')
|
||||
phone: CustomPhoneNumber | None = Field(None, description='手机号')
|
||||
|
||||
@@ -62,19 +63,9 @@ class UserInfoSchemaBase(SchemaBase):
|
||||
class UpdateUserParam(UserInfoSchemaBase):
|
||||
"""更新用户参数"""
|
||||
|
||||
|
||||
class UpdateUserRoleParam(SchemaBase):
|
||||
"""更新用户角色参数"""
|
||||
|
||||
roles: list[int] = Field(description='角色 ID 列表')
|
||||
|
||||
|
||||
class AvatarParam(SchemaBase):
|
||||
"""更新头像参数"""
|
||||
|
||||
url: HttpUrl = Field(description='头像 http 地址')
|
||||
|
||||
|
||||
class GetUserInfoDetail(UserInfoSchemaBase):
|
||||
"""用户信息详情"""
|
||||
|
||||
|
||||
@@ -11,11 +11,9 @@ from backend.app.admin.crud.crud_user import user_dao
|
||||
from backend.app.admin.model import User
|
||||
from backend.app.admin.schema.user import (
|
||||
AddUserParam,
|
||||
AvatarParam,
|
||||
RegisterUserParam,
|
||||
ResetPasswordParam,
|
||||
UpdateUserParam,
|
||||
UpdateUserRoleParam,
|
||||
)
|
||||
from backend.common.exception import errors
|
||||
from backend.common.security.jwt import get_hash_password, get_token, jwt_decode, password_verify, superuser_verify
|
||||
@@ -152,50 +150,11 @@ class UserService:
|
||||
email = await user_dao.check_email(db, obj.email)
|
||||
if email:
|
||||
raise errors.ForbiddenError(msg='邮箱已注册')
|
||||
count = await user_dao.update_userinfo(db, user.id, obj)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def update_roles(*, request: Request, username: str, obj: UpdateUserRoleParam) -> None:
|
||||
"""
|
||||
更新用户角色
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param username: 用户名
|
||||
:param obj: 角色更新参数
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if not request.user.is_superuser and request.user.username != username:
|
||||
raise errors.ForbiddenError(msg='你只能修改自己的信息')
|
||||
input_user = await user_dao.get_with_relation(db, username=username)
|
||||
if not input_user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
for role_id in obj.roles:
|
||||
role = await role_dao.get(db, role_id)
|
||||
if not role:
|
||||
raise errors.NotFoundError(msg='角色不存在')
|
||||
await user_dao.update_role(db, input_user, obj)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{input_user.id}')
|
||||
|
||||
@staticmethod
|
||||
async def update_avatar(*, request: Request, username: str, avatar: AvatarParam) -> int:
|
||||
"""
|
||||
更新用户头像
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param username: 用户名
|
||||
:param avatar: 头像参数
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if request.user.username != username:
|
||||
raise errors.AuthorizationError(msg='你只能修改自己的信息')
|
||||
user = await user_dao.get_by_username(db, username)
|
||||
if not user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
count = await user_dao.update_avatar(db, user.id, avatar)
|
||||
count = await user_dao.update(db, user, obj)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user