Skip to content

Commit aa84968

Browse files
author
gaozhe
committed
style: 用户数据隔离
1 parent 3bd417a commit aa84968

File tree

34 files changed

+2740
-1092
lines changed

34 files changed

+2740
-1092
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from app.admin.api.v1.sys import role, user
1+
from app.admin.api.v1.sys import menu, role, user
22
from fastapi import APIRouter
33

44
router = APIRouter(prefix='/sys')
55
router.include_router(user.router, prefix='/users', tags=['用户管理'])
66
router.include_router(role.router, prefix='/roles', tags=['角色管理'])
7+
router.include_router(menu.router, prefix='/menus', tags=['菜单管理'])
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from typing import Annotated
2+
3+
from app.admin.schema.menu import CreateMenuParam, GetMenuDetail, GetMenuTree, UpdateMenuParam
4+
from app.admin.service.menu_service import menu_service
5+
from common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base
6+
from common.security.permission import RequestPermission
7+
from common.security.rbac import DependsRBAC
8+
from database.db import CurrentSession, CurrentSessionTransaction
9+
from fastapi import APIRouter, Depends, Path
10+
11+
router = APIRouter()
12+
13+
14+
@router.get(
15+
'/tree',
16+
summary='获取菜单树',
17+
dependencies=[
18+
Depends(RequestPermission('sys:menu:list')),
19+
DependsRBAC,
20+
],
21+
)
22+
async def get_menu_tree(db: CurrentSession) -> ResponseSchemaModel[list[GetMenuTree]]:
23+
data = await menu_service.get_all(db=db)
24+
return response_base.success(data=data)
25+
26+
27+
@router.get(
28+
'',
29+
summary='获取所有菜单(平铺)',
30+
dependencies=[
31+
Depends(RequestPermission('sys:menu:list')),
32+
DependsRBAC,
33+
],
34+
)
35+
async def get_menus(db: CurrentSession) -> ResponseSchemaModel[list[GetMenuDetail]]:
36+
data = await menu_service.get_all_flat(db=db)
37+
return response_base.success(data=data)
38+
39+
40+
@router.get(
41+
'/{pk}',
42+
summary='获取菜单详情',
43+
dependencies=[
44+
Depends(RequestPermission('sys:menu:list')),
45+
DependsRBAC,
46+
],
47+
)
48+
async def get_menu(
49+
db: CurrentSession,
50+
pk: Annotated[int, Path(description='菜单 ID')],
51+
) -> ResponseSchemaModel[GetMenuDetail]:
52+
data = await menu_service.get(db=db, pk=pk)
53+
return response_base.success(data=data)
54+
55+
56+
@router.post(
57+
'',
58+
summary='创建菜单',
59+
dependencies=[
60+
Depends(RequestPermission('sys:menu:add')),
61+
DependsRBAC,
62+
],
63+
)
64+
async def create_menu(db: CurrentSessionTransaction, obj: CreateMenuParam) -> ResponseModel:
65+
await menu_service.create(db=db, obj=obj)
66+
return response_base.success()
67+
68+
69+
@router.put(
70+
'/{pk}',
71+
summary='更新菜单',
72+
dependencies=[
73+
Depends(RequestPermission('sys:menu:edit')),
74+
DependsRBAC,
75+
],
76+
)
77+
async def update_menu(
78+
db: CurrentSessionTransaction,
79+
pk: Annotated[int, Path(description='菜单 ID')],
80+
obj: UpdateMenuParam,
81+
) -> ResponseModel:
82+
count = await menu_service.update(db=db, pk=pk, obj=obj)
83+
if count > 0:
84+
return response_base.success()
85+
return response_base.fail()
86+
87+
88+
@router.delete(
89+
'/{pk}',
90+
summary='删除菜单',
91+
dependencies=[
92+
Depends(RequestPermission('sys:menu:del')),
93+
DependsRBAC,
94+
],
95+
)
96+
async def delete_menu(
97+
db: CurrentSessionTransaction,
98+
pk: Annotated[int, Path(description='菜单 ID')],
99+
) -> ResponseModel:
100+
count = await menu_service.delete(db=db, pk=pk)
101+
if count > 0:
102+
return response_base.success()
103+
return response_base.fail()

backend/app/admin/api/v1/sys/user.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020
router = APIRouter()
2121

2222

23-
@router.get('/{pk}', summary='获取用户信息', dependencies=[DependsJwtAuth])
23+
@router.get(
24+
'/{pk}',
25+
summary='获取用户信息',
26+
dependencies=[
27+
Depends(RequestPermission('sys:user:list')),
28+
DependsRBAC,
29+
],
30+
)
2431
async def get_userinfo(
2532
db: CurrentSession,
2633
pk: Annotated[int, Path(description='用户 ID')],
@@ -29,7 +36,14 @@ async def get_userinfo(
2936
return response_base.success(data=data)
3037

3138

32-
@router.get('/{pk}/roles', summary='获取用户所有角色', dependencies=[DependsJwtAuth])
39+
@router.get(
40+
'/{pk}/roles',
41+
summary='获取用户所有角色',
42+
dependencies=[
43+
Depends(RequestPermission('sys:user:list')),
44+
DependsRBAC,
45+
],
46+
)
3347
async def get_user_roles(
3448
db: CurrentSession, pk: Annotated[int, Path(description='用户 ID')]
3549
) -> ResponseSchemaModel[list[GetRoleDetail]]:
@@ -41,7 +55,8 @@ async def get_user_roles(
4155
'',
4256
summary='分页获取所有用户',
4357
dependencies=[
44-
DependsJwtAuth,
58+
Depends(RequestPermission('sys:user:list')),
59+
DependsRBAC,
4560
DependsPagination,
4661
],
4762
)
@@ -55,7 +70,14 @@ async def get_users_paginated(
5570
return response_base.success(data=page_data)
5671

5772

58-
@router.post('', summary='创建用户', dependencies=[DependsSuperUser])
73+
@router.post(
74+
'',
75+
summary='创建用户',
76+
dependencies=[
77+
Depends(RequestPermission('sys:user:add')),
78+
DependsRBAC,
79+
],
80+
)
5981
async def create_user(
6082
db: CurrentSessionTransaction, obj: AddUserParam
6183
) -> ResponseSchemaModel[GetUserInfoWithRelationDetail]:
@@ -64,7 +86,14 @@ async def create_user(
6486
return response_base.success(data=data)
6587

6688

67-
@router.put('/{pk}', summary='更新用户信息', dependencies=[DependsSuperUser])
89+
@router.put(
90+
'/{pk}',
91+
summary='更新用户信息',
92+
dependencies=[
93+
Depends(RequestPermission('sys:user:edit')),
94+
DependsRBAC,
95+
],
96+
)
6897
async def update_user(
6998
db: CurrentSessionTransaction,
7099
pk: Annotated[int, Path(description='用户 ID')],
@@ -76,7 +105,11 @@ async def update_user(
76105
return response_base.fail()
77106

78107

79-
@router.put('/{pk}/permissions', summary='更新用户权限', dependencies=[DependsSuperUser])
108+
@router.put(
109+
'/{pk}/permissions',
110+
summary='更新用户权限',
111+
dependencies=[DependsSuperUser],
112+
)
80113
async def update_user_permission(
81114
db: CurrentSessionTransaction,
82115
request: Request,
@@ -99,7 +132,14 @@ async def update_user_password(
99132
return response_base.fail()
100133

101134

102-
@router.put('/{pk}/password', summary='重置用户密码', dependencies=[DependsSuperUser])
135+
@router.put(
136+
'/{pk}/password',
137+
summary='重置用户密码',
138+
dependencies=[
139+
Depends(RequestPermission('sys:user:password:reset')),
140+
DependsRBAC,
141+
],
142+
)
103143
async def reset_user_password(
104144
db: CurrentSessionTransaction,
105145
pk: Annotated[int, Path(description='用户 ID')],

backend/app/admin/crud/crud_admin_agent.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,16 @@ async def get_filter_list(
5151
async def delete_agent(self, db: AsyncSession, agent_id: int) -> int:
5252
return await self.delete_model(db, agent_id)
5353

54+
async def get_my_agents(self, user_id: int) -> Select:
55+
return await self.select_order(
56+
'updated_time',
57+
'desc',
58+
load_options=[
59+
noload(self.model.category),
60+
selectinload(self.model.user),
61+
],
62+
user_id=user_id,
63+
)
64+
5465

5566
agent_admin_server_dao: CRUDAgentAdminServer = CRUDAgentAdminServer(AgentServer)

backend/app/admin/crud/crud_admin_mcp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,16 @@ async def get_filter_list(
5656
**filters,
5757
)
5858

59+
async def get_my_mcps(self, user_id: int) -> Select:
60+
return await self.select_order(
61+
'updated_time',
62+
'desc',
63+
load_options=[
64+
selectinload(self.model.category).options(noload(McpCategory.mcp_servers)),
65+
selectinload(self.model.user),
66+
],
67+
user_id=user_id,
68+
)
69+
5970

6071
mcp_admin_server_dao: CRUDMcpAdminServer = CRUDMcpAdminServer(McpServer)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from collections.abc import Sequence
2+
3+
from app.admin.model import Menu
4+
from app.admin.schema.menu import CreateMenuParam, UpdateMenuParam
5+
from sqlalchemy import select
6+
from sqlalchemy.ext.asyncio import AsyncSession
7+
from sqlalchemy_crud_plus import CRUDPlus
8+
9+
10+
class CRUDMenu(CRUDPlus[Menu]):
11+
"""菜单数据库操作类"""
12+
13+
async def get(self, db: AsyncSession, menu_id: int) -> Menu | None:
14+
return await self.select_model(db, menu_id)
15+
16+
async def get_all(self, db: AsyncSession) -> Sequence[Menu]:
17+
"""获取所有菜单,按 sort 排序"""
18+
result = await db.execute(select(Menu).order_by(Menu.sort, Menu.id))
19+
return result.scalars().all()
20+
21+
async def create(self, db: AsyncSession, obj: CreateMenuParam) -> None:
22+
await self.create_model(db, obj)
23+
24+
async def update(self, db: AsyncSession, menu_id: int, obj: UpdateMenuParam) -> int:
25+
return await self.update_model(db, menu_id, obj)
26+
27+
async def delete(self, db: AsyncSession, menu_id: int) -> int:
28+
return await self.delete_model(db, menu_id)
29+
30+
31+
menu_dao: CRUDMenu = CRUDMenu(Menu)

backend/app/admin/crud/crud_opera_log.py

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
# -*- coding: utf-8 -*-
31
from app.admin.model import OperaLog
42
from app.admin.schema.opera_log import CreateOperaLogParam
53
from sqlalchemy import Select
@@ -31,26 +29,6 @@ async def get_select(self, username: str | None, status: int | None, ip: str | N
3129

3230
return await self.select_order('created_time', 'desc', **filters)
3331

34-
async def get_list(self, username: str | None, status: int | None, ip: str | None) -> Select:
35-
"""
36-
获取操作日志列表
37-
38-
:param username: 用户名
39-
:param status: 操作状态
40-
:param ip: IP 地址
41-
:return:
42-
"""
43-
filters = {}
44-
45-
if username is not None:
46-
filters['username__like'] = f'%{username}%'
47-
if status is not None:
48-
filters['status__eq'] = status
49-
if ip is not None:
50-
filters['ip__like'] = f'%{ip}%'
51-
52-
return await self.select_order('created_time', 'desc', **filters)
53-
5432
async def create(self, db: AsyncSession, obj: CreateOperaLogParam) -> None:
5533
"""
5634
创建操作日志

backend/app/admin/schema/mcp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ class GetAdminMcpDetail(SchemaBase):
3939
is_public: int | None = Field(None, description='是否公开')
4040

4141

42+
class MyMcpDetail(SchemaBase):
43+
id: int = Field(description='id')
44+
server_title: str = Field(description='名称')
45+
server_name: str = Field(description='mcp name')
46+
description: str | None = Field(None, description='描述')
47+
server_type: str = Field(description='类型')
48+
is_public: bool | None = Field(None, description='是否公开')
49+
created_time: datetime = Field(description='创建时间')
50+
updated_time: datetime | None = Field(None, description='更新时间')
51+
52+
4253
class UpdateMcpServerParam(SchemaBase):
4354
server_title: str | None = Field(None, description='名称')
4455
description: str | None = Field(None, description='描述')

backend/app/admin/schema/user.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import datetime
44
from typing import Annotated, Any
55

6-
from app.admin.schema.role import GetRoleDetail
6+
from app.admin.schema.role import GetRoleWithRelationDetail
77
from common.enums import StatusType
88
from common.schema import CustomEmailStr, CustomPhoneNumber, SchemaBase, ser_string
99
from pydantic import ConfigDict, Field, HttpUrl, PlainSerializer, model_validator
@@ -97,7 +97,7 @@ class GetUserInfoWithRelationDetail(GetUserInfoDetail):
9797

9898
model_config = ConfigDict(from_attributes=True)
9999

100-
roles: list[GetRoleDetail] = Field(default=[], description='角色列表')
100+
roles: list[GetRoleWithRelationDetail] = Field(default=[], description='角色列表')
101101

102102

103103
class GetCurrentUserInfoWithRelationDetail(GetUserInfoWithRelationDetail):

backend/app/admin/service/admin_agent_service.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,9 @@ async def update_agent(
4444
async def delete_agent(db: AsyncSession, agent_id: int) -> int:
4545
return await agent_admin_server_dao.delete_agent(db, agent_id)
4646

47+
@staticmethod
48+
async def get_my_agents(*, user_id: int) -> Select:
49+
return await agent_admin_server_dao.get_my_agents(user_id=user_id)
50+
4751

4852
agent_admin_server_service: AgentAdminServerService = AgentAdminServerService()

0 commit comments

Comments
 (0)