Skip to content

Commit daf7b60

Browse files
authored
Merge pull request #685 from actiontech/chore/sqle-ee-issue-2448
[feature]: add permission control for navigation menus and routing
2 parents 328a4f3 + 99407d6 commit daf7b60

File tree

17 files changed

+931
-55
lines changed

17 files changed

+931
-55
lines changed

packages/base/src/App.tsx

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ import { StyledEngineProvider, ThemeProvider } from '@mui/system';
1414
import {
1515
EmptyBox,
1616
HeaderProgress,
17+
LocalStorageWrapper,
1718
SpinIndicator,
1819
useTypedNavigate
1920
} from '@actiontech/shared';
2021
import { useNotificationContext } from '@actiontech/shared/lib/hooks';
21-
import { SupportLanguage, SupportTheme } from '@actiontech/shared/lib/enum';
22+
import {
23+
StorageKey,
24+
SupportLanguage,
25+
SupportTheme
26+
} from '@actiontech/shared/lib/enum';
2227
import Nav from './page/Nav';
2328
import {
2429
useChangeTheme,
@@ -57,6 +62,7 @@ import sharedEmitterKey from '@actiontech/shared/lib/data/EmitterKey';
5762
import useRecentlySelectedZone from './hooks/useRecentlySelectedZone';
5863
import { debounce } from 'lodash';
5964
import './index.less';
65+
import { IUserBindProject } from '@actiontech/shared/lib/api/base/service/common';
6066

6167
dayjs.extend(updateLocale);
6268
dayjs.updateLocale('zh-cn', {
@@ -113,7 +119,9 @@ function App() {
113119
const {
114120
isUserInfoFetched,
115121
theme,
116-
language: currentLanguage
122+
language: currentLanguage,
123+
username,
124+
bindProjects
117125
} = useCurrentUser();
118126

119127
const { fetchModuleSupportStatus, isFeatureSupportFetched } =
@@ -141,13 +149,37 @@ function App() {
141149
);
142150
// #endif
143151

152+
const catchProjectID = useMemo<string>(() => {
153+
const data = LocalStorageWrapper.get(StorageKey.DMS_Project_Catch);
154+
try {
155+
const recentlyProjectsRecord = JSON.parse(data || '{}');
156+
const localData: Pick<IUserBindProject, 'project_id' | 'project_name'>[] =
157+
recentlyProjectsRecord[username] ?? [];
158+
const recentlyProjects =
159+
localData.filter((v) =>
160+
bindProjects.some((project) => project.project_id === v.project_id)
161+
) ?? [];
162+
163+
return recentlyProjects[0]?.project_id ?? '';
164+
} catch (error) {
165+
// eslint-disable-next-line no-console
166+
console.error(error);
167+
return '';
168+
}
169+
}, [bindProjects, username]);
170+
144171
const AuthRouterConfigData = useMemo(() => {
145172
const filterRoutesByPermission: (
146173
routes: RouterConfigItem[]
147174
) => RouterConfigItem[] = (routes) => {
148175
const verifiedRoutes: RouterConfigItem[] = [];
149176
return routes.reduce((acc, route) => {
150-
if (route.permission && !checkPagePermission(route.permission)) {
177+
if (
178+
route.permission &&
179+
!checkPagePermission(route.permission, {
180+
targetProjectID: catchProjectID
181+
})
182+
) {
151183
return acc;
152184
}
153185
if (route.children) {
@@ -166,7 +198,12 @@ function App() {
166198
return filterRoutesByPermission(AuthRouterConfig);
167199
}
168200
return AuthRouterConfig;
169-
}, [checkPagePermission, isFeatureSupportFetched, isUserInfoFetched]);
201+
}, [
202+
checkPagePermission,
203+
catchProjectID,
204+
isFeatureSupportFetched,
205+
isUserInfoFetched
206+
]);
170207

171208
const elements = useRoutes(
172209
token ? (AuthRouterConfigData as RouteObject[]) : unAuthRouterConfig

packages/base/src/page/Nav/SideMenu/MenuList/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ const MenuList: React.FC<Props> = ({ projectID }) => {
7373
): CustomMenuItemType[] => {
7474
return requiredMenus.filter((menu) => {
7575
if (menu?.permission) {
76-
return checkPagePermission(menu.permission);
76+
return checkPagePermission(menu.permission, {
77+
targetProjectID: projectID
78+
});
7779
}
7880

7981
if ((menu as SubMenuType)?.children) {

packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ exports[`test genMenuItemsWithMenuStructTree should match snapshot 4`] = `
261261
>
262262
流水线配置
263263
</ForwardRef(TypedLink)>,
264+
"permission": "page:pipeline_configuration",
264265
"structKey": "pipeline-configuration",
265266
"to": "/sqle/project/600300/pipeline-configuration",
266267
},
@@ -282,6 +283,7 @@ exports[`test genMenuItemsWithMenuStructTree should match snapshot 4`] = `
282283
>
283284
SQL管控
284285
</ForwardRef(TypedLink)>,
286+
"permission": "page:sql_management",
285287
"structKey": "sql-management",
286288
"to": "/sqle/project/600300/sql-management",
287289
},
@@ -296,6 +298,7 @@ exports[`test genMenuItemsWithMenuStructTree should match snapshot 4`] = `
296298
>
297299
SQL管控配置
298300
</ForwardRef(TypedLink)>,
301+
"permission": "page:sql_management_conf",
299302
"structKey": "sql-management-conf",
300303
"to": "/sqle/project/600300/sql-management-conf",
301304
},

packages/base/src/page/Nav/SideMenu/MenuList/menus/sqle.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ const sqlManagementMenuItem: GenerateMenuItemI18nConfig = (projectID) => ({
8484
}),
8585
icon: <ManagementFilled width={18} height={18} />,
8686
key: `sqle/project/${SIDE_MENU_DATA_PLACEHOLDER_KEY}/sql-management`,
87-
structKey: 'sql-management'
87+
structKey: 'sql-management',
88+
permission: PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT
8889
});
8990

9091
const projectRuleTemplateMenuItem: GenerateMenuItemI18nConfig = (
@@ -149,7 +150,8 @@ const sqlManagementConf: GenerateMenuItemI18nConfig = (projectID) => ({
149150
}),
150151
icon: <PlanFilled width={18} height={18} />,
151152
key: `sqle/project/${SIDE_MENU_DATA_PLACEHOLDER_KEY}/sql-management-conf`,
152-
structKey: 'sql-management-conf'
153+
structKey: 'sql-management-conf',
154+
permission: PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT_CONF
153155
});
154156

155157
const pushRuleConfiguration: GenerateMenuItemI18nConfig = (projectID) => ({
@@ -169,7 +171,8 @@ const pipelineConfiguration: GenerateMenuItemI18nConfig = (projectID) => ({
169171
}),
170172
icon: <PipelineOutlined width={18} height={18} />,
171173
key: `sqle/project/${SIDE_MENU_DATA_PLACEHOLDER_KEY}/pipeline-configuration`,
172-
structKey: 'pipeline-configuration'
174+
structKey: 'pipeline-configuration',
175+
permission: PERMISSIONS.PAGES.SQLE.PIPELINE_CONFIGURATION
173176
});
174177

175178
const versionManagement: GenerateMenuItemI18nConfig = (projectID) => ({

packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ exports[`usePermission should match snapshot 1`] = `
3232
"TEST": "action:test_db_service",
3333
"TEST_IN_MORE_BUTTON": "action:test_db_service_in_more_button",
3434
},
35+
"GLOBAL_DASHBOARD": {
36+
"PENDING_SQL_NAVIGATE_TO_SQL_MANAGEMENT": "action:global_dashboard_pending_sql_navigate_to_sql_management",
37+
},
3538
"GLOBAL_DATA_SOURCE": {
3639
"ADD": "action:add_global_db_service",
3740
"BATCH_IMPORT": "action:batch_import_global_db_service",
@@ -239,8 +242,11 @@ exports[`usePermission should match snapshot 1`] = `
239242
"SQLE": {
240243
"KNOWLEDGE": "page:knowledge",
241244
"OPERATION_RECORD": "page:operation_record",
245+
"PIPELINE_CONFIGURATION": "page:pipeline_configuration",
242246
"REPORT_STATISTICS": "page:report_statistics",
243247
"RULE_MANAGEMENT": "page:rule_management",
248+
"SQL_MANAGEMENT": "page:sql_management",
249+
"SQL_MANAGEMENT_CONF": "page:sql_management_conf",
244250
"SQL_OPTIMIZATION": "page:sql_optimization",
245251
},
246252
},
@@ -954,6 +960,15 @@ exports[`usePermission should match snapshot 2`] = `
954960
"id": "action:export_workflow",
955961
"type": "action",
956962
},
963+
"action:global_dashboard_pending_sql_navigate_to_sql_management": {
964+
"id": "action:global_dashboard_pending_sql_navigate_to_sql_management",
965+
"projectManager": true,
966+
"role": [
967+
"admin",
968+
"systemAdministrator",
969+
],
970+
"type": "action",
971+
},
957972
"action:global_rule_template_create_rule_template": {
958973
"id": "action:global_rule_template_create_rule_template",
959974
"role": [
@@ -1535,6 +1550,15 @@ exports[`usePermission should match snapshot 2`] = `
15351550
],
15361551
"type": "page",
15371552
},
1553+
"page:pipeline_configuration": {
1554+
"id": "page:pipeline_configuration",
1555+
"projectManager": true,
1556+
"role": [
1557+
"admin",
1558+
"systemAdministrator",
1559+
],
1560+
"type": "page",
1561+
},
15381562
"page:report_statistics": {
15391563
"id": "page:report_statistics",
15401564
"role": [
@@ -1563,6 +1587,24 @@ exports[`usePermission should match snapshot 2`] = `
15631587
],
15641588
"type": "page",
15651589
},
1590+
"page:sql_management": {
1591+
"id": "page:sql_management",
1592+
"projectManager": true,
1593+
"role": [
1594+
"admin",
1595+
"systemAdministrator",
1596+
],
1597+
"type": "page",
1598+
},
1599+
"page:sql_management_conf": {
1600+
"id": "page:sql_management_conf",
1601+
"projectManager": true,
1602+
"role": [
1603+
"admin",
1604+
"systemAdministrator",
1605+
],
1606+
"type": "page",
1607+
},
15661608
"page:sql_optimization": {
15671609
"id": "page:sql_optimization",
15681610
"moduleSupport": [

packages/shared/lib/features/usePermission/__tests__/index.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,15 @@ describe('usePermission', () => {
157157
[SystemRole.systemAdministrator]: false,
158158
[SystemRole.projectDirector]: false,
159159
[SystemRole.auditAdministrator]: false
160-
}
160+
},
161+
bindProjects: [
162+
{
163+
project_id: mockProjectInfo.projectID,
164+
project_name: 'test',
165+
is_manager: true,
166+
archived: false
167+
}
168+
]
161169
});
162170
const { result } = renderHook(() => usePermission());
163171

@@ -184,6 +192,9 @@ describe('usePermission', () => {
184192
PERMISSIONS.PAGES.SQLE.SQL_OPTIMIZATION
185193
)
186194
).toBeFalsy();
195+
expect(
196+
result.current.checkPagePermission(PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT)
197+
).toBeTruthy();
187198
});
188199

189200
it('should check action permission correctly', () => {

packages/shared/lib/features/usePermission/index.type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,7 @@ export type CheckActionPermissionOtherValues<T> = {
4646
authDataSourceId?: string;
4747
targetProjectID?: string;
4848
};
49+
50+
export type CheckPagePermissionOtherValues = {
51+
targetProjectID?: string;
52+
};

packages/shared/lib/features/usePermission/permissionManifest.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,34 @@ export const PERMISSION_MANIFEST: Record<
114114
SystemRole.certainProjectManager
115115
]
116116
},
117+
[PERMISSIONS.PAGES.SQLE.PIPELINE_CONFIGURATION]: {
118+
id: PERMISSIONS.PAGES.SQLE.PIPELINE_CONFIGURATION,
119+
type: 'page',
120+
role: [SystemRole.admin, SystemRole.systemAdministrator],
121+
projectManager: true
122+
},
123+
[PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT]: {
124+
id: PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT,
125+
type: 'page',
126+
role: [SystemRole.admin, SystemRole.systemAdministrator],
127+
projectManager: true
128+
},
129+
[PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT_CONF]: {
130+
id: PERMISSIONS.PAGES.SQLE.SQL_MANAGEMENT_CONF,
131+
type: 'page',
132+
role: [SystemRole.admin, SystemRole.systemAdministrator],
133+
projectManager: true
134+
},
117135
// action
136+
// global dashboard
137+
[PERMISSIONS.ACTIONS.BASE.GLOBAL_DASHBOARD
138+
.PENDING_SQL_NAVIGATE_TO_SQL_MANAGEMENT]: {
139+
id: PERMISSIONS.ACTIONS.BASE.GLOBAL_DASHBOARD
140+
.PENDING_SQL_NAVIGATE_TO_SQL_MANAGEMENT,
141+
type: 'action',
142+
role: [SystemRole.admin, SystemRole.systemAdministrator],
143+
projectManager: true
144+
},
118145

119146
//cloud beaver
120147
[PERMISSIONS.ACTIONS.BASE.CLOUD_BEAVER.EXPORT]: {

packages/shared/lib/features/usePermission/permissions.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export const PERMISSIONS = {
1313
SQL_OPTIMIZATION: 'page:sql_optimization',
1414
REPORT_STATISTICS: 'page:report_statistics',
1515
RULE_MANAGEMENT: 'page:rule_management',
16-
KNOWLEDGE: 'page:knowledge'
16+
KNOWLEDGE: 'page:knowledge',
17+
PIPELINE_CONFIGURATION: 'page:pipeline_configuration',
18+
SQL_MANAGEMENT: 'page:sql_management',
19+
SQL_MANAGEMENT_CONF: 'page:sql_management_conf'
1720
}
1821
},
1922
ACTIONS: {
@@ -30,6 +33,10 @@ export const PERMISSIONS = {
3033
DELETE: 'action:delete_role'
3134
}
3235
},
36+
GLOBAL_DASHBOARD: {
37+
PENDING_SQL_NAVIGATE_TO_SQL_MANAGEMENT:
38+
'action:global_dashboard_pending_sql_navigate_to_sql_management'
39+
},
3340
GLOBAL_DATA_SOURCE: {
3441
EDIT: 'action:edit_global_db_service',
3542
DELETE: 'action:delete_global_db_service',

packages/shared/lib/features/usePermission/usePermission.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import useCurrentUser from '../useCurrentUser';
33
import { PERMISSION_MANIFEST, PermissionDetail } from './permissionManifest';
44
import { PermissionsConstantType } from './permissions';
55
import useCurrentProject from '../useCurrentProject';
6+
67
import {
78
ActiontechTableActionsWithPermissions,
89
ActiontechTableToolbarActionWithPermissions,
9-
CheckActionPermissionOtherValues
10+
CheckActionPermissionOtherValues,
11+
CheckPagePermissionOtherValues
1012
} from './index.type';
1113
import { ActiontechTableProps } from '../../components/ActiontechTable';
1214
import {
@@ -44,7 +46,6 @@ const usePermission = () => {
4446
},
4547
[bindProjects, projectID]
4648
);
47-
4849
const checkDbServicePermission = useCallback(
4950
(
5051
opPermissionType: OpPermissionItemOpPermissionTypeEnum,
@@ -111,13 +112,23 @@ const usePermission = () => {
111112
);
112113

113114
const checkPagePermission = useCallback(
114-
(requiredPermission: PermissionsConstantType): boolean => {
115+
(
116+
requiredPermission: PermissionsConstantType,
117+
otherValues?: CheckPagePermissionOtherValues
118+
): boolean => {
119+
const { targetProjectID } = otherValues ?? {};
115120
const permissionDetails = PERMISSION_MANIFEST[requiredPermission];
121+
const projectAttributesStatus =
122+
getProjectAttributesStatus(targetProjectID);
123+
116124
return (
117-
checkRoles(permissionDetails) && checkModuleSupport(permissionDetails)
125+
((projectAttributesStatus.isManager &&
126+
permissionDetails.projectManager === true) ||
127+
checkRoles(permissionDetails)) &&
128+
checkModuleSupport(permissionDetails)
118129
);
119130
},
120-
[checkModuleSupport, checkRoles]
131+
[checkModuleSupport, checkRoles, getProjectAttributesStatus]
121132
);
122133

123134
const checkActionPermission = useCallback(

0 commit comments

Comments
 (0)