From 406c362f84200e2d11d30a8ac27ede84efc045a5 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Fri, 1 Dec 2023 16:20:30 +0800 Subject: [PATCH] Add permission control to element --- src/components/common/Permission.tsx | 16 ++++++ src/pages/Login.tsx | 12 +++-- src/pages/UserFramework.tsx | 2 +- src/pages/system/Group.tsx | 78 ++++++++++++++++----------- src/pages/system/Role.tsx | 79 ++++++++++++++++------------ src/pages/system/User.tsx | 75 +++++++++++++++----------- src/services/index.tsx | 5 +- src/util/auth.tsx | 44 ++++++++++++++++ src/util/route.tsx | 23 +------- 9 files changed, 211 insertions(+), 123 deletions(-) create mode 100644 src/components/common/Permission.tsx diff --git a/src/components/common/Permission.tsx b/src/components/common/Permission.tsx new file mode 100644 index 0000000..811051d --- /dev/null +++ b/src/components/common/Permission.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import { hasPermission } from '@/util/auth.tsx' + +interface PermissionProps extends React.PropsWithChildren { + operationCode?: string +} + +const Permission: React.FC = (props) => { + if (!props.operationCode || hasPermission(props.operationCode)) { + return props.children + } + + return <> +} + +export default Permission diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 197eea6..a1362cb 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -28,13 +28,15 @@ const Login: React.FC = () => { setToken(data?.token ?? '') void messageApi.success('登录成功') setTimeout(() => { - if (searchParams.has('redirect')) { - navigate(searchParams.get('redirect') ?? '/') - } else { - navigate('/') - } void getUserInfo().then((user) => { refreshRouter() + + if (searchParams.has('redirect')) { + navigate(searchParams.get('redirect') ?? '/') + } else { + navigate('/') + } + notification.success({ message: '欢迎回来', description: ( diff --git a/src/pages/UserFramework.tsx b/src/pages/UserFramework.tsx index d4ffec5..830c463 100644 --- a/src/pages/UserFramework.tsx +++ b/src/pages/UserFramework.tsx @@ -1,7 +1,7 @@ import React from 'react' import '@/assets/css/pages/tools-framework.scss' import user from '@/router/user' -import { hasPathPermission } from '@/util/route' +import { hasPathPermission } from '@/util/auth' import FitFullScreen from '@/components/common/FitFullScreen' import Sidebar from '@/components/common/sidebar' import SidebarItemList from '@/components/common/sidebar/SidebarItemList' diff --git a/src/pages/system/Group.tsx b/src/pages/system/Group.tsx index 5658fc4..2ee08ba 100644 --- a/src/pages/system/Group.tsx +++ b/src/pages/system/Group.tsx @@ -11,6 +11,7 @@ import { DATABASE_UPDATE_SUCCESS } from '@/constants/common.constants' import { useUpdatedEffect } from '@/util/hooks' +import { hasPermission } from '@/util/auth' import { utcToLocalTime } from '@/util/datetime' import { r_sys_group_add, @@ -21,6 +22,7 @@ import { r_sys_group_update, r_sys_role_get_list } from '@/services/system' +import Permission from '@/components/common/Permission' import FitFullScreen from '@/components/common/FitFullScreen' import HideScrollbar from '@/components/common/HideScrollbar' import FlexBox from '@/components/common/FlexBox' @@ -105,33 +107,39 @@ const Group: React.FC = () => { render: (value, record) => ( <> - {value ? ( + + {value ? ( + + 禁用 + + ) : ( + + 启用 + + )} + + - 禁用 + 编辑 - ) : ( + + - 启用 + 删除 - )} - - 编辑 - - - 删除 - + ) @@ -488,15 +496,17 @@ const Group: React.FC = () => { const toolbar = ( - - - - - + + + + + + + ) diff --git a/src/pages/system/Role.tsx b/src/pages/system/Role.tsx index 6c24f2f..e276fd8 100644 --- a/src/pages/system/Role.tsx +++ b/src/pages/system/Role.tsx @@ -12,7 +12,7 @@ import { } from '@/constants/common.constants' import { useUpdatedEffect } from '@/util/hooks' import { utcToLocalTime } from '@/util/datetime' -import { powerListToPowerTree } from '@/util/auth.tsx' +import { hasPermission, powerListToPowerTree } from '@/util/auth' import { r_sys_role_add, r_sys_role_change_status, @@ -22,6 +22,7 @@ import { r_sys_role_delete, r_sys_role_delete_list } from '@/services/system' +import Permission from '@/components/common/Permission' import FitFullScreen from '@/components/common/FitFullScreen' import HideScrollbar from '@/components/common/HideScrollbar' import FlexBox from '@/components/common/FlexBox' @@ -98,33 +99,39 @@ const Role: React.FC = () => { render: (value, record) => ( <> - {value ? ( + + {value ? ( + + 禁用 + + ) : ( + + 启用 + + )} + + - 禁用 + 编辑 - ) : ( + + - 启用 + 删除 - )} - - 编辑 - - - 删除 - + ) @@ -498,15 +505,17 @@ const Role: React.FC = () => { const toolbar = ( - - - - - + + + + + + + ) diff --git a/src/pages/system/User.tsx b/src/pages/system/User.tsx index 42afc11..b027382 100644 --- a/src/pages/system/User.tsx +++ b/src/pages/system/User.tsx @@ -12,6 +12,7 @@ import { DATABASE_UPDATE_SUCCESS } from '@/constants/common.constants' import { useUpdatedEffect } from '@/util/hooks' +import { hasPermission } from '@/util/auth' import { utcToLocalTime, isPastTime, localTimeToUtc, dayjsToUtc, getNowUtc } from '@/util/datetime' import { r_sys_group_get_list, @@ -23,6 +24,7 @@ import { r_sys_user_get, r_sys_user_update } from '@/services/system' +import Permission from '@/components/common/Permission' import { r_api_avatar_random_base64 } from '@/services/api/avatar' import FitFullScreen from '@/components/common/FitFullScreen' import HideScrollbar from '@/components/common/HideScrollbar' @@ -188,26 +190,32 @@ const User: React.FC = () => { render: (_, record) => ( <> - - 修改密码 - - - 编辑 - - {record.id !== '0' ? ( + - 删除 + 修改密码 - ) : undefined} + + + + 编辑 + + + + {record.id !== '0' ? ( + + 删除 + + ) : undefined} + ) @@ -393,6 +401,7 @@ const User: React.FC = () => { }).then((res) => { const response = res.data if (response.success) { + void message.success('修改密码成功') resolve(true) } else { reject(response.msg) @@ -884,15 +893,17 @@ const User: React.FC = () => { const toolbar = ( - - - - - + + + + + + + ) diff --git a/src/services/index.tsx b/src/services/index.tsx index 1b890c9..7a1b612 100644 --- a/src/services/index.tsx +++ b/src/services/index.tsx @@ -7,6 +7,7 @@ import { PERMISSION_TOKEN_RENEW_SUCCESS, PERMISSION_UNAUTHORIZED } from '@/constants/common.constants' +import { getRedirectUrl } from '@/util/route' import { getToken, setToken, removeToken } from '@/util/auth' const service: AxiosInstance = axios.create({ @@ -84,7 +85,9 @@ service.interceptors.response.use( ) setTimeout(() => { - location.reload() + location.replace( + getRedirectUrl('/login', `${location.pathname}${location.search}`) + ) }, 1500) throw response?.data case PERMISSION_ACCESS_DENIED: diff --git a/src/util/auth.tsx b/src/util/auth.tsx index a9e80db..9b1f958 100644 --- a/src/util/auth.tsx +++ b/src/util/auth.tsx @@ -121,6 +121,12 @@ export const getUsername = async () => { return user.username } +export const getUserId = async () => { + const user = await getUserInfo() + + return user.id +} + export const getCaptchaSrc = () => { captcha = getCaptcha(300, 150, 4) return captcha.base64Src @@ -227,3 +233,41 @@ const parentToTree = (data: _DataNode[]): _DataNode[] => { return parents } + +export const getPermissionPath = (): string[] => { + const s = getLocalStorage(STORAGE_USER_INFO_KEY) + if (s === null) { + return [] + } + + const user = JSON.parse(s) as UserWithPowerInfoVo + const paths: string[] = [] + user.menus.forEach((menu) => { + paths.push(menu.url) + }) + + return paths +} + +export const hasPathPermission = (path: string) => { + return getPermissionPath().indexOf(path) !== -1 +} + +export const getPermission = (): string[] => { + const s = getLocalStorage(STORAGE_USER_INFO_KEY) + if (s === null) { + return [] + } + + const user = JSON.parse(s) as UserWithPowerInfoVo + const operationCodes: string[] = [] + user.operations.forEach((operation) => { + operationCodes.push(operation.code) + }) + + return operationCodes +} + +export const hasPermission = (operationCode: string) => { + return getPermission().indexOf(operationCode) !== -1 +} diff --git a/src/util/route.tsx b/src/util/route.tsx index 3065c09..688b0e7 100644 --- a/src/util/route.tsx +++ b/src/util/route.tsx @@ -1,5 +1,5 @@ -import { getLocalStorage } from '@/util/browser.tsx' -import { STORAGE_USER_INFO_KEY } from '@/constants/common.constants.ts' +import { RouteObject } from 'react-router' +import { hasPathPermission } from '@/util/auth' export const getRedirectUrl = (path: string, redirectUrl: string): string => { return `${path}?redirect=${encodeURIComponent(redirectUrl)}` @@ -15,25 +15,6 @@ export const getFullTitle = (data: _DataNode, preTitle?: string) => { return data } -export const getPermissionPath = (): string[] => { - const s = getLocalStorage(STORAGE_USER_INFO_KEY) - if (s === null) { - return [] - } - - const user = JSON.parse(s) as UserWithPowerInfoVo - const paths: string[] = [] - user.menus.forEach((menu) => { - paths.push(menu.url) - }) - - return paths -} - -export const hasPathPermission = (path: string) => { - return getPermissionPath().indexOf(path) !== -1 -} - export const getAuthRoute = ( route: RouteJsonObject[], parentPermission: boolean = false