From 37a4f971c8f9f6eb0fe5a8e721581999a8c7297c Mon Sep 17 00:00:00 2001 From: vben Date: Sat, 6 Jul 2024 13:28:08 +0800 Subject: [PATCH] feat: Improve the front-end and back-end permission mode and useAccess --- apps/backend-mock/package.json | 2 +- .../src/modules/auth/auth.controller.ts | 10 ++ .../src/modules/auth/auth.service.ts | 24 ++++ .../src/modules/menu/menu.controller.ts | 101 ++++++++++++++- apps/web-antd/src/apis/modules/user.ts | 9 +- .../src/router/routes/modules/demos.ts | 16 +-- apps/web-antd/src/store/modules/access.ts | 10 +- .../demos/access/backend/access-test-1.vue | 13 ++ .../demos/access/backend/access-test-2.vue | 13 ++ .../demos/access/backend/access-test-3.vue | 13 ++ .../demos/access/backend/button-control.vue | 115 +++++++++++++++++- .../src/views/demos/access/backend/index.vue | 98 ++++++++++++++- .../demos/access/frontend/access-test-1.vue | 2 +- .../demos/access/frontend/access-test-2.vue | 2 +- .../demos/access/frontend/access-test-3.vue | 2 +- .../demos/access/frontend/button-control.vue | 62 +++++++--- .../src/views/demos/access/frontend/index.vue | 6 - package.json | 4 +- .../@core/forward/preferences/src/types.ts | 6 +- .../forward/stores/src/modules/access.ts | 16 ++- .../business/access/src/code-authority.vue | 10 +- .../generate-routes-backend.ts | 1 + .../src/generate-menu-and-routes/index.ts | 12 +- .../business/access/src/role-authority.vue | 10 +- packages/business/access/src/use-access.ts | 32 ++++- packages/locales/src/langs/en-US.yaml | 6 +- packages/locales/src/langs/zh-CN.yaml | 6 +- 27 files changed, 522 insertions(+), 79 deletions(-) create mode 100644 apps/web-antd/src/views/demos/access/backend/access-test-1.vue create mode 100644 apps/web-antd/src/views/demos/access/backend/access-test-2.vue create mode 100644 apps/web-antd/src/views/demos/access/backend/access-test-3.vue diff --git a/apps/backend-mock/package.json b/apps/backend-mock/package.json index b9dc4988..e8b28c85 100644 --- a/apps/backend-mock/package.json +++ b/apps/backend-mock/package.json @@ -36,7 +36,7 @@ "@nestjs/cli": "^10.4.2", "@nestjs/schematics": "^10.1.2", "@types/express": "^4.17.21", - "@types/node": "^20.14.9", + "@types/node": "^20.14.10", "nodemon": "^3.1.4", "ts-node": "^10.9.2", "typescript": "^5.5.3" diff --git a/apps/backend-mock/src/modules/auth/auth.controller.ts b/apps/backend-mock/src/modules/auth/auth.controller.ts index 19fd3456..b61d3a20 100644 --- a/apps/backend-mock/src/modules/auth/auth.controller.ts +++ b/apps/backend-mock/src/modules/auth/auth.controller.ts @@ -19,6 +19,16 @@ import { AuthService } from './auth.service'; export class AuthController { constructor(private authService: AuthService) {} + /** + * 获取用户权限码 + * @param req + */ + @Get('getAccessCodes') + @HttpCode(HttpStatus.OK) + async getAccessCodes(@Request() req: Request) { + return await this.authService.getAccessCodes(req.user.username); + } + /** * 获取用户信息 * @param req diff --git a/apps/backend-mock/src/modules/auth/auth.service.ts b/apps/backend-mock/src/modules/auth/auth.service.ts index 37f4b68b..dc89f609 100644 --- a/apps/backend-mock/src/modules/auth/auth.service.ts +++ b/apps/backend-mock/src/modules/auth/auth.service.ts @@ -19,6 +19,30 @@ export class AuthService { * get user info * @param username */ + async getAccessCodes(username: string): Promise { + const user = await this.usersService.findOne(username); + + const mockCodes = [ + // super + { + codes: ['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010'], + userId: 0, + }, + { + // admin + codes: ['AC_100010', 'AC_100020', 'AC_100030'], + userId: 1, + }, + { + // user + codes: ['AC_1000001', 'AC_1000002'], + userId: 2, + }, + ]; + + return mockCodes.find((item) => item.userId === user.id)?.codes ?? []; + } + async getUserInfo(username: string): Promise> { const user = await this.usersService.findOne(username); const { password: _pass, ...userInfo } = user; diff --git a/apps/backend-mock/src/modules/menu/menu.controller.ts b/apps/backend-mock/src/modules/menu/menu.controller.ts index d5effc3a..6baa4187 100644 --- a/apps/backend-mock/src/modules/menu/menu.controller.ts +++ b/apps/backend-mock/src/modules/menu/menu.controller.ts @@ -10,7 +10,7 @@ export class MenuController { @HttpCode(HttpStatus.OK) async getAll(@Request() req: Request) { // 模拟请求延迟 - await sleep(1000); + await sleep(500); // 请求用户的id const userId = req.user.id; @@ -46,15 +46,110 @@ export class MenuController { ], }, ]; + + const createDemosMenus = (role: 'admin' | 'super' | 'user') => { + const roleWithMenus = { + admin: { + component: '/demos/access/backend/access-test-2', + meta: { + icon: 'mdi:button-cursor', + title: 'page.demos.access.access-test-2', + }, + name: 'AccessBackendTest2', + path: 'access-test-2', + }, + super: { + component: '/demos/access/backend/access-test-1', + meta: { + icon: 'mdi:button-cursor', + title: 'page.demos.access.access-test-1', + }, + name: 'AccessBackendTest1', + path: 'access-test-1', + }, + user: { + component: '/demos/access/backend/access-test-3', + meta: { + icon: 'mdi:button-cursor', + title: 'page.demos.access.access-test-3', + }, + name: 'AccessBackendTest3', + path: 'access-test-3', + }, + }; + + return [ + { + component: 'BasicLayout', + meta: { + icon: 'ic:baseline-view-in-ar', + keepAlive: true, + order: 1000, + title: 'page.demos.title', + }, + name: 'Demos', + path: '/demos', + redirect: '/demos/access', + children: [ + { + meta: { + icon: 'mdi:shield-key-outline', + title: 'page.demos.access.title', + }, + name: 'Access', + path: 'access', + redirect: '/demos/access/backend', + children: [ + { + name: 'AccessBackend', + path: 'backend', + meta: { + icon: 'mdi:cloud-key-outline', + title: 'page.demos.access.backend-control', + }, + redirect: '/demos/access/backend/page-control', + children: [ + { + name: 'AccessBackendPageControl', + path: 'page-control', + component: '/demos/access/backend/index', + meta: { + icon: 'mdi:page-previous-outline', + title: 'page.demos.access.page', + }, + }, + { + name: 'AccessBackendButtonControl', + path: 'button-control', + component: '/demos/access/backend/button-control', + meta: { + icon: 'mdi:button-cursor', + title: 'page.demos.access.button', + }, + }, + roleWithMenus[role], + ], + }, + ], + }, + ], + }, + ]; + }; + const MOCK_MENUS = [ { - menus: [...dashboardMenus], + menus: [...dashboardMenus, ...createDemosMenus('super')], userId: 0, }, { - menus: [...dashboardMenus], + menus: [...dashboardMenus, ...createDemosMenus('admin')], userId: 1, }, + { + menus: [...dashboardMenus, ...createDemosMenus('user')], + userId: 2, + }, ]; return MOCK_MENUS.find((item) => item.userId === userId)?.menus ?? []; diff --git a/apps/web-antd/src/apis/modules/user.ts b/apps/web-antd/src/apis/modules/user.ts index 42eb7025..87d052af 100644 --- a/apps/web-antd/src/apis/modules/user.ts +++ b/apps/web-antd/src/apis/modules/user.ts @@ -18,4 +18,11 @@ async function getUserInfo() { return requestClient.get('/auth/getUserInfo'); } -export { getUserInfo, userLogin }; +/** + * 获取用户权限码 + */ +async function getAccessCodes() { + return requestClient.get('/auth/getAccessCodes'); +} + +export { getAccessCodes, getUserInfo, userLogin }; diff --git a/apps/web-antd/src/router/routes/modules/demos.ts b/apps/web-antd/src/router/routes/modules/demos.ts index 288d8043..31b4d5e8 100644 --- a/apps/web-antd/src/router/routes/modules/demos.ts +++ b/apps/web-antd/src/router/routes/modules/demos.ts @@ -61,7 +61,7 @@ const routes: RouteRecordRaw[] = [ component: () => import('#/views/demos/access/frontend/access-test-1.vue'), meta: { - authority: ['admin'], + authority: ['super'], icon: 'mdi:button-cursor', title: $t('page.demos.access.access-test-1'), }, @@ -72,7 +72,7 @@ const routes: RouteRecordRaw[] = [ component: () => import('#/views/demos/access/frontend/access-test-2.vue'), meta: { - authority: ['user'], + authority: ['admin'], icon: 'mdi:button-cursor', title: $t('page.demos.access.access-test-2'), }, @@ -83,7 +83,7 @@ const routes: RouteRecordRaw[] = [ component: () => import('#/views/demos/access/frontend/access-test-3.vue'), meta: { - authority: ['super'], + authority: ['user'], icon: 'mdi:button-cursor', title: $t('page.demos.access.access-test-3'), }, @@ -109,16 +109,6 @@ const routes: RouteRecordRaw[] = [ title: $t('page.demos.access.page'), }, }, - { - name: 'AccessBackendButtonControl', - path: 'button-control', - component: () => - import('#/views/demos/access/frontend/button-control.vue'), - meta: { - icon: 'mdi:button-cursor', - title: $t('page.demos.access.button'), - }, - }, ], }, ], diff --git a/apps/web-antd/src/store/modules/access.ts b/apps/web-antd/src/store/modules/access.ts index 7b50ba42..5d979424 100644 --- a/apps/web-antd/src/store/modules/access.ts +++ b/apps/web-antd/src/store/modules/access.ts @@ -10,7 +10,7 @@ import { useCoreAccessStore } from '@vben-core/stores'; import { defineStore } from 'pinia'; -import { getUserInfo, userLogin } from '#/apis'; +import { getAccessCodes, getUserInfo, userLogin } from '#/apis'; export const useAccessStore = defineStore('access', () => { const coreStoreAccess = useCoreAccessStore(); @@ -55,9 +55,15 @@ export const useAccessStore = defineStore('access', () => { // 获取用户信息并存储到 accessStore 中 // Get user information and store it in accessStore - userInfo = await fetchUserInfo(); + const [fetchUserInfoResult, accessCodes] = await Promise.all([ + fetchUserInfo(), + getAccessCodes(), + ]); + + userInfo = fetchUserInfoResult; coreStoreAccess.setUserInfo(userInfo); + coreStoreAccess.setAccessCodes(accessCodes); onSuccess ? await onSuccess?.() diff --git a/apps/web-antd/src/views/demos/access/backend/access-test-1.vue b/apps/web-antd/src/views/demos/access/backend/access-test-1.vue new file mode 100644 index 00000000..9fe4a3b3 --- /dev/null +++ b/apps/web-antd/src/views/demos/access/backend/access-test-1.vue @@ -0,0 +1,13 @@ + + + diff --git a/apps/web-antd/src/views/demos/access/backend/access-test-2.vue b/apps/web-antd/src/views/demos/access/backend/access-test-2.vue new file mode 100644 index 00000000..526efac1 --- /dev/null +++ b/apps/web-antd/src/views/demos/access/backend/access-test-2.vue @@ -0,0 +1,13 @@ + + + diff --git a/apps/web-antd/src/views/demos/access/backend/access-test-3.vue b/apps/web-antd/src/views/demos/access/backend/access-test-3.vue new file mode 100644 index 00000000..38913e5a --- /dev/null +++ b/apps/web-antd/src/views/demos/access/backend/access-test-3.vue @@ -0,0 +1,13 @@ + + + diff --git a/apps/web-antd/src/views/demos/access/backend/button-control.vue b/apps/web-antd/src/views/demos/access/backend/button-control.vue index 75c76a44..664b913e 100644 --- a/apps/web-antd/src/views/demos/access/backend/button-control.vue +++ b/apps/web-antd/src/views/demos/access/backend/button-control.vue @@ -1,9 +1,118 @@ diff --git a/apps/web-antd/src/views/demos/access/backend/index.vue b/apps/web-antd/src/views/demos/access/backend/index.vue index 47ef44e3..ac5e9aa6 100644 --- a/apps/web-antd/src/views/demos/access/backend/index.vue +++ b/apps/web-antd/src/views/demos/access/backend/index.vue @@ -1,9 +1,101 @@ diff --git a/apps/web-antd/src/views/demos/access/frontend/access-test-1.vue b/apps/web-antd/src/views/demos/access/frontend/access-test-1.vue index 1309fa57..edcfe5e3 100644 --- a/apps/web-antd/src/views/demos/access/frontend/access-test-1.vue +++ b/apps/web-antd/src/views/demos/access/frontend/access-test-1.vue @@ -6,7 +6,7 @@ defineOptions({ name: 'AccessFrontendAccessTest1' });