mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 21:15:13 +00:00
Optimize the userinfo cache cleaning logic (#586)
This commit is contained in:
@@ -17,7 +17,7 @@ router.include_router(dept_router, prefix='/depts', tags=['系统部门'])
|
||||
router.include_router(menu_router, prefix='/menus', tags=['系统菜单'])
|
||||
router.include_router(role_router, prefix='/roles', tags=['系统角色'])
|
||||
router.include_router(user_router, prefix='/users', tags=['系统用户'])
|
||||
router.include_router(data_rule_router, prefix='/data-rules', tags=['系统数据权限规则'])
|
||||
router.include_router(data_rule_router, prefix='/data-rules', tags=['系统数据规则'])
|
||||
router.include_router(token_router, prefix='/tokens', tags=['系统令牌'])
|
||||
router.include_router(upload_router, prefix='/upload', tags=['系统上传'])
|
||||
router.include_router(plugin_router, prefix='/plugin', tags=['系统插件'])
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Path, Query, Request
|
||||
from fastapi import APIRouter, Depends, Path, Query
|
||||
|
||||
from backend.app.admin.schema.data_rule import CreateDataRuleParam, GetDataRuleDetail, UpdateDataRuleParam
|
||||
from backend.app.admin.service.data_rule_service import data_rule_service
|
||||
@@ -16,13 +16,13 @@ from backend.database.db import CurrentSession
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/models', summary='获取支持过滤的数据库模型', dependencies=[DependsJwtAuth])
|
||||
@router.get('/models', summary='获取数据规则可用模型', dependencies=[DependsJwtAuth])
|
||||
async def get_data_rule_models() -> ResponseSchemaModel[list[str]]:
|
||||
models = await data_rule_service.get_models()
|
||||
return response_base.success(data=models)
|
||||
|
||||
|
||||
@router.get('/model/{model}/columns', summary='获取支持过滤的数据库模型列', dependencies=[DependsJwtAuth])
|
||||
@router.get('/model/{model}/columns', summary='获取数据规则可用模型列', dependencies=[DependsJwtAuth])
|
||||
async def get_data_rule_model_columns(
|
||||
model: Annotated[str, Path(description='模型名称')],
|
||||
) -> ResponseSchemaModel[list[str]]:
|
||||
@@ -36,7 +36,7 @@ async def get_all_data_rules() -> ResponseSchemaModel[list[GetDataRuleDetail]]:
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取数据权限规则详情', dependencies=[DependsJwtAuth])
|
||||
@router.get('/{pk}', summary='获取数据规则详情', dependencies=[DependsJwtAuth])
|
||||
async def get_data_rule(
|
||||
pk: Annotated[int, Path(description='数据规则 ID')],
|
||||
) -> ResponseSchemaModel[GetDataRuleDetail]:
|
||||
@@ -46,7 +46,7 @@ async def get_data_rule(
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='分页获取所有数据权限规则',
|
||||
summary='分页获取所有数据规则',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -62,7 +62,7 @@ async def get_pagination_data_rules(
|
||||
|
||||
@router.post(
|
||||
'',
|
||||
summary='创建数据权限规则',
|
||||
summary='创建数据规则',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('data:rule:add')),
|
||||
DependsRBAC,
|
||||
@@ -75,7 +75,7 @@ async def create_data_rule(obj: CreateDataRuleParam) -> ResponseModel:
|
||||
|
||||
@router.put(
|
||||
'/{pk}',
|
||||
summary='更新数据权限规则',
|
||||
summary='更新数据规则',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('data:rule:edit')),
|
||||
DependsRBAC,
|
||||
@@ -92,16 +92,14 @@ async def update_data_rule(
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='批量删除数据权限规则',
|
||||
summary='批量删除数据规则',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('data:rule:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_data_rule(
|
||||
request: Request, pk: Annotated[list[int], Query(description='数据规则 ID 列表')]
|
||||
) -> ResponseModel:
|
||||
count = await data_rule_service.delete(request=request, pk=pk)
|
||||
async def delete_data_rule(pk: Annotated[list[int], Query(description='数据规则 ID 列表')]) -> ResponseModel:
|
||||
count = await data_rule_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Annotated, Any
|
||||
|
||||
from fastapi import APIRouter, Depends, Path, Query, Request
|
||||
from fastapi import APIRouter, Depends, Path, Query
|
||||
|
||||
from backend.app.admin.schema.dept import CreateDeptParam, GetDeptDetail, UpdateDeptParam
|
||||
from backend.app.admin.service.dept_service import dept_service
|
||||
@@ -67,8 +67,8 @@ async def update_dept(pk: Annotated[int, Path(description='部门 ID')], obj: Up
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_dept(request: Request, pk: Annotated[int, Path(description='部门 ID')]) -> ResponseModel:
|
||||
count = await dept_service.delete(request=request, pk=pk)
|
||||
async def delete_dept(pk: Annotated[int, Path(description='部门 ID')]) -> ResponseModel:
|
||||
count = await dept_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
@@ -71,8 +71,8 @@ async def update_menu(pk: Annotated[int, Path(description='菜单 ID')], obj: Up
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_menu(request: Request, pk: Annotated[int, Path(description='菜单 ID 列表')]) -> ResponseModel:
|
||||
count = await menu_service.delete(request=request, pk=pk)
|
||||
async def delete_menu(pk: Annotated[int, Path(description='菜单 ID 列表')]) -> ResponseModel:
|
||||
count = await menu_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Annotated, Any
|
||||
|
||||
from fastapi import APIRouter, Depends, Path, Query, Request
|
||||
from fastapi import APIRouter, Depends, Path, Query
|
||||
|
||||
from backend.app.admin.schema.role import (
|
||||
CreateRoleParam,
|
||||
@@ -116,9 +116,9 @@ async def update_role(pk: Annotated[int, Path(description='角色 ID')], obj: Up
|
||||
],
|
||||
)
|
||||
async def update_role_menus(
|
||||
request: Request, pk: Annotated[int, Path(description='角色 ID')], menu_ids: UpdateRoleMenuParam
|
||||
pk: Annotated[int, Path(description='角色 ID')], menu_ids: UpdateRoleMenuParam
|
||||
) -> ResponseModel:
|
||||
count = await role_service.update_role_menu(request=request, pk=pk, menu_ids=menu_ids)
|
||||
count = await role_service.update_role_menu(pk=pk, menu_ids=menu_ids)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
@@ -126,16 +126,16 @@ async def update_role_menus(
|
||||
|
||||
@router.put(
|
||||
'/{pk}/rule',
|
||||
summary='更新角色数据权限规则',
|
||||
summary='更新角色数据规则',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:role:rule:edit')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_role_rules(
|
||||
request: Request, pk: Annotated[int, Path(description='角色 ID')], rule_ids: UpdateRoleRuleParam
|
||||
pk: Annotated[int, Path(description='角色 ID')], rule_ids: UpdateRoleRuleParam
|
||||
) -> ResponseModel:
|
||||
count = await role_service.update_role_rule(request=request, pk=pk, rule_ids=rule_ids)
|
||||
count = await role_service.update_role_rule(pk=pk, rule_ids=rule_ids)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
@@ -149,8 +149,8 @@ async def update_role_rules(
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_role(request: Request, pk: Annotated[list[int], Query(description='角色 ID 列表')]) -> ResponseModel:
|
||||
count = await role_service.delete(request=request, pk=pk)
|
||||
async def delete_role(pk: Annotated[list[int], Query(description='角色 ID 列表')]) -> ResponseModel:
|
||||
count = await role_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
@@ -12,7 +12,7 @@ from backend.app.admin.schema.data_rule import CreateDataRuleParam, UpdateDataRu
|
||||
|
||||
|
||||
class CRUDDataRule(CRUDPlus[DataRule]):
|
||||
"""数据权限规则数据库操作类"""
|
||||
"""数据规则数据库操作类"""
|
||||
|
||||
async def get(self, db: AsyncSession, pk: int) -> DataRule | None:
|
||||
"""
|
||||
|
||||
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class DataRule(Base):
|
||||
"""数据权限规则表"""
|
||||
"""数据规则表"""
|
||||
|
||||
__tablename__ = 'sys_data_rule'
|
||||
|
||||
|
||||
@@ -30,6 +30,6 @@ sys_role_data_rule = Table(
|
||||
Integer,
|
||||
ForeignKey('sys_data_rule.id', ondelete='CASCADE'),
|
||||
primary_key=True,
|
||||
comment='数据权限规则ID',
|
||||
comment='数据规则ID',
|
||||
),
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ class Role(Base):
|
||||
# 角色菜单多对多
|
||||
menus: Mapped[list[Menu]] = relationship(init=False, secondary=sys_role_menu, back_populates='roles')
|
||||
|
||||
# 角色数据权限规则多对多
|
||||
# 角色数据规则多对多
|
||||
rules: Mapped[list[DataRule]] = relationship(init=False, secondary=sys_role_data_rule, back_populates='roles')
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Sequence
|
||||
|
||||
from fastapi import Request
|
||||
from sqlalchemy import Select
|
||||
|
||||
from backend.app.admin.crud.crud_data_rule import data_rule_dao
|
||||
@@ -17,7 +16,7 @@ from backend.utils.import_parse import dynamic_import_data_model
|
||||
|
||||
|
||||
class DataRuleService:
|
||||
"""数据权限规则服务类"""
|
||||
"""数据规则服务类"""
|
||||
|
||||
@staticmethod
|
||||
async def get(*, pk: int) -> DataRule:
|
||||
@@ -50,19 +49,19 @@ class DataRuleService:
|
||||
|
||||
@staticmethod
|
||||
async def get_models() -> list[str]:
|
||||
"""获取所有数据模型"""
|
||||
"""获取所有数据规则可用模型"""
|
||||
return list(settings.DATA_PERMISSION_MODELS.keys())
|
||||
|
||||
@staticmethod
|
||||
async def get_columns(model: str) -> list[str]:
|
||||
"""
|
||||
获取数据模型的字段列表
|
||||
获取数据规则可用模型的字段列表
|
||||
|
||||
:param model: 模型名称
|
||||
:return:
|
||||
"""
|
||||
if model not in settings.DATA_PERMISSION_MODELS:
|
||||
raise errors.NotFoundError(msg='数据模型不存在')
|
||||
raise errors.NotFoundError(msg='数据规则可用模型不存在')
|
||||
model_ins = dynamic_import_data_model(settings.DATA_PERMISSION_MODELS[model])
|
||||
model_columns = [
|
||||
key for key in model_ins.__table__.columns.keys() if key not in settings.DATA_PERMISSION_COLUMN_EXCLUDE
|
||||
@@ -97,7 +96,7 @@ class DataRuleService:
|
||||
async with async_db_session.begin() as db:
|
||||
data_rule = await data_rule_dao.get_by_name(db, obj.name)
|
||||
if data_rule:
|
||||
raise errors.ForbiddenError(msg='数据权限规则已存在')
|
||||
raise errors.ForbiddenError(msg='数据规则已存在')
|
||||
await data_rule_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -112,22 +111,29 @@ class DataRuleService:
|
||||
async with async_db_session.begin() as db:
|
||||
data_rule = await data_rule_dao.get(db, pk)
|
||||
if not data_rule:
|
||||
raise errors.NotFoundError(msg='数据权限规则不存在')
|
||||
raise errors.NotFoundError(msg='数据规则不存在')
|
||||
count = await data_rule_dao.update(db, pk, obj)
|
||||
for role in await data_rule.awaitable_attrs.roles:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def delete(*, request: Request, pk: list[int]) -> int:
|
||||
async def delete(*, pk: list[int]) -> int:
|
||||
"""
|
||||
删除数据规则
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 规则 ID 列表
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
count = await data_rule_dao.delete(db, pk)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
for _pk in pk:
|
||||
data_rule = await data_rule_dao.get(db, _pk)
|
||||
if data_rule:
|
||||
for role in await data_rule.awaitable_attrs.roles:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Any
|
||||
|
||||
from fastapi import Request
|
||||
|
||||
from backend.app.admin.crud.crud_dept import dept_dao
|
||||
from backend.app.admin.model import Dept
|
||||
from backend.app.admin.schema.dept import CreateDeptParam, UpdateDeptParam
|
||||
@@ -93,24 +91,23 @@ class DeptService:
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def delete(*, request: Request, pk: int) -> int:
|
||||
async def delete(*, pk: int) -> int:
|
||||
"""
|
||||
删除部门
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 部门 ID
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
dept = await dept_dao.get_with_relation(db, pk)
|
||||
dept_user = dept.users
|
||||
if dept_user:
|
||||
if dept.users:
|
||||
raise errors.ForbiddenError(msg='部门下存在用户,无法删除')
|
||||
children = await dept_dao.get_children(db, pk)
|
||||
if children:
|
||||
raise errors.ForbiddenError(msg='部门下存在子部门,无法删除')
|
||||
count = await dept_dao.delete(db, pk)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
for user in dept.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
|
||||
|
||||
@@ -123,14 +123,16 @@ class MenuService:
|
||||
if obj.parent_id == menu.id:
|
||||
raise errors.ForbiddenError(msg='禁止关联自身为父级')
|
||||
count = await menu_dao.update(db, pk, obj)
|
||||
for role in await menu.awaitable_attrs.roles:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def delete(*, request: Request, pk: int) -> int:
|
||||
async def delete(*, pk: int) -> int:
|
||||
"""
|
||||
删除菜单
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 菜单 ID
|
||||
:return:
|
||||
"""
|
||||
@@ -138,8 +140,12 @@ class MenuService:
|
||||
children = await menu_dao.get_children(db, pk)
|
||||
if children:
|
||||
raise errors.ForbiddenError(msg='菜单下存在子菜单,无法删除')
|
||||
menu = await menu_dao.get(db, pk)
|
||||
count = await menu_dao.delete(db, pk)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
if menu:
|
||||
for role in await menu.awaitable_attrs.roles:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Sequence
|
||||
|
||||
from fastapi import Request
|
||||
from sqlalchemy import Select
|
||||
|
||||
from backend.app.admin.crud.crud_data_rule import data_rule_dao
|
||||
@@ -100,20 +99,21 @@ class RoleService:
|
||||
if role:
|
||||
raise errors.ForbiddenError(msg='角色已存在')
|
||||
count = await role_dao.update(db, pk, obj)
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete_prefix(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def update_role_menu(*, request: Request, pk: int, menu_ids: UpdateRoleMenuParam) -> int:
|
||||
async def update_role_menu(*, pk: int, menu_ids: UpdateRoleMenuParam) -> int:
|
||||
"""
|
||||
更新角色菜单
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 角色 ID
|
||||
:param menu_ids: 菜单 ID 列表
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
role = await role_dao.get(db, pk)
|
||||
role = await role_dao.get_with_relation(db, pk)
|
||||
if not role:
|
||||
raise errors.NotFoundError(msg='角色不存在')
|
||||
for menu_id in menu_ids.menus:
|
||||
@@ -121,16 +121,15 @@ class RoleService:
|
||||
if not menu:
|
||||
raise errors.NotFoundError(msg='菜单不存在')
|
||||
count = await role_dao.update_menus(db, pk, menu_ids)
|
||||
if pk in [role.id for role in request.user.roles]:
|
||||
await redis_client.delete_prefix(f'{settings.JWT_USER_REDIS_PREFIX}')
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete_prefix(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def update_role_rule(*, request: Request, pk: int, rule_ids: UpdateRoleRuleParam) -> int:
|
||||
async def update_role_rule(*, pk: int, rule_ids: UpdateRoleRuleParam) -> int:
|
||||
"""
|
||||
更新角色数据权限
|
||||
更新角色数据规则
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 角色 ID
|
||||
:param rule_ids: 权限规则 ID 列表
|
||||
:return:
|
||||
@@ -142,24 +141,27 @@ class RoleService:
|
||||
for rule_id in rule_ids.rules:
|
||||
rule = await data_rule_dao.get(db, rule_id)
|
||||
if not rule:
|
||||
raise errors.NotFoundError(msg='数据权限不存在')
|
||||
raise errors.NotFoundError(msg='数据规则不存在')
|
||||
count = await role_dao.update_rules(db, pk, rule_ids)
|
||||
if pk in [role.id for role in request.user.roles]:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
async def delete(*, request: Request, pk: list[int]) -> int:
|
||||
async def delete(*, pk: list[int]) -> int:
|
||||
"""
|
||||
删除角色
|
||||
|
||||
:param request: FastAPI 请求对象
|
||||
:param pk: 角色 ID 列表
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
count = await role_dao.delete(db, pk)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
for _pk in pk:
|
||||
role = await role_dao.get(db, _pk)
|
||||
if role:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
|
||||
|
||||
@@ -135,25 +135,25 @@ class UserService:
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if not request.user.is_superuser and request.user.username != username:
|
||||
if request.user.username != username:
|
||||
raise errors.ForbiddenError(msg='你只能修改自己的信息')
|
||||
input_user = await user_dao.get_with_relation(db, username=username)
|
||||
if not input_user:
|
||||
user = await user_dao.get_with_relation(db, username=username)
|
||||
if not user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
if input_user.username != obj.username:
|
||||
if user.username != obj.username:
|
||||
_username = await user_dao.get_by_username(db, obj.username)
|
||||
if _username:
|
||||
raise errors.ForbiddenError(msg='用户名已注册')
|
||||
if input_user.nickname != obj.nickname:
|
||||
if user.nickname != obj.nickname:
|
||||
nickname = await user_dao.get_by_nickname(db, obj.nickname)
|
||||
if nickname:
|
||||
raise errors.ForbiddenError(msg='昵称已注册')
|
||||
if input_user.email != obj.email:
|
||||
if user.email != obj.email:
|
||||
email = await user_dao.check_email(db, obj.email)
|
||||
if email:
|
||||
raise errors.ForbiddenError(msg='邮箱已注册')
|
||||
count = await user_dao.update_userinfo(db, input_user.id, obj)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
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
|
||||
@@ -168,7 +168,7 @@ class UserService:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if not request.user.is_superuser and request.user.username != username:
|
||||
raise errors.AuthorizationError
|
||||
raise errors.ForbiddenError(msg='你只能修改自己的信息')
|
||||
input_user = await user_dao.get_with_relation(db, username=username)
|
||||
if not input_user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
@@ -190,13 +190,13 @@ class UserService:
|
||||
:return:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if not request.user.is_superuser and request.user.username != username:
|
||||
if request.user.username != username:
|
||||
raise errors.AuthorizationError
|
||||
input_user = await user_dao.get_by_username(db, username)
|
||||
if not input_user:
|
||||
user = await user_dao.get_by_username(db, username)
|
||||
if not user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
count = await user_dao.update_avatar(db, input_user.id, avatar)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
count = await user_dao.update_avatar(db, user.id, avatar)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
@@ -230,7 +230,7 @@ class UserService:
|
||||
raise errors.ForbiddenError(msg='非法操作')
|
||||
super_status = await user_dao.get_super(db, pk)
|
||||
count = await user_dao.set_super(db, pk, not super_status)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{pk}')
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
@@ -251,7 +251,7 @@ class UserService:
|
||||
raise errors.ForbiddenError(msg='非法操作')
|
||||
staff_status = await user_dao.get_staff(db, pk)
|
||||
count = await user_dao.set_staff(db, pk, not staff_status)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{pk}')
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
@@ -272,7 +272,7 @@ class UserService:
|
||||
raise errors.ForbiddenError(msg='非法操作')
|
||||
status = await user_dao.get_status(db, pk)
|
||||
count = await user_dao.set_status(db, pk, 0 if status == 1 else 1)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{pk}')
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
@@ -289,32 +289,22 @@ class UserService:
|
||||
user = await user_dao.get(db, pk)
|
||||
if not user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
user_id = request.user.id
|
||||
multi_login = await user_dao.get_multi_login(db, pk) if pk != user_id else request.user.is_multi_login
|
||||
count = await user_dao.set_multi_login(db, pk, not multi_login)
|
||||
# 删除当前用户缓存
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
|
||||
multi_login = await user_dao.get_multi_login(db, pk) if pk != user.id else request.user.is_multi_login
|
||||
new_multi_login = not multi_login
|
||||
count = await user_dao.set_multi_login(db, pk, new_multi_login)
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
token = get_token(request)
|
||||
token_payload = jwt_decode(token)
|
||||
latest_multi_login = await user_dao.get_multi_login(db, pk)
|
||||
# 超级用户修改自身时,除当前 token 外,其他 token 失效
|
||||
if pk == user_id:
|
||||
if not latest_multi_login:
|
||||
key_prefix = f'{settings.TOKEN_REDIS_PREFIX}:{pk}'
|
||||
if pk == user.id:
|
||||
# 系统管理员修改自身时,除当前 token 外,其他 token 失效
|
||||
if not new_multi_login:
|
||||
key_prefix = f'{settings.TOKEN_REDIS_PREFIX}:{user.id}'
|
||||
await redis_client.delete_prefix(key_prefix, exclude=f'{key_prefix}:{token_payload.session_uuid}')
|
||||
refresh_token = request.cookies.get(settings.COOKIE_REFRESH_TOKEN_KEY)
|
||||
if refresh_token:
|
||||
key_prefix = f'{settings.TOKEN_REFRESH_REDIS_PREFIX}:{pk}'
|
||||
await redis_client.delete_prefix(key_prefix, exclude=f'{key_prefix}:{refresh_token}')
|
||||
# 超级用户修改他人时,其他 token 将全部失效
|
||||
else:
|
||||
if not latest_multi_login:
|
||||
key_prefix = [f'{settings.TOKEN_REDIS_PREFIX}:{pk}']
|
||||
refresh_token = request.cookies.get(settings.COOKIE_REFRESH_TOKEN_KEY)
|
||||
if refresh_token:
|
||||
key_prefix.append(f'{settings.TOKEN_REFRESH_REDIS_PREFIX}:{pk}')
|
||||
for prefix in key_prefix:
|
||||
await redis_client.delete_prefix(prefix)
|
||||
# 系统管理员修改他人时,他人 token 全部失效
|
||||
if not new_multi_login:
|
||||
key_prefix = f'{settings.TOKEN_REDIS_PREFIX}:{user.id}'
|
||||
await redis_client.delete_prefix(key_prefix)
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -47,14 +47,14 @@ class MenuType(IntEnum):
|
||||
|
||||
|
||||
class RoleDataRuleOperatorType(IntEnum):
|
||||
"""数据权限规则运算符"""
|
||||
"""数据规则运算符"""
|
||||
|
||||
AND = 0
|
||||
OR = 1
|
||||
|
||||
|
||||
class RoleDataRuleExpressionType(IntEnum):
|
||||
"""数据权限规则表达式"""
|
||||
"""数据规则表达式"""
|
||||
|
||||
eq = 0 # ==
|
||||
ne = 1 # !=
|
||||
|
||||
@@ -119,7 +119,7 @@ create table sys_data_rule
|
||||
constraint name
|
||||
unique (name)
|
||||
)
|
||||
comment '数据权限规则表';
|
||||
comment '数据规则表';
|
||||
|
||||
create index ix_sys_data_rule_id
|
||||
on sys_data_rule (id);
|
||||
@@ -319,7 +319,7 @@ create table sys_role_data_rule
|
||||
(
|
||||
id int auto_increment comment '主键ID',
|
||||
role_id int not null comment '角色ID',
|
||||
data_rule_id int not null comment '数据权限规则ID',
|
||||
data_rule_id int not null comment '数据规则ID',
|
||||
primary key (id, role_id, data_rule_id),
|
||||
constraint ix_sys_role_data_rule_id
|
||||
unique (id),
|
||||
|
||||
@@ -13,7 +13,7 @@ create table sys_data_rule
|
||||
updated_time timestamp with time zone
|
||||
);
|
||||
|
||||
comment on table sys_data_rule is '数据权限规则表';
|
||||
comment on table sys_data_rule is '数据规则表';
|
||||
|
||||
comment on column sys_data_rule.id is '主键 ID';
|
||||
|
||||
@@ -609,7 +609,7 @@ comment on column sys_role_data_rule.id is '主键ID';
|
||||
|
||||
comment on column sys_role_data_rule.role_id is '角色ID';
|
||||
|
||||
comment on column sys_role_data_rule.data_rule_id is '数据权限规则ID';
|
||||
comment on column sys_role_data_rule.data_rule_id is '数据规则ID';
|
||||
|
||||
alter table sys_role_data_rule
|
||||
owner to postgres;
|
||||
|
||||
Reference in New Issue
Block a user