Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ui/src/layout/sidebar/SystemSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const getSystemMenuIcon = (systemMenuItem: LayoutMenuItem) => (isSystemMenuActiv
router
:persistent="false"
>
<template v-for="item in systemMenuItems" :key="item.name">
<template v-for="item in systemMenuItems" :key="item.name" >
<template v-if="item.permission? item.permission():true">
<!-- 有子菜单 -->
<el-sub-menu v-if="item.children?.length && item.route" :index="router.resolve(item.route).path" popper-class="mk-system-sidebar-menu-popper">
<template #title>
Expand All @@ -48,6 +49,9 @@ const getSystemMenuIcon = (systemMenuItem: LayoutMenuItem) => (isSystemMenuActiv
<MkIcon v-if="item.icon" :name="getSystemMenuIcon(item)" :size="18" />
<template #title>{{ item.label }}</template>
</el-menu-item>

</template>

</template>
</el-menu>
</el-scrollbar>
Expand Down
5 changes: 3 additions & 2 deletions ui/src/layout/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/** 应用布局和菜单使用的类型。 */

import type { RouteLocationRaw } from 'vue-router'

import type { RouteLocationRaw ,RouteLocationNormalizedLoaded,RouteLocationNormalized} from 'vue-router'
export interface LayoutMenuItem {
name: string
label: string
activeIcon?: string
icon?: string
route?: RouteLocationRaw
permission?:(route?:RouteLocationNormalized | RouteLocationNormalizedLoaded)=>boolean
children?: LayoutMenuItem[]
}

Expand Down
6 changes: 6 additions & 0 deletions ui/src/permission/core/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ export const RoleConstants = {
EXTENDS_USER: new Role('EXTENDS_USER'),
} as const

export enum Edition{
CE="CE",
EE="EE",
PE="PE"
}

/** 单条权限,对应后端 `common/auth/struct/permission.py` 的 Permission。 */
export class Permission {
constructor(
Expand Down
15 changes: 13 additions & 2 deletions ui/src/permission/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Role, RoleConstants, Compare, Permission, AggregatePermission, type PermissionContext, type PermissionFactory, type RoleFactory } from './common'
import { Role, RoleConstants, Compare, Permission,Edition, AggregatePermission, type PermissionContext, type PermissionFactory, type RoleFactory } from './common'
import { useStore } from '@/stores'
import { getWorkspaceId } from '@/utils/resource-context'

Expand Down Expand Up @@ -78,6 +78,17 @@ export const buildBaseResourcePermission = (permission: Permission, resourceId:
.addRole(new Role(RoleConstants.WORKSPACE_MANAGE.name, workspaceId))
.compare(Compare.OR)
.build()

/**
* 判断当前系统环境
* @param edition
* @returns
*/
export const hasEdition=(edition:Edition)=>{
const { auth } = useStore()
if(edition==Edition.PE||edition==Edition.EE){
return auth.baseProfile?.license_is_valid
}
return true
}
export { Role, RoleConstants, Compare } from './common'
export { PermissionConstants } from './data'
2 changes: 1 addition & 1 deletion ui/src/permission/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ import model from './model'
import system from './system'
import trigger from './trigger'

export default { application, knowledge, tool, model, trigger, ...system }
export default { application, knowledge, tool, model, trigger, system }
4 changes: 2 additions & 2 deletions ui/src/permission/modules/system/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ import loginAuth from './loginAuth'
import appearance from './appearance'
import email from './email'
import operationLog from './operationLog'

export default { user, workspace, role, userGroup, authorization, chatUser, chatUserGroup, chatAuth, portal, loginAuth, appearance, email, operationLog }
import homepage from './homepage'
export default { user, workspace,homepage, role, userGroup, authorization, chatUser, chatUserGroup, chatAuth, portal, loginAuth, appearance, email, operationLog }
1 change: 1 addition & 0 deletions ui/src/permission/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import { hasPermission, buildBasePermission, buildBaseResourcePermission, RoleConstants, Compare } from './core'
import type { Permission } from './core/common'


/** 工作空间级:命中权限位 / 系统管理员 / 该空间管理员 即可。workspaceId 内部取当前路由。 */
export const can = (p: Permission): boolean => hasPermission(buildBasePermission(p))

Expand Down
37 changes: 35 additions & 2 deletions ui/src/router/admin/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import NProgress from 'nprogress'
import { createRouter, createWebHistory } from 'vue-router'
import { createRouter, createWebHistory , type RouteLocationNormalizedLoaded,type RouteLocationNormalized,type RouteLocationResolvedGeneric} from 'vue-router'
import { useStore } from '@/stores'
import { loginRoutes } from './login'
import { systemRoutes } from './system'
import { workspaceRoutes } from './workspace'
import { workflowRoutes } from './workflow'

const ADMIN_BASE_PATH = window.MaxKB?.prefix || import.meta.env.VITE_BASE_PATH || '/admin/'

NProgress.configure({ minimum: 0.3, showSpinner: false, speed: 500, trickleSpeed: 200 })
Expand Down Expand Up @@ -41,6 +40,40 @@ router.beforeEach(async (to, from) => {
await auth.loadAuthBaseProfile()
}
}

// 当前路由有权限,放行
if (!to.meta?.permission || (to.meta.permission as (route:RouteLocationNormalizedLoaded)=>boolean)(to)) {
return true
}

// 当前没权限,沿 next 找
const visited = new Set()
let currentName = to.name ? to.name.toString() : ''

while (currentName) {
if (visited.has(currentName)) {
return { name: 'no-permission', replace: true }
}
visited.add(currentName)

const currentRoute = router.resolve({ name: currentName })
const nextName = currentRoute?.meta?.next as string

if (!nextName) {
return { name: 'no-permission', replace: true }
}

const nextRoute = router.resolve({ name: nextName })
if (nextRoute?.name) {
const nextPermission = nextRoute.meta?.permission as ((route?:RouteLocationNormalized |RouteLocationResolvedGeneric| RouteLocationNormalizedLoaded)=>boolean)
if (!nextPermission || nextPermission(nextRoute)) {
return { name: nextName, replace: true }
}
}

currentName = nextName
}
return { name: 'no-permission', replace: true }
})

router.afterEach((to) => {
Expand Down
7 changes: 5 additions & 2 deletions ui/src/router/admin/system/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router'
import { RESOURCE_TYPE } from '@/api/enums'
import { systemApplicationRoutes } from './modules/application'
import { systemKnowledgeRoutes } from './modules/knowledge'

import perm from "@/permission/index"
export const systemRoutes: RouteRecordRaw = {
path: '/system',
component: () => import('@/layout/AppLayout.vue'),
Expand All @@ -13,7 +13,10 @@ export const systemRoutes: RouteRecordRaw = {
path: 'home',
name: 'system-home',
component: () => import('@/views/system/SystemView.vue'),
meta: { title: '首页', activeIcon: 'icon_screen_filled', icon: 'icon_screen_outlined', order: 0 },
meta: { title: '首页', activeIcon: 'icon_screen_filled', icon: 'icon_screen_outlined', order: 0,
permission: perm.system.homepage.read,
next:'system-identity'
},
},
{
path: 'identity',
Expand Down
1 change: 1 addition & 0 deletions ui/src/router/admin/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function createMenuItems(routes: readonly MenuRouteRecord[]): LayoutMenuItem[] {
activeIcon: route.meta?.activeIcon,
icon: route.meta?.icon,
route: { name: route.name! },
permission:route.meta?.permission as LayoutMenuItem['permission'],
children: children.length ? children : undefined,
}
})
Expand Down
Loading