diff --git a/ui/src/directives/hasPermission.ts b/ui/src/directives/hasPermission.ts index 5a71520e8..1941ecb30 100644 --- a/ui/src/directives/hasPermission.ts +++ b/ui/src/directives/hasPermission.ts @@ -1,6 +1,5 @@ import type { App } from 'vue' import { hasPermission } from '@/utils/permission' - const display = async (el: any, binding: any) => { const has = hasPermission( binding.value?.permission || binding.value, diff --git a/ui/src/router/modules/application-detail.ts b/ui/src/router/modules/application-detail.ts index 20b6d444f..e32411492 100644 --- a/ui/src/router/modules/application-detail.ts +++ b/ui/src/router/modules/application-detail.ts @@ -1,3 +1,6 @@ +import { ComplexPermission } from '@/utils/permission/type' +import { PermissionConst, RoleConst } from '@/utils/permission/data' + const ApplicationDetailRouter = { path: '/application/:id/:type', name: 'ApplicationDetail', @@ -15,6 +18,10 @@ const ApplicationDetailRouter = { active: 'overview', parentPath: '/application/:id/:type', parentName: 'ApplicationDetail', + permission: [ + PermissionConst.APPLICATION_OVERVIEW_READ.getWorkspacePermission, + RoleConst.WORKSPACE_MANAGE.getWorkspaceRole, + ], }, component: () => import('@/views/application-overview/index.vue'), }, @@ -66,10 +73,10 @@ const ApplicationDetailRouter = { title: 'views.chatLog.title', active: 'chat-log', parentPath: '/application/:id/:type', - parentName: 'ApplicationDetail' + parentName: 'ApplicationDetail', }, - component: () => import('@/views/chat-log/index.vue') - } + component: () => import('@/views/chat-log/index.vue'), + }, ], } diff --git a/ui/src/stores/modules-shared-system/theme.ts b/ui/src/stores/modules-shared-system/theme.ts deleted file mode 100644 index 820ceafdd..000000000 --- a/ui/src/stores/modules-shared-system/theme.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { defineStore } from 'pinia' -import { cloneDeep } from 'lodash' -import { useElementPlusTheme } from 'use-element-plus-theme' -import ThemeApi from '@/api/system-settings/theme' -import type {Ref} from "vue"; -export interface themeStateTypes { - themeInfo: any -} -const defalueColor = '#3370FF' - -const useThemeStore = defineStore('them', { - state: (): themeStateTypes => ({ - themeInfo: null, - }), - actions: { - isDefaultTheme() { - return !this.themeInfo?.theme || this.themeInfo?.theme === defalueColor - }, - - setTheme(data?: any) { - const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme || defalueColor) - changeTheme(defalueColor) - changeTheme(data?.['theme']) - this.themeInfo = cloneDeep(data) - }, - - // async theme(loading?: Ref) { - // return await ThemeApi.getThemeInfo(loading).then((ok) => { - // this.setTheme(ok.data) - // // window.document.title = this.themeInfo['title'] || 'MaxKB' - // // const link = document.querySelector('link[rel="icon"]') as any - // // if (link) { - // // link['href'] = this.themeInfo['icon'] || '/favicon.ico' - // // } - // }) - // }, - }, -}) - -export default useThemeStore diff --git a/ui/src/stores/modules-shared-system/user.ts b/ui/src/stores/modules-shared-system/user.ts deleted file mode 100644 index fb8c1e2d4..000000000 --- a/ui/src/stores/modules-shared-system/user.ts +++ /dev/null @@ -1,191 +0,0 @@ -import {defineStore} from 'pinia' -import {type Ref} from 'vue' -import type {User} from '@/api/type/user' -import UserApi from '@/api/user/user' -import LoginApi from '@/api/user/login' -import {cloneDeep} from 'lodash' -import ThemeApi from '@/api/system-settings/theme' -// import { defaultPlatformSetting } from '@/utils/theme' -import {useLocalStorage} from '@vueuse/core' -import {localeConfigKey, getBrowserLang} from '@/locales/index' -import useThemeStore from './theme' -import {useElementPlusTheme} from "use-element-plus-theme"; -import {defaultPlatformSetting} from "@/utils/theme"; - -export interface userStateTypes { - userType: number // 1 系统操作者 2 对话用户 - userInfo: User | null - version?: string - XPACK_LICENSE_IS_VALID: true - isXPack: true - themeInfo: any - token: any -} - -const useLoginStore = defineStore('use', { - state: (): userStateTypes => ({ - userType: 1, // 1 系统操作者 2 对话用户 - userInfo: null, - version: '', - XPACK_LICENSE_IS_VALID: false, - isXPack: false, - themeInfo: null, - token: '' - }), - actions: { - getLanguage() { - return this.userType === 1 - ? localStorage.getItem('MaxKB-locale') || getBrowserLang() - : sessionStorage.getItem('language') || getBrowserLang() - }, - isDefaultTheme() { - return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF' - }, - setTheme(data: any) { - const {changeTheme} = useElementPlusTheme(this.themeInfo?.theme) - changeTheme(data?.['theme']) - this.themeInfo = cloneDeep(data) - }, - async profile(loading?: Ref) { - return UserApi.getUserProfile(loading).then((ok) => { - this.userInfo = ok.data - useLocalStorage(localeConfigKey, 'en-US').value = - ok?.data?.language || this.getLanguage() - const theme = useThemeStore() - theme.setTheme() - return this.asyncGetProfile() - }) - }, - async asyncGetProfile() { - return new Promise((resolve, reject) => { - UserApi.getProfile() - .then(async (ok) => { - // this.version = ok.data?.version || '-' - this.isXPack = true - this.XPACK_LICENSE_IS_VALID = true - - if (this.isEnterprise()) { - // await this.theme() - } else { - this.themeInfo = { - ...defaultPlatformSetting - } - } - resolve(ok) - }) - .catch((error) => { - reject(error) - }) - }) - }, - - getPermissions() { - if (this.userInfo) { - return this.isXPack && this.XPACK_LICENSE_IS_VALID - ? [...this.userInfo?.permissions, 'x-pack'] - : this.userInfo?.permissions - } else { - return this.userInfo?.permissions - } - }, - getRole() { - if (this.userInfo) { - return this.userInfo?.role - } else { - return '' - } - }, - async theme(loading?: Ref) { - return await ThemeApi.getThemeInfo(loading).then((ok) => { - this.setTheme(ok.data) - // window.document.title = this.themeInfo['title'] || 'MaxKB' - // const link = document.querySelector('link[rel="icon"]') as any - // if (link) { - // link['href'] = this.themeInfo['icon'] || '/favicon.ico' - // } - }) - }, - showXpack() { - return this.isXPack - }, - - isExpire() { - return this.isXPack && !this.XPACK_LICENSE_IS_VALID - }, - isEnterprise() { - return this.isXPack && this.XPACK_LICENSE_IS_VALID - }, - - // changeUserType(num: number, token?: string) { - // this.userType = num - // this.userAccessToken = token - // }, - - - async dingCallback(code: string) { - return LoginApi.getDingCallback(code).then((ok) => { - this.token = ok.data - localStorage.setItem('token', ok.data) - return this.profile() - }) - }, - async dingOauth2Callback(code: string) { - return LoginApi.getDingOauth2Callback(code).then((ok) => { - this.token = ok.data - localStorage.setItem('token', ok.data) - return this.profile() - }) - }, - async wecomCallback(code: string) { - return LoginApi.getWecomCallback(code).then((ok) => { - this.token = ok.data - localStorage.setItem('token', ok.data) - return this.profile() - }) - }, - async larkCallback(code: string) { - return LoginApi.getLarkCallback(code).then((ok) => { - this.token = ok.data - localStorage.setItem('token', ok.data) - return this.profile() - }) - }, - - async logout() { - return LoginApi.logout().then(() => { - localStorage.removeItem('token') - return true - }) - }, - async getAuthType() { - return LoginApi.getAuthType().then((ok) => { - return ok.data - }) - }, - async getQrType() { - return LoginApi.getQrType().then((ok) => { - return ok.data - }) - }, - async getQrSource() { - return LoginApi.getQrSource().then((ok) => { - return ok.data - }) - }, - async postUserLanguage(lang: string, loading?: Ref) { - return new Promise((resolve, reject) => { - LoginApi.postLanguage({ language: lang }, loading) - .then(async (ok) => { - useLocalStorage(localeConfigKey, 'en-US').value = lang - window.location.reload() - resolve(ok) - }) - .catch((error) => { - reject(error) - }) - }) - } - }, -}) - -export default useLoginStore diff --git a/ui/src/stores/modules/user.ts b/ui/src/stores/modules/user.ts index 1a16cdf0d..6630cf6a3 100644 --- a/ui/src/stores/modules/user.ts +++ b/ui/src/stores/modules/user.ts @@ -73,7 +73,6 @@ const useUserStore = defineStore('user', { UserApi.getProfile() .then(async (ok) => { // this.version = ok.data?.version || '-' - console.log(ok) this.license_is_valid = ok.data.license_is_valid this.edition = ok.data.edition @@ -91,21 +90,23 @@ const useUserStore = defineStore('user', { }) }) }, - getPermissions() { if (this.userInfo) { - return this.isXPack && this.XPACK_LICENSE_IS_VALID - ? [...this.userInfo?.permissions, 'x-pack'] - : this.userInfo?.permissions - } else { + if (this.isEE()) { + return [...this.userInfo?.permissions, 'x-pack-ee'] + } else if (this.isPE()) { + return [...this.userInfo?.permissions, 'x-pack-pe'] + } return this.userInfo?.permissions + } else { + return [] } }, getRole() { if (this.userInfo) { return this.userInfo?.role } else { - return '' + return [] } }, async theme(loading?: Ref) { diff --git a/ui/src/utils/common.ts b/ui/src/utils/common.ts index f825c3c59..993e0cd2a 100644 --- a/ui/src/utils/common.ts +++ b/ui/src/utils/common.ts @@ -66,3 +66,7 @@ export const defaultIcon = '/ui/favicon.ico' export function isAppIcon(url: string | undefined) { return url === defaultIcon ? '' : url } + +export function isFunction(fn: any) { + return typeof fn === 'function' +} diff --git a/ui/src/utils/permission/data.ts b/ui/src/utils/permission/data.ts index 990e4eec7..6fb5704ff 100644 --- a/ui/src/utils/permission/data.ts +++ b/ui/src/utils/permission/data.ts @@ -1,7 +1,13 @@ -import { Permission } from '@/utils/permission/type' +import { Permission, Role } from '@/utils/permission/type' const PermissionConst = { USER_READ: new Permission('USER:READ'), USER_CREATE: new Permission('USER:CREATE'), KNOWLEDGE_READ: new Permission('KNOWLEDGE:READ'), + APPLICATION_OVERVIEW_READ: new Permission('APPLICATION_OVERVIEW_READ'), } -export default PermissionConst +const RoleConst = { + ADMIN: new Role('ADMIN'), + WORKSPACE_MANAGE: new Role('WORKSPACE_MANAGE'), + USER: new Role('USER'), +} +export { PermissionConst, RoleConst } diff --git a/ui/src/utils/permission/index.ts b/ui/src/utils/permission/index.ts index 7e4c7e2ab..9169e6448 100644 --- a/ui/src/utils/permission/index.ts +++ b/ui/src/utils/permission/index.ts @@ -1,26 +1,33 @@ import useStore from '@/stores' import { Role, Permission, ComplexPermission } from '@/utils/permission/type' +import { isFunction } from '@/utils/common' + +type PF = () => Role | string | Permission | ComplexPermission /** * 是否包含当前权限 * @param permission 当前权限 * @returns True 包含 false 不包含 */ -const hasPermissionChild = (permission: Role | string | Permission | ComplexPermission) => { +const hasPermissionChild = (permission: Role | string | Permission | ComplexPermission | PF) => { const { user } = useStore() const permissions = user.getPermissions() - const role = user.getRole() + const role: Array = user.getRole() if (!permission) { return true } + + if (isFunction(permission)) { + permission = (permission as PF)() + } if (permission instanceof Role) { - return role === permission.role + return role.includes(permission.role) } if (permission instanceof Permission) { return permissions.includes(permission.permission) } if (permission instanceof ComplexPermission) { const permissionOk = permission.permissionList.some((p) => permissions.includes(p)) - const roleOk = permission.roleList.includes(role) + const roleOk = role.some((r) => permission.roleList.includes(r)) return permission.compare === 'AND' ? permissionOk && roleOk : permissionOk || roleOk } if (typeof permission === 'string') { @@ -38,11 +45,12 @@ const hasPermissionChild = (permission: Role | string | Permission | ComplexPerm */ export const hasPermission = ( permission: - | Array + | Array | Role | string | Permission - | ComplexPermission, + | ComplexPermission + | PF, compare: 'OR' | 'AND', ): boolean => { if (permission instanceof Array) { diff --git a/ui/src/utils/permission/type.ts b/ui/src/utils/permission/type.ts index ec91e69aa..e9b6bcadf 100644 --- a/ui/src/utils/permission/type.ts +++ b/ui/src/utils/permission/type.ts @@ -1,3 +1,4 @@ +import useStore from '@/stores' /** * 角色对象 */ @@ -7,6 +8,11 @@ export class Role { constructor(role: string) { this.role = role } + + getWorkspaceRole = () => { + const { user } = useStore() + return new Role(`${this.role}:/WORKSPACE/${user.getWorkspaceId()}`) + } } /** * 权限对象 @@ -22,8 +28,9 @@ export class Permission { * @param workspace_id 工作空间id * @returns 工作空间权限 */ - getWorkspacePermission(workspace_id: string) { - return `${this.permission}:/WORKSPACE/${workspace_id}` + getWorkspacePermission = () => { + const { user } = useStore() + return `${this.permission}:/WORKSPACE/${user.getWorkspaceId()}` } /** * 工作空间资源权限 @@ -32,8 +39,9 @@ export class Permission { * @param resource_id 资源id * @returns 工作空间资源权限 */ - getWorkspaceResourcePermission(workspace_id: string, resource: string, resource_id: string) { - return `${this.permission}:/WORKSPACE/${workspace_id}/${resource}/${resource_id}` + getWorkspaceResourcePermission = (resource: string, resource_id: string) => { + const { user } = useStore() + return `${this.permission}:/WORKSPACE/${user.getWorkspaceId()}/${resource}/${resource_id}` } } /**