feat: 添加系统级管理专属页面权限

This commit is contained in:
皓月归尘 2025-02-26 23:00:24 +08:00
parent f6af4eace8
commit 7d4170a3c3
7 changed files with 71 additions and 22 deletions

View File

@ -9,6 +9,7 @@ from functools import wraps
from fastapi import Request from fastapi import Request
from config.constant import RedisKeyConfig
from controller.login import LoginController from controller.login import LoginController
from exceptions.exception import PermissionException from exceptions.exception import PermissionException
@ -53,3 +54,16 @@ async def hasAuth(request: Request, permission: str) -> bool:
return True return True
else: else:
return False return False
async def hasAdmin(request: Request, department_id: str) -> bool:
"""
判断是否有管理员权限
"""
permissions = []
if ids := await request.app.state.redis.get(f'{RedisKeyConfig.SYSTEM_CONFIG.key}:permission_departments'):
permissions = eval(ids)
if department_id in permissions:
return True
else:
return False

View File

@ -10,7 +10,7 @@ from typing import Optional
from fastapi import APIRouter, Depends, Path, Query, Request from fastapi import APIRouter, Depends, Path, Query, Request
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from annotation.auth import Auth from annotation.auth import Auth, hasAdmin
from annotation.log import Log from annotation.log import Log
from config.constant import BusinessType, RedisKeyConfig from config.constant import BusinessType, RedisKeyConfig
from controller.login import LoginController from controller.login import LoginController
@ -51,6 +51,7 @@ async def add_permission(request: Request, params: AddPermissionParams):
leave_transition=params.leave_transition, leave_transition=params.leave_transition,
fixed_tag=params.fixed_tag, fixed_tag=params.fixed_tag,
hidden_tag=params.hidden_tag, hidden_tag=params.hidden_tag,
is_admin=params.is_admin
) )
if permission: if permission:
# 更新用户信息缓存 # 更新用户信息缓存
@ -114,6 +115,7 @@ async def update_permission(request: Request, params: AddPermissionParams, id: s
permission.leave_transition = params.leave_transition permission.leave_transition = params.leave_transition
permission.fixed_tag = params.fixed_tag permission.fixed_tag = params.fixed_tag
permission.hidden_tag = params.hidden_tag permission.hidden_tag = params.hidden_tag
permission.is_admin = params.is_admin
await permission.save() await permission.save()
# 更新用户信息缓存 # 更新用户信息缓存
userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*')
@ -161,6 +163,7 @@ async def get_permission(request: Request, id: str = Path(description="权限ID"
fixed_tag="fixed_tag", fixed_tag="fixed_tag",
show_link="show_link", show_link="show_link",
show_parent="show_parent", show_parent="show_parent",
is_admin="is_admin"
) )
return Response.success(msg="查询权限详情成功!", data=permission) return Response.success(msg="查询权限详情成功!", data=permission)
else: else:
@ -195,7 +198,9 @@ async def get_permission_list(
enterTransition: Optional[str] = Query(default=None, description="进场动画"), enterTransition: Optional[str] = Query(default=None, description="进场动画"),
leaveTransition: Optional[str] = Query(default=None, description="离场动画"), leaveTransition: Optional[str] = Query(default=None, description="离场动画"),
fixedTag: Optional[bool] = Query(default=None, description="固定标签页"), fixedTag: Optional[bool] = Query(default=None, description="固定标签页"),
hiddenTag: Optional[bool] = Query(default=None, description="隐藏标签页") hiddenTag: Optional[bool] = Query(default=None, description="隐藏标签页"),
isAdmin: Optional[bool] = Query(default=None, description="是否为管理专属页面"),
current_user: dict = Depends(LoginController.get_current_user),
): ):
filterArgs = { filterArgs = {
f'{k}__contains': v for k, v in { f'{k}__contains': v for k, v in {
@ -219,9 +224,13 @@ async def get_permission_list(
"enter_transition": enterTransition, "enter_transition": enterTransition,
"leave_transition": leaveTransition, "leave_transition": leaveTransition,
"fixed_tag": fixedTag, "fixed_tag": fixedTag,
"hidden_tag": hiddenTag "hidden_tag": hiddenTag,
"is_admin": isAdmin
}.items() if v }.items() if v
} }
department_id = current_user.get("department_id", "")
if not await hasAdmin(request, department_id):
filterArgs["is_admin"] = False
total = await Permission.filter(**filterArgs, del_flag=1).count() total = await Permission.filter(**filterArgs, del_flag=1).count()
result = await Permission.filter(**filterArgs, del_flag=1).offset((page - 1) * pageSize).limit(pageSize).order_by( result = await Permission.filter(**filterArgs, del_flag=1).offset((page - 1) * pageSize).limit(pageSize).order_by(
'rank').values( 'rank').values(
@ -250,7 +259,8 @@ async def get_permission_list(
hidden_tag="hidden_tag", hidden_tag="hidden_tag",
fixed_tag="fixed_tag", fixed_tag="fixed_tag",
show_link="show_link", show_link="show_link",
show_parent="show_parent" show_parent="show_parent",
is_admin="is_admin"
) )
return Response.success(data={ return Response.success(data={
"total": total, "total": total,

View File

@ -10,7 +10,7 @@ from typing import Optional
from fastapi import APIRouter, Depends, Path, Query, Request from fastapi import APIRouter, Depends, Path, Query, Request
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from annotation.auth import Auth, hasAuth from annotation.auth import Auth, hasAuth, hasAdmin
from annotation.log import Log from annotation.log import Log
from config.constant import BusinessType, RedisKeyConfig from config.constant import BusinessType, RedisKeyConfig
from controller.login import LoginController from controller.login import LoginController
@ -235,6 +235,11 @@ async def add_role_permission(request: Request, params: AddRolePermissionParams,
id: str = Path(..., description="角色ID"), id: str = Path(..., description="角色ID"),
current_user: dict = Depends(LoginController.get_current_user)): current_user: dict = Depends(LoginController.get_current_user)):
sub_departments = current_user.get("sub_departments") sub_departments = current_user.get("sub_departments")
if await hasAdmin(request, current_user.get("department_id")):
department_permissions = await Permission.filter(del_flag=1).values("id")
else:
department_permissions = await Permission.filter(is_admin=False, del_flag=1).values("id")
department_permissions = filterKeyValues(department_permissions, "id")
if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments):
# 已有角色权限 # 已有角色权限
rolePermissions = await RolePermission.filter(role_id=id, del_flag=1).values("permission_id") rolePermissions = await RolePermission.filter(role_id=id, del_flag=1).values("permission_id")
@ -243,6 +248,8 @@ async def add_role_permission(request: Request, params: AddRolePermissionParams,
add_list = set(params.permission_ids).difference(set(rolePermissions)) add_list = set(params.permission_ids).difference(set(rolePermissions))
# 循环添加角色权限 # 循环添加角色权限
for item in add_list: for item in add_list:
if item not in department_permissions:
continue
permission = await Permission.get_or_none(id=item, del_flag=1) permission = await Permission.get_or_none(id=item, del_flag=1)
if permission: if permission:
await RolePermission.create( await RolePermission.create(
@ -294,6 +301,11 @@ async def update_role_permission(request: Request, params: AddRolePermissionPara
id: str = Path(..., description="角色ID"), id: str = Path(..., description="角色ID"),
current_user: dict = Depends(LoginController.get_current_user)): current_user: dict = Depends(LoginController.get_current_user)):
sub_departments = current_user.get("sub_departments") sub_departments = current_user.get("sub_departments")
if await hasAdmin(request, current_user.get("department_id")):
department_permissions = await Permission.filter(del_flag=1).values("id")
else:
department_permissions = await Permission.filter(is_admin=False, del_flag=1).values("id")
department_permissions = filterKeyValues(department_permissions, "id")
if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments):
# 已有角色权限 # 已有角色权限
rolePermissions = await RolePermission.filter(role_id=role.id, del_flag=1).values("permission_id") rolePermissions = await RolePermission.filter(role_id=role.id, del_flag=1).values("permission_id")
@ -307,6 +319,8 @@ async def update_role_permission(request: Request, params: AddRolePermissionPara
await RolePermission.filter(role_id=id, permission_id=item, del_flag=1).update(del_flag=0) await RolePermission.filter(role_id=id, permission_id=item, del_flag=1).update(del_flag=0)
# 循环添加角色权限 # 循环添加角色权限
for item in add_list: for item in add_list:
if item not in department_permissions:
continue
await RolePermission.create(role_id=id, permission_id=item) await RolePermission.create(role_id=id, permission_id=item)
# 更新用户信息缓存 # 更新用户信息缓存
userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*')

View File

@ -443,7 +443,7 @@ async def reset_user_password(request: Request, params: ResetPasswordParams, id:
@userAPI.post("/updateBaseUserInfo", response_model=BaseResponse, response_class=JSONResponse, @userAPI.post("/updateBaseUserInfo", response_model=BaseResponse, response_class=JSONResponse,
summary="更新基础个人信息") summary="更新基础个人信息")
@Log(title="更新基础个人信息", business_type=BusinessType.UPDATE) @Log(title="更新基础个人信息", business_type=BusinessType.UPDATE)
async def update_base_userinfo(params: UpdateBaseUserInfoParams, request: Request, async def update_base_userinfo(request: Request, params: UpdateBaseUserInfoParams,
current_user: dict = Depends(LoginController.get_current_user)): current_user: dict = Depends(LoginController.get_current_user)):
user = await User.get_or_none(id=current_user.get("id"), del_flag=1) user = await User.get_or_none(id=current_user.get("id"), del_flag=1)
if user: if user:
@ -500,7 +500,8 @@ async def update_user_phone(request: Request, password: str = Form(description="
@userAPI.post("/updateEmail", response_class=JSONResponse, response_model=BaseResponse, summary="用户更新邮箱") @userAPI.post("/updateEmail", response_class=JSONResponse, response_model=BaseResponse, summary="用户更新邮箱")
@Log(title="用户更新邮箱", business_type=BusinessType.UPDATE) @Log(title="用户更新邮箱", business_type=BusinessType.UPDATE)
async def update_user_email(request: Request, password: str = Form(description="用户密码"), async def update_user_email(request: Request, password: str = Form(description="用户密码"),
email: str = Form(description="用户邮箱"),current_user: dict = Depends(LoginController.get_current_user)): email: str = Form(description="用户邮箱"),
current_user: dict = Depends(LoginController.get_current_user)):
if user := await User.get_or_none(id=current_user.get("id"), del_flag=1): if user := await User.get_or_none(id=current_user.get("id"), del_flag=1):
password = await Password.get_password_hash(password) password = await Password.get_password_hash(password)
if user.password != password: if user.password != password:

View File

@ -280,6 +280,18 @@ class Permission(BaseModel):
- 映射到数据库字段 show_parent - 映射到数据库字段 show_parent
""" """
is_admin = fields.BooleanField(
default=False,
description="是否为管理专属页面",
source_field="is_admin" # 映射到数据库字段 is_admin
)
"""
是否为管理专属页面
- 是否为管理专属页面仅管理员可见
- 默认为 False
- 映射到数据库字段 is_admin
"""
class Meta: class Meta:
table = "permission" # 数据库表名 table = "permission" # 数据库表名
table_description = "权限表" # 表描述 table_description = "权限表" # 表描述

View File

@ -43,6 +43,7 @@ class PermissionInfo(BaseModel):
fixed_tag: bool = Field(default=False, description="固定标签页") fixed_tag: bool = Field(default=False, description="固定标签页")
show_link: bool = Field(default=True, description="显示菜单") show_link: bool = Field(default=True, description="显示菜单")
show_parent: bool = Field(default=True, description="显示父级菜单") show_parent: bool = Field(default=True, description="显示父级菜单")
is_admin: bool = Field(default=False, description="是否为管理专属页面")
class Config: class Config:
json_schema_extra = { json_schema_extra = {
@ -72,7 +73,8 @@ class PermissionInfo(BaseModel):
"hidden_tag": False, "hidden_tag": False,
"fixed_tag": False, "fixed_tag": False,
"show_link": True, "show_link": True,
"show_parent": True "show_parent": True,
"is_admin": False
} }
} }
@ -109,6 +111,7 @@ class AddPermissionParams(BaseModel):
show_parent: bool = Field(default=True, description="显示父级菜单") show_parent: bool = Field(default=True, description="显示父级菜单")
parent_id: str = Field(default="", max_length=36, description="父级菜单ID") parent_id: str = Field(default="", max_length=36, description="父级菜单ID")
menu_type: int = Field(default=0, description="菜单类型") menu_type: int = Field(default=0, description="菜单类型")
is_admin: bool = Field(default=False, description="是否为管理专属页面")
class Config: class Config:
json_schema_extra = { json_schema_extra = {
@ -133,7 +136,8 @@ class AddPermissionParams(BaseModel):
"show_link": True, "show_link": True,
"show_parent": True, "show_parent": True,
"parent_id": "", "parent_id": "",
"menu_type": 0 "menu_type": 0,
"is_admin": False
} }
} }

View File

@ -6,7 +6,6 @@
# @Software : PyCharm # @Software : PyCharm
# @Comment : 本程序 # @Comment : 本程序
from datetime import datetime from datetime import datetime
from enum import IntEnum
from typing import Optional, List from typing import Optional, List
from uuid import UUID from uuid import UUID
@ -16,11 +15,6 @@ from pydantic_validation_decorator import Xss, NotBlank, Size, Network
from schemas.common import BaseResponse, ListQueryResult from schemas.common import BaseResponse, ListQueryResult
class Gender(IntEnum):
MAN = 0
WOMAN = 1
class UserBase(BaseModel): class UserBase(BaseModel):
""" """
用户表基础模型 用户表基础模型
@ -399,7 +393,7 @@ class UpdateBaseUserInfoParams(BaseModel):
"""修改基础信息参数""" """修改基础信息参数"""
name: str name: str
"""姓名""" """姓名"""
gender: Gender gender: int
"""性别""" """性别"""
class Config: class Config: