diff --git a/src/router/applications.js b/src/router/applications.js index 191270b80..0468f6759 100644 --- a/src/router/applications.js +++ b/src/router/applications.js @@ -5,27 +5,27 @@ export default [ path: 'remote-apps', name: 'RemoteAppList', component: () => import('@/views/applications/RemoteApp/RemoteAppList'), - meta: { title: i18n.t('route.RemoteApp') } + meta: { title: i18n.t('route.RemoteApp'), licenseRequired: true } }, { path: 'remote-apps/create', name: 'RemoteAppCreate', component: () => import('@/views/applications/RemoteApp/RemoteAppCreateUpdate'), - meta: { title: i18n.t('route.RemoteApp'), activeMenu: '/applications/remote-apps', action: 'create' }, + meta: { title: i18n.t('route.RemoteApp'), activeMenu: '/applications/remote-apps', action: 'create', licenseRequired: true }, hidden: true }, { path: 'remote-apps/:id/update', name: 'RemoteAppUpdate', component: () => import('@/views/applications/RemoteApp/RemoteAppCreateUpdate'), - meta: { title: i18n.t('route.RemoteAppUpdate'), activeMenu: '/applications/remote-apps', action: 'update' }, + meta: { title: i18n.t('route.RemoteAppUpdate'), activeMenu: '/applications/remote-apps', action: 'update', licenseRequired: true }, hidden: true }, { path: 'remote-apps/:id', name: 'RemoteAppDetail', component: () => import('@/views/applications/RemoteApp/RemoteAppDetail/index'), - meta: { title: i18n.t('route.RemoteAppDetail'), activeMenu: '/applications/remote-apps' }, + meta: { title: i18n.t('route.RemoteAppDetail'), activeMenu: '/applications/remote-apps', licenseRequired: true }, hidden: true }, { diff --git a/src/router/index.js b/src/router/index.js index 440c9e5c9..c540eb69f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -7,7 +7,7 @@ Vue.use(Router) /* Layout */ import Layout from '@/layout' -const requireContext = require.context('@/views/', true, /router\.js$/) +const requireContext = require.context('@/views/xpack/', true, /router\.js$/) /** * Note: sub-menu only appear when route children.length >= 1 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html @@ -47,17 +47,11 @@ export const constantRoutes = [ name: '404', component: () => import('@/views/404'), hidden: true - } -] - -/** - * admin and user routes - * the routes that need to be dynamically loaded based on admin or user roles - */ -export const commonRoutes = { - userProfile: { - path: '/users/profile', + }, + { + path: '/profile', component: Layout, + hidden: true, children: [ { path: '', @@ -67,14 +61,20 @@ export const commonRoutes = { } ] } -} +] + +/** + * user routes + * the routes that need to be dynamically loaded based on user roles + */ +// 权限路由 +import userPageRoutes from './userPage' /** * admin * the routes that need to be dynamically loaded based on admin roles */ -export const adminRoutes = [ - Object.assign({}, commonRoutes.userProfile, { hidden: true }), +export const allRoleRoutes = [ { path: '/', component: Layout, @@ -144,7 +144,10 @@ export const adminRoutes = [ path: '/tickets/', component: Layout, redirect: '/tickets/tickets/', - children: TicketsRoutes + children: TicketsRoutes, + meta: { + licenseRequired: true + } }, { path: '/audits/', @@ -164,17 +167,12 @@ export const adminRoutes = [ path: 'settings', name: 'Settings', component: () => import('@/views/settings/index'), - meta: { title: i18n.t('route.Settings'), icon: 'gears' } + meta: { title: i18n.t('route.Settings'), icon: 'gears', roles: ['SuperAdmin'] } }] }, - { path: '*', redirect: '/404', hidden: true } + ...userPageRoutes, + { path: '*', redirect: '/404', hidden: true, meta: { roles: ['SuperAdmin', 'Admin', 'Auditor', 'User'] }} ] -/** - * user routes - * the routes that need to be dynamically loaded based on user roles - */ -// 权限路由 -export { default as userRoutes } from './userPage' const createRouter = () => new Router({ // mode: 'history', // require service support diff --git a/src/router/userPage.js b/src/router/userPage.js index 6922f0065..09d1bd24a 100644 --- a/src/router/userPage.js +++ b/src/router/userPage.js @@ -10,13 +10,21 @@ export default [ { path: '/', component: Layout, - redirect: '/assets', + meta: { + roles: ['User'], + title: i18n.t('route.MyAssets'), + icon: 'files-o' + }, children: [ { - path: 'assets', + path: '', name: 'assets', component: () => import('@/userviews/assets/index'), - meta: { title: i18n.t('route.MyAssets'), icon: 'files-o' } + meta: { + title: i18n.t('route.MyAssets'), + icon: 'files-o', + roles: ['User'] + } } ] }, @@ -25,53 +33,61 @@ export default [ name: 'Apps', component: Layout, redirect: '/apps/remoteapp', - meta: { title: i18n.t('route.MyApps'), icon: 'th' }, + meta: { title: i18n.t('route.MyApps'), icon: 'th', roles: ['User'] }, children: [ { path: '/apps/remoteapp', name: 'remoteapp', component: () => import('@/userviews/apps/RemoteApp'), - meta: { title: i18n.t('route.RemoteApp') } + meta: { title: i18n.t('route.RemoteApp'), roles: ['User'] } }, { path: '/apps/database', name: 'assets', component: () => import('@/userviews/apps/DatabaseApp'), - meta: { title: i18n.t('route.DatabaseApp') } + meta: { title: i18n.t('route.DatabaseApp'), roles: ['User'] } } ] }, { path: '/command-executions', component: Layout, + meta: { + roles: ['User'] + }, children: [ { path: '', name: 'CommandExecutions', component: () => import('@/views/ops/CommandExecution'), - meta: { title: i18n.t('route.CommandExecutions'), icon: 'terminal' } + meta: { title: i18n.t('route.CommandExecutions'), icon: 'terminal', roles: ['User'] } } ] }, { path: `external-luna`, component: Layout, + meta: { + roles: ['User'] + }, children: [ { path: `${URL}/luna/`, - meta: { title: i18n.t('route.WebTerminal'), icon: 'window-maximize', activeMenu: '/assets' } + meta: { title: i18n.t('route.WebTerminal'), icon: 'window-maximize', activeMenu: '/assets', roles: ['User'] } } ] }, { path: 'external-elfinder', component: Layout, + meta: { + roles: ['User'] + }, children: [ { path: `${URL}/koko/elfinder/sftp/`, - meta: { title: i18n.t('route.WebFTP'), icon: 'file', activeMenu: '/assets' } + meta: { title: i18n.t('route.WebFTP'), icon: 'file', activeMenu: '/assets', roles: ['User'] } } ] - }, - { path: '*', redirect: '/404', hidden: true } + } ] diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 178f0440b..3ec6e1aed 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -1,20 +1,19 @@ import { - adminRoutes, - userRoutes, + allRoleRoutes, constantRoutes } from '@/router' -import _ from 'lodash' /** * Use meta.role to determine if the current user has permission * @param roles * @param route */ function hasPermission(roles, route) { - if (route.meta && route.meta.roles) { - return roles.some(role => route.meta.roles.includes(role)) - } else { - return true + let requireRoles = route.meta ? route.meta.roles : null + if (!requireRoles) { + requireRoles = ['Admin'] } + const has = roles.some(role => requireRoles.includes(role)) + return has } /** @@ -40,41 +39,6 @@ export function filterAsyncRoutes(routes, roles) { return res } -export function filterNoneXpackRoutes(routes) { - const accessedRoutes = [] - routes.forEach(route => { - const tmp = { - ...route - } - if (tmp.name !== 'Xpack' && tmp.name !== 'Tickets') { - if (tmp.name === 'applications' || tmp.name === 'Perms') { - tmp.children = _.remove(tmp.children, (n) => { - return !n.name.includes('RemoteApp') - }) - console.log(tmp.children) - } - accessedRoutes.push(tmp) - } - }) - return accessedRoutes -} - -export function filterUserNoneXpackRoutes(routes) { - const accessedRoutes = [] - routes.forEach(route => { - const tmp = { - ...route - } - if (tmp.name === 'Apps') { - tmp.children = _.remove(tmp.children, (n) => { - return !n.name.includes('remoteapp') - }) - } - accessedRoutes.push(tmp) - }) - return accessedRoutes -} - const state = { routes: [], addRoutes: [] @@ -83,27 +47,15 @@ const state = { const mutations = { SET_ROUTES: (state, routes) => { state.addRoutes = routes - state.routes = constantRoutes.concat(routes) + state.routes = routes.concat(constantRoutes) } } const actions = { - generateRoutes(store, roles) { + generateRoutes({ commit }, roles) { return new Promise(resolve => { - let accessedRoutes - if (roles.includes('Admin')) { - accessedRoutes = adminRoutes || [] - if (!store.rootState.settings.publicSettings.XPACK_LICENSE_IS_VALID) { - accessedRoutes = filterNoneXpackRoutes(adminRoutes) - } - } else if (roles.includes('User')) { - accessedRoutes = userRoutes || [] - // accessedRoutes = filterAsyncRoutes(userRoutes, roles) - if (!store.rootState.settings.publicSettings.XPACK_LICENSE_IS_VALID) { - accessedRoutes = filterUserNoneXpackRoutes(userRoutes) - } - } - store.commit('SET_ROUTES', accessedRoutes) + const accessedRoutes = filterAsyncRoutes(allRoleRoutes, roles) + commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) } diff --git a/src/utils/startup.js b/src/utils/startup.js index c779cfa84..cfb78f0c9 100644 --- a/src/utils/startup.js +++ b/src/utils/startup.js @@ -53,15 +53,15 @@ export async function getUserRoleAndSetRoutes({ to, from, next }) { // try get user profile // note: roles must be a object array! such as: ['admin'] or ,['developer','editor'] // 不能改名 current_org_roles, 里面返回的就是这个 - let { current_org_roles } = await store.dispatch('users/getProfile') + const { current_org_roles } = await store.dispatch('users/getProfile') // console.log('Current org role: ', current_org_roles) - current_org_roles = checkRoles(current_org_roles) - // console.log('Current org role: ', current_org_roles) + const cleanedRoles = cleanCurrentRole(current_org_roles) + console.log('Current org role: ', cleanedRoles) // generate accessible routes map based on roles - const accessRoutes = await store.dispatch('permission/generateRoutes', current_org_roles) - // console.log('Access routes: ', accessRoutes) + const accessRoutes = await store.dispatch('permission/generateRoutes', cleanedRoles) + console.log('Access routes: ', accessRoutes) // dynamically add accessible routes router.addRoutes(accessRoutes) @@ -80,7 +80,6 @@ export async function getUserRoleAndSetRoutes({ to, from, next }) { export async function startup({ to, from, next }) { if (initial) { - console.debug('Has initial') return true } initial = true @@ -93,19 +92,16 @@ export async function startup({ to, from, next }) { return true } -function checkRoles(val) { +function cleanCurrentRole(val) { let currentRole = store.getters.currentRole - if (currentRole) { - if (val && !val.includes(currentRole)) { - // TODO 异常注入处理 - currentRole = val[0] - store.dispatch('users/setCurrentRole', currentRole) - } - } else { - // 设置默认路由 + if (!currentRole) { currentRole = val[0] - store.dispatch('users/setCurrentRole', currentRole) } + if (val && !val.includes(currentRole)) { + // TODO 异常注入处理 + currentRole = val[0] + } + store.dispatch('users/setCurrentRole', currentRole) return [currentRole] } diff --git a/src/views/xpack/router.js b/src/views/xpack/router.js index 609b00151..2c2a5b710 100644 --- a/src/views/xpack/router.js +++ b/src/views/xpack/router.js @@ -7,7 +7,7 @@ export default { component: Layout, redirect: '/applications/remote-apps/', name: 'Xpack', - meta: { title: 'Xpack', icon: 'sitemap' }, + meta: { title: 'Xpack', icon: 'sitemap', licenseRequired: true }, children: [ { path: 'interface-setting', @@ -23,91 +23,115 @@ export default { // }, { path: 'gathered-users', - component: () => import('@/views/xpack/GatheredUser/GatheredUserList'), - name: 'GatherUserList', - meta: { title: i18n.t('xpack.GatherUserList') } - }, - { - path: 'gathered-users/tasks', - component: () => import('@/views/xpack/GatheredUser/TaskList'), - name: 'GatherUserTaskList', - meta: { title: i18n.t('xpack.GatherUserTaskList') }, - hidden: true - }, - { - path: 'gathered-users/tasks/create', - component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'), - name: 'GatherUserTaskCreate', - meta: { title: i18n.t('xpack.GatherUserTaskCreate') }, - hidden: true - }, - { - path: 'gathered-users/tasks/update', - component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'), - name: 'GatherUserTaskUpdate', - meta: { title: i18n.t('xpack.GatherUserTaskUpdate'), action: 'update' }, - hidden: true + component: empty, + redirect: '', + meta: { title: i18n.t('xpack.GatherUserList') }, + children: [ + { + path: '', + component: () => import('@/views/xpack/GatheredUser/GatheredUserList'), + name: 'GatherUserList', + meta: { title: i18n.t('xpack.GatherUserList') } + }, + { + path: 'gathered-users/tasks', + component: () => import('@/views/xpack/GatheredUser/TaskList'), + name: 'GatherUserTaskList', + meta: { title: i18n.t('xpack.GatherUserTaskList') }, + hidden: true + }, + { + path: 'gathered-users/tasks/create', + component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'), + name: 'GatherUserTaskCreate', + meta: { title: i18n.t('xpack.GatherUserTaskCreate') }, + hidden: true + }, + { + path: 'gathered-users/tasks/update', + component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'), + name: 'GatherUserTaskUpdate', + meta: { title: i18n.t('xpack.GatherUserTaskUpdate'), action: 'update' }, + hidden: true + } + ] }, { path: 'orgs', - component: () => import('@/views/xpack/Org/OrganizationList'), + component: empty, name: 'OrganizationList', - meta: { title: i18n.t('xpack.OrganizationList') } + redirect: '', + meta: { title: i18n.t('xpack.OrganizationList'), roles: ['SuperAdmin'] }, + children: [ + { + path: '', + component: () => import('@/views/xpack/Org/OrganizationList'), + name: 'OrganizationList', + meta: { title: i18n.t('xpack.OrganizationList') } + }, + { + path: 'orgs/create', + component: () => import('@/views/xpack/Org/OrganizationCreateUpdate'), + name: 'OrganizationCreate', + hidden: true, + meta: { title: i18n.t('xpack.OrganizationCreate'), activeMenu: '/xpack/orgs', action: 'create' } + }, + { + path: 'orgs/:id/update', + component: () => import('@/views/xpack/Org/OrganizationCreateUpdate'), + name: 'OrganizationUpdate', + hidden: true, + meta: { title: i18n.t('xpack.OrganizationUpdate'), activeMenu: '/xpack/orgs', action: 'update' } + }, + { + path: 'orgs/:id', + component: () => import('@/views/xpack/Org/OrganizationDetail/index'), + name: 'OrganizationDetail', + hidden: true, + meta: { title: i18n.t('xpack.OrganizationDetail'), activeMenu: '/xpack/orgs' } + } + ] }, { - path: 'orgs/create', - component: () => import('@/views/xpack/Org/OrganizationCreateUpdate'), - name: 'OrganizationCreate', - hidden: true, - meta: { title: i18n.t('xpack.OrganizationCreate'), activeMenu: '/xpack/orgs', action: 'create' } - }, - { - path: 'orgs/:id/update', - component: () => import('@/views/xpack/Org/OrganizationCreateUpdate'), - name: 'OrganizationUpdate', - hidden: true, - meta: { title: i18n.t('xpack.OrganizationUpdate'), activeMenu: '/xpack/orgs', action: 'update' } - }, - { - path: 'orgs/:id', - component: () => import('@/views/xpack/Org/OrganizationDetail/index'), - name: 'OrganizationDetail', - hidden: true, - meta: { title: i18n.t('xpack.OrganizationDetail'), activeMenu: '/xpack/orgs' } - }, - { - path: 'change-auth-plan/plan', - component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanList.vue'), - name: 'ChangeAuthPlanList', - meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlan'), activeMenu: '/xpack/change-auth-plan/plan' } - }, - { - path: 'change-auth-plan/plan/create', - component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanCreateUpdate.vue'), - name: 'ChangeAuthPlanCreate', - meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlanCreate'), activeMenu: '/xpack/change-auth-plan/plan', action: 'create' }, - hidden: true - }, - { - path: 'change-auth-plan/plan/:id/update', - component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanCreateUpdate.vue'), - name: 'ChangeAuthPlanUpdate', - meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlanUpdate'), activeMenu: '/xpack/change-auth-plan/plan', action: 'update' }, - hidden: true - }, - { - path: 'change-auth-plan/plan/:id', - component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanDetail/index.vue'), - name: 'ChangeAuthPlanDetail', + path: 'change-auth-plan', + component: empty, meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlan'), activeMenu: '/xpack/change-auth-plan/plan' }, - hidden: true - }, - { - path: 'change-auth-plan/plan-execution/:id', - component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanExecution/ChangeAuthPlanExecutionDetail/index.vue'), - name: 'ChangeAuthPlanExecutionDetail', - meta: { title: i18n.t('xpack.ChangeAuthPlan.ExecutionDetail'), activeMenu: '/xpack/change-auth-plan/plan' }, - hidden: true + children: [ + { + path: 'plan', + component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanList.vue'), + name: 'ChangeAuthPlanList', + meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlan'), activeMenu: '/xpack/change-auth-plan/plan' } + }, + { + path: 'plan/create', + component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanCreateUpdate.vue'), + name: 'ChangeAuthPlanCreate', + meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlanCreate'), activeMenu: '/xpack/change-auth-plan/plan', action: 'create' }, + hidden: true + }, + { + path: 'plan/:id/update', + component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanCreateUpdate.vue'), + name: 'ChangeAuthPlanUpdate', + meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlanUpdate'), activeMenu: '/xpack/change-auth-plan/plan', action: 'update' }, + hidden: true + }, + { + path: 'plan/:id', + component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanDetail/index.vue'), + name: 'ChangeAuthPlanDetail', + meta: { title: i18n.t('xpack.ChangeAuthPlan.ChangeAuthPlan'), activeMenu: '/xpack/change-auth-plan/plan' }, + hidden: true + }, + { + path: 'plan-execution/:id', + component: () => import('@/views/xpack/ChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanExecution/ChangeAuthPlanExecutionDetail/index.vue'), + name: 'ChangeAuthPlanExecutionDetail', + meta: { title: i18n.t('xpack.ChangeAuthPlan.ExecutionDetail'), activeMenu: '/xpack/change-auth-plan/plan' }, + hidden: true + } + ] }, { path: '/cloud',