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 config.constant import RedisKeyConfig
from controller.login import LoginController
from exceptions.exception import PermissionException
@ -53,3 +54,16 @@ async def hasAuth(request: Request, permission: str) -> bool:
return True
else:
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.responses import JSONResponse
from annotation.auth import Auth
from annotation.auth import Auth, hasAdmin
from annotation.log import Log
from config.constant import BusinessType, RedisKeyConfig
from controller.login import LoginController
@ -51,6 +51,7 @@ async def add_permission(request: Request, params: AddPermissionParams):
leave_transition=params.leave_transition,
fixed_tag=params.fixed_tag,
hidden_tag=params.hidden_tag,
is_admin=params.is_admin
)
if permission:
# 更新用户信息缓存
@ -114,6 +115,7 @@ async def update_permission(request: Request, params: AddPermissionParams, id: s
permission.leave_transition = params.leave_transition
permission.fixed_tag = params.fixed_tag
permission.hidden_tag = params.hidden_tag
permission.is_admin = params.is_admin
await permission.save()
# 更新用户信息缓存
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",
show_link="show_link",
show_parent="show_parent",
is_admin="is_admin"
)
return Response.success(msg="查询权限详情成功!", data=permission)
else:
@ -195,7 +198,9 @@ async def get_permission_list(
enterTransition: Optional[str] = Query(default=None, description="进场动画"),
leaveTransition: Optional[str] = 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 = {
f'{k}__contains': v for k, v in {
@ -219,9 +224,13 @@ async def get_permission_list(
"enter_transition": enterTransition,
"leave_transition": leaveTransition,
"fixed_tag": fixedTag,
"hidden_tag": hiddenTag
"hidden_tag": hiddenTag,
"is_admin": isAdmin
}.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()
result = await Permission.filter(**filterArgs, del_flag=1).offset((page - 1) * pageSize).limit(pageSize).order_by(
'rank').values(
@ -250,7 +259,8 @@ async def get_permission_list(
hidden_tag="hidden_tag",
fixed_tag="fixed_tag",
show_link="show_link",
show_parent="show_parent"
show_parent="show_parent",
is_admin="is_admin"
)
return Response.success(data={
"total": total,

View File

@ -10,7 +10,7 @@ from typing import Optional
from fastapi import APIRouter, Depends, Path, Query, Request
from fastapi.responses import JSONResponse
from annotation.auth import Auth, hasAuth
from annotation.auth import Auth, hasAuth, hasAdmin
from annotation.log import Log
from config.constant import BusinessType, RedisKeyConfig
from controller.login import LoginController
@ -235,6 +235,11 @@ async def add_role_permission(request: Request, params: AddRolePermissionParams,
id: str = Path(..., description="角色ID"),
current_user: dict = Depends(LoginController.get_current_user)):
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):
# 已有角色权限
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))
# 循环添加角色权限
for item in add_list:
if item not in department_permissions:
continue
permission = await Permission.get_or_none(id=item, del_flag=1)
if permission:
await RolePermission.create(
@ -294,6 +301,11 @@ async def update_role_permission(request: Request, params: AddRolePermissionPara
id: str = Path(..., description="角色ID"),
current_user: dict = Depends(LoginController.get_current_user)):
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):
# 已有角色权限
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)
# 循环添加角色权限
for item in add_list:
if item not in department_permissions:
continue
await RolePermission.create(role_id=id, permission_id=item)
# 更新用户信息缓存
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,
summary="更新基础个人信息")
@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)):
user = await User.get_or_none(id=current_user.get("id"), del_flag=1)
if user:
@ -485,10 +485,10 @@ async def update_user_phone(request: Request, password: str = Form(description="
password = await Password.get_password_hash(password)
if user.password != password:
return Response.error("更改失败,请正确输入旧密码")
phoneStatus = await User.filter(phone=phone,del_flag=1).count()
phoneStatus = await User.filter(phone=phone, del_flag=1).count()
if phoneStatus:
return Response.error( f"更改失败,手机号:{phone}已绑定其他账号!")
user.phone=phone
return Response.error(f"更改失败,手机号:{phone}已绑定其他账号!")
user.phone = phone
await user.save()
if await request.app.state.redis.get(f'{RedisKeyConfig.USER_INFO.key}:{user.id}'):
await request.app.state.redis.delete(f'{RedisKeyConfig.USER_INFO.key}:{user.id}')
@ -500,15 +500,16 @@ async def update_user_phone(request: Request, password: str = Form(description="
@userAPI.post("/updateEmail", response_class=JSONResponse, response_model=BaseResponse, summary="用户更新邮箱")
@Log(title="用户更新邮箱", business_type=BusinessType.UPDATE)
async def update_user_email(request: Request, password: str = Form(description="用户密码"),
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):
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):
password = await Password.get_password_hash(password)
if user.password != password:
return Response.error("更改失败,请正确输入旧密码")
emailStatus = await User.filter(email=email,del_flag=1).count()
emailStatus = await User.filter(email=email, del_flag=1).count()
if emailStatus:
return Response.error(f"更改失败,邮箱:{email}已绑定其他账号!")
user.email=email
user.email = email
await user.save()
if await request.app.state.redis.get(f'{RedisKeyConfig.USER_INFO.key}:{user.id}'):
await request.app.state.redis.delete(f'{RedisKeyConfig.USER_INFO.key}:{user.id}')

View File

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

View File

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

View File

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