Skip to content

Commit 8210e10

Browse files
committed
update codes
1 parent addd0a1 commit 8210e10

File tree

9 files changed

+105
-18
lines changed

9 files changed

+105
-18
lines changed

backend/app/admin/crud/crud_role.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from sqlalchemy.orm import selectinload
77
from sqlalchemy_crud_plus import CRUDPlus
88

9-
from backend.app.admin.model import Menu, Role, User
10-
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleMenuParam, UpdateRoleParam
9+
from backend.app.admin.model import Dept, Menu, Role, User
10+
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleDeptParam, UpdateRoleMenuParam, UpdateRoleParam
1111

1212

1313
class CRUDRole(CRUDPlus[Role]):
@@ -122,6 +122,21 @@ async def update_menus(self, db, role_id: int, menu_ids: UpdateRoleMenuParam) ->
122122
current_role.menus = menus.scalars().all()
123123
return len(current_role.menus)
124124

125+
async def update_depts(self, db, role_id: int, dept_ids: UpdateRoleDeptParam) -> int:
126+
"""
127+
更新角色部门
128+
129+
:param db:
130+
:param role_id:
131+
:param dept_ids:
132+
:return:
133+
"""
134+
stmt = select(Dept).where(Dept.id.in_(dept_ids.depts))
135+
depts = await db.execute(stmt)
136+
current_role = await self.get_with_relation(db, role_id)
137+
current_role.depts = depts.scalars().all()
138+
return len(current_role.depts)
139+
125140
async def delete(self, db, role_id: list[int]) -> int:
126141
"""
127142
删除角色

backend/app/admin/crud/crud_user.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,10 @@ async def get_list(self, dept: int = None, username: str = None, phone: str = No
183183
"""
184184
stmt = (
185185
select(self.model)
186-
.options(selectinload(self.model.dept))
187-
.options(selectinload(self.model.roles).selectinload(Role.menus))
186+
.options(
187+
selectinload(self.model.dept),
188+
selectinload(self.model.roles).selectinload(Role.menus),
189+
)
188190
.order_by(desc(self.model.join_time))
189191
)
190192
where_list = []
@@ -297,10 +299,10 @@ async def get_with_relation(self, db: AsyncSession, *, user_id: int = None, user
297299
:param username:
298300
:return:
299301
"""
300-
stmt = (
301-
select(self.model)
302-
.options(selectinload(self.model.dept))
303-
.options(selectinload(self.model.roles).joinedload(Role.menus))
302+
stmt = select(self.model).options(
303+
selectinload(self.model.dept),
304+
selectinload(self.model.roles).joinedload(Role.menus),
305+
selectinload(self.model.roles).joinedload(Role.depts),
304306
)
305307
filters = []
306308
if user_id:

backend/app/admin/model/sys_dept.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ class Dept(Base):
3232

3333
# 部门用户一对多
3434
users: Mapped[list['User']] = relationship(init=False, back_populates='dept') # noqa: F821
35+
36+
# 部门角色多对多
37+
roles: Mapped[list['Role']] = relationship(init=False, back_populates='dept') # noqa: F821

backend/app/admin/model/sys_role.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sqlalchemy.dialects.mysql import LONGTEXT
55
from sqlalchemy.orm import Mapped, mapped_column, relationship
66

7-
from backend.app.admin.model.m2m import sys_role_menu, sys_user_role
7+
from backend.app.admin.model.m2m import sys_role_dept, sys_role_menu, sys_user_role
88
from backend.common.model import Base, id_key
99

1010

@@ -16,7 +16,8 @@ class Role(Base):
1616
id: Mapped[id_key] = mapped_column(init=False)
1717
name: Mapped[str] = mapped_column(String(20), unique=True, comment='角色名称')
1818
data_scope: Mapped[int | None] = mapped_column(
19-
default=2, comment='权限范围(0: 全部数据,1: 本人数据,2: 所在部门数据,3: 所在部门及以下数据,4: 自定义数据)'
19+
default=0,
20+
comment='权限范围(0: 全部数据,1: 自定义数据,2: 所在部门及以下数据,3: 所在部门数据,4: 仅本人数据)',
2021
)
2122
status: Mapped[int] = mapped_column(default=1, comment='角色状态(0停用 1正常)')
2223
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')
@@ -26,3 +27,6 @@ class Role(Base):
2627

2728
# 角色菜单多对多
2829
menus: Mapped[list['Menu']] = relationship(init=False, secondary=sys_role_menu, back_populates='roles') # noqa: F821
30+
31+
# 角色部门多对多
32+
depts: Mapped[list['Dept']] = relationship(init=False, secondary=sys_role_dept, back_populates='roles') # noqa: F821

backend/app/admin/schema/role.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class UpdateRoleMenuParam(SchemaBase):
3030
menus: list[int]
3131

3232

33+
class UpdateRoleDeptParam(SchemaBase):
34+
depts: list[int]
35+
36+
3337
class GetRoleListDetails(RoleSchemaBase):
3438
model_config = ConfigDict(from_attributes=True)
3539

backend/app/admin/service/role_service.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
from fastapi import Request
66
from sqlalchemy import Select
77

8+
from backend.app.admin.crud.crud_dept import dept_dao
89
from backend.app.admin.crud.crud_menu import menu_dao
910
from backend.app.admin.crud.crud_role import role_dao
1011
from backend.app.admin.model import Role
11-
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleMenuParam, UpdateRoleParam
12+
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleDeptParam, UpdateRoleMenuParam, UpdateRoleParam
1213
from backend.common.exception import errors
1314
from backend.core.conf import settings
1415
from backend.database.db_mysql import async_db_session
@@ -77,6 +78,21 @@ async def update_role_menu(*, request: Request, pk: int, menu_ids: UpdateRoleMen
7778
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
7879
return count
7980

81+
@staticmethod
82+
async def update_role_dept(*, request: Request, pk: int, dept_ids: UpdateRoleDeptParam) -> int:
83+
async with async_db_session.begin() as db:
84+
role = await role_dao.get(db, pk)
85+
if not role:
86+
raise errors.NotFoundError(msg='角色不存在')
87+
for dept_id in dept_ids.depts:
88+
dept = await dept_dao.get(db, dept_id)
89+
if not dept:
90+
raise errors.NotFoundError(msg='部门不存在')
91+
count = await role_dao.update_depts(db, pk, dept_ids)
92+
if pk in [role.id for role in request.user.roles]:
93+
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
94+
return count
95+
8096
@staticmethod
8197
async def delete(*, pk: list[int]) -> int:
8298
async with async_db_session.begin() as db:

backend/common/security/jwt.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,13 @@ async def get_current_user(db: AsyncSession, pk: int) -> User:
183183
raise AuthorizationError(msg='用户已被锁定,请联系系统管理员')
184184
if user.dept_id:
185185
if not user.dept.status:
186-
raise AuthorizationError(msg='用户所属部门已锁定')
186+
raise AuthorizationError(msg='用户所属部门已被锁定,请联系系统管理员')
187187
if user.dept.del_flag:
188-
raise AuthorizationError(msg='用户所属部门已删除')
188+
raise AuthorizationError(msg='用户所属部门已被删除,请联系系统管理员')
189189
if user.roles:
190190
role_status = [role.status for role in user.roles]
191191
if all(status == 0 for status in role_status):
192-
raise AuthorizationError(msg='用户所属角色已锁定')
192+
raise AuthorizationError(msg='用户所属角色已被锁定,请联系系统管理员')
193193
return user
194194

195195

backend/common/security/permission.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
from typing import Any
4+
35
from fastapi import Request
6+
from sqlalchemy import Select, select
47

8+
from backend.app.admin.model import User
9+
from backend.app.admin.model.m2m import sys_role_dept
510
from backend.common.exception.errors import ServerError
611
from backend.core.conf import settings
712

@@ -24,3 +29,45 @@ async def __call__(self, request: Request):
2429
raise ServerError
2530
# 附加权限标识
2631
request.state.permission = self.value
32+
33+
34+
def filter_user_data_scope(request: Request, model: Any, stmt: Select) -> Select:
35+
"""
36+
获取用户数据范围
37+
38+
使用场景:对于非后台管理数据,需要在前端界面向用户进行展示的数据
39+
40+
:param request:
41+
:param model:
42+
:param stmt:
43+
:return:
44+
"""
45+
user_roles = request.user.roles
46+
dept_roles = request.user.dept.roles
47+
user_roles.extend(dept_roles)
48+
data_scope = min(role.data_scope for role in set(user_roles))
49+
50+
# 全部数据
51+
if data_scope == 0:
52+
stmt = stmt
53+
# 自定义数据
54+
elif data_scope == 1:
55+
stmt = stmt.where(
56+
model.create_user.in_(
57+
select(User.id)
58+
.select_from(sys_role_dept)
59+
.join(User, User.dept_id == sys_role_dept.c.dept_id)
60+
.where(sys_role_dept.c.role_id.in_(user_roles))
61+
)
62+
)
63+
# 所在部门及以下数据
64+
elif data_scope == 2:
65+
... # TODO
66+
# 所在部门数据
67+
elif data_scope == 3:
68+
stmt = stmt.where(select(User.id).where(User.dept_id == request.user.dept_id))
69+
# 仅本人数据
70+
elif data_scope == 4:
71+
stmt = stmt.where(model.create_user == request.user.id)
72+
73+
return stmt

backend/common/security/rbac.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ async def rbac_verify(self, request: Request, _token: str = DependsJwtAuth) -> N
8181
if not request.user.is_staff:
8282
raise AuthorizationError(msg='用户已被禁止后台管理操作,请联系系统管理员')
8383

84-
# 数据权限范围
85-
if any(role.data_scope == 1 for role in user_roles):
86-
return
87-
8884
# RBAC 鉴权
8985
if settings.PERMISSION_MODE == 'role-menu':
9086
path_auth_perm = getattr(request.state, 'permission', None)

0 commit comments

Comments
 (0)