提交 a647c66b authored 作者: fit2cloud-chenyw's avatar fit2cloud-chenyw

feat: 增加权限设置

上级 a60a2431
...@@ -12,4 +12,6 @@ import java.util.List; ...@@ -12,4 +12,6 @@ import java.util.List;
public class CurrentUserDto extends SysUserEntity implements Serializable { public class CurrentUserDto extends SysUserEntity implements Serializable {
private List<CurrentRoleDto> roles; private List<CurrentRoleDto> roles;
private List<String> permissions;
} }
...@@ -23,6 +23,8 @@ public class DynamicMenuDto implements Serializable { ...@@ -23,6 +23,8 @@ public class DynamicMenuDto implements Serializable {
private Long id; private Long id;
private String permission;
private List<DynamicMenuDto> children; private List<DynamicMenuDto> children;
} }
...@@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -59,7 +58,9 @@ public class AuthServer implements AuthApi { ...@@ -59,7 +58,9 @@ public class AuthServer implements AuthApi {
SysUserEntity user = authUserService.getUser(username); SysUserEntity user = authUserService.getUser(username);
CurrentUserDto currentUserDto = BeanUtils.copyBean(new CurrentUserDto(), user); CurrentUserDto currentUserDto = BeanUtils.copyBean(new CurrentUserDto(), user);
List<CurrentRoleDto> currentRoleDtos = authUserService.roleInfos(user.getUserId()); List<CurrentRoleDto> currentRoleDtos = authUserService.roleInfos(user.getUserId());
List<String> permissions = authUserService.permissions(user.getUserId());
currentUserDto.setRoles(currentRoleDtos); currentUserDto.setRoles(currentRoleDtos);
currentUserDto.setPermissions(permissions);
return currentUserDto; return currentUserDto;
} }
......
...@@ -4,11 +4,13 @@ import io.dataease.auth.api.dto.CurrentRoleDto; ...@@ -4,11 +4,13 @@ import io.dataease.auth.api.dto.CurrentRoleDto;
import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.SysUserEntity;
import io.dataease.base.mapper.ext.AuthMapper; import io.dataease.base.mapper.ext.AuthMapper;
import io.dataease.auth.service.AuthUserService; import io.dataease.auth.service.AuthUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
public class AuthUserServiceImpl implements AuthUserService { public class AuthUserServiceImpl implements AuthUserService {
...@@ -27,7 +29,8 @@ public class AuthUserServiceImpl implements AuthUserService { ...@@ -27,7 +29,8 @@ public class AuthUserServiceImpl implements AuthUserService {
} }
@Override @Override
public List<String> permissions(Long userId){ public List<String> permissions(Long userId){
return authMapper.permissions(userId); List<String> permissions = authMapper.permissions(userId);
return permissions.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
} }
@Override @Override
......
...@@ -21,6 +21,7 @@ public class DynamicMenuServiceImpl implements DynamicMenuService { ...@@ -21,6 +21,7 @@ public class DynamicMenuServiceImpl implements DynamicMenuService {
@Override @Override
public List<DynamicMenuDto> load(String userId) { public List<DynamicMenuDto> load(String userId) {
SysMenuExample sysMenuExample = new SysMenuExample(); SysMenuExample sysMenuExample = new SysMenuExample();
sysMenuExample.createCriteria().andTypeLessThanOrEqualTo(1);
sysMenuExample.setOrderByClause(" menu_sort "); sysMenuExample.setOrderByClause(" menu_sort ");
List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample); List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample);
List<DynamicMenuDto> dynamicMenuDtos = sysMenus.stream().map(this::convert).collect(Collectors.toList()); List<DynamicMenuDto> dynamicMenuDtos = sysMenus.stream().map(this::convert).collect(Collectors.toList());
...@@ -40,6 +41,7 @@ public class DynamicMenuServiceImpl implements DynamicMenuService { ...@@ -40,6 +41,7 @@ public class DynamicMenuServiceImpl implements DynamicMenuService {
menuMeta.setTitle(sysMenu.getTitle()); menuMeta.setTitle(sysMenu.getTitle());
menuMeta.setIcon(sysMenu.getIcon()); menuMeta.setIcon(sysMenu.getIcon());
dynamicMenuDto.setMeta(menuMeta); dynamicMenuDto.setMeta(menuMeta);
dynamicMenuDto.setPermission(sysMenu.getPermission());
return dynamicMenuDto; return dynamicMenuDto;
} }
......
import store from '@/store'
function checkPermission(el, binding) {
const { value } = binding
// 我们是基于资源授鉴权 不用角色 因为后期可能有对部门授权 对 人员授权
const permissions = store.getters && store.getters.permissions
if (value && value instanceof Array) {
const needPermissions = value
// 满足指令中的每个权限才可放行 而不是 满足任意一个即可
const hasPermission = needPermissions.every(needP => {
const result = permissions.includes(needP)
return result
})
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`使用方式: v-permission="['user:read']"`)
}
}
export default {
inserted(el, binding) {
checkPermission(el, binding)
},
update(el, binding) {
checkPermission(el, binding)
}
}
import permission from '@/directive/Permission'
export default {
install(Vue) {
Vue.directive('permission', permission)
}
}
...@@ -14,11 +14,12 @@ import router from './router' ...@@ -14,11 +14,12 @@ import router from './router'
import '@/icons' // icon import '@/icons' // icon
import '@/permission' // permission control import '@/permission' // permission control
import api from '@/api/index.js' import api from '@/api/index.js'
import filter from '@/filter/filter' import filter from '@/filter/filter'
import message from '@/metersphere/common/js/message' import message from '@/metersphere/common/js/message'
import { left2RightDrag, bottom2TopDrag, right2LeftDrag } from '@/metersphere/common/js/directive' import { left2RightDrag, bottom2TopDrag, right2LeftDrag } from '@/metersphere/common/js/directive'
import directives from './directive'
Vue.prototype.$api = api Vue.prototype.$api = api
import * as echarts from 'echarts' import * as echarts from 'echarts'
...@@ -50,11 +51,13 @@ Vue.use(Fit2CloudUI, { ...@@ -50,11 +51,13 @@ Vue.use(Fit2CloudUI, {
}) })
Vue.use(filter) Vue.use(filter)
Vue.use(message) Vue.use(message)
Vue.use(directives)
Vue.config.productionTip = false Vue.config.productionTip = false
// 支持左右拖拽 // 支持左右拖拽
Vue.directive('left-to-right-drag', left2RightDrag) Vue.directive('left-to-right-drag', left2RightDrag)
Vue.directive('right-to-left-drag', right2LeftDrag) Vue.directive('right-to-left-drag', right2LeftDrag)
Vue.directive('bottom-to-top-drag', bottom2TopDrag) Vue.directive('bottom-to-top-drag', bottom2TopDrag)
new Vue({ new Vue({
el: '#app', el: '#app',
router, router,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<span class="operate-button"> <span class="operate-button">
<ms-table-button <ms-table-button
v-if="showCreate" v-if="showCreate"
v-permission="permission.add"
:is-tester-permission="isTesterPermission" :is-tester-permission="isTesterPermission"
icon="el-icon-circle-plus-outline" icon="el-icon-circle-plus-outline"
:content="createTip" :content="createTip"
...@@ -67,7 +68,8 @@ export default { ...@@ -67,7 +68,8 @@ export default {
default: false default: false
}, },
condition: { condition: {
type: Object type: Object,
default: null
}, },
createTip: { createTip: {
type: String, type: String,
...@@ -76,7 +78,8 @@ export default { ...@@ -76,7 +78,8 @@ export default {
} }
}, },
runTip: { runTip: {
type: String type: String,
default: null
}, },
...@@ -85,10 +88,18 @@ export default { ...@@ -85,10 +88,18 @@ export default {
default: false default: false
}, },
tip: { tip: {
String, type: String,
default() { default() {
return this.$t('commons.search_by_name') return this.$t('commons.search_by_name')
} }
},
permission: {
type: Object,
default() {
return {
add: []
}
}
} }
}, },
computed: { computed: {
......
<template> <template>
<span> <span>
<slot name="front" /> <slot name="front" />
<ms-table-operator-button :is-tester-permission="isTesterPermission" :tip="tip1" icon="el-icon-edit" @exec="editClick" @click.stop="editClickStop" /> <ms-table-operator-button v-permission="permission.edit" :is-tester-permission="isTesterPermission" :tip="tip1" icon="el-icon-edit" @exec="editClick" @click.stop="editClickStop" />
<slot name="middle" /> <slot name="middle" />
<ms-table-operator-button :is-tester-permission="isTesterPermission" :tip="tip2" icon="el-icon-delete" type="danger" @exec="deleteClick" @click.stop="deleteClickStop" /> <ms-table-operator-button v-permission="permission.del" :is-tester-permission="isTesterPermission" :tip="tip2" icon="el-icon-delete" type="danger" @exec="deleteClick" @click.stop="deleteClickStop" />
<slot name="behind" /> <slot name="behind" />
</span> </span>
...@@ -30,6 +30,16 @@ export default { ...@@ -30,6 +30,16 @@ export default {
isTesterPermission: { isTesterPermission: {
type: Boolean, type: Boolean,
default: false default: false
},
permission: {
type: Object,
default() {
return {
edit: [],
del: []
}
}
} }
}, },
methods: { methods: {
......
...@@ -66,7 +66,8 @@ router.beforeEach(async(to, from, next) => { ...@@ -66,7 +66,8 @@ router.beforeEach(async(to, from, next) => {
}) })
export const loadMenus = (next, to) => { export const loadMenus = (next, to) => {
buildMenus().then(res => { buildMenus().then(res => {
const asyncRouter = filterAsyncRouter(res.data) const filterDatas = filterRouter(res.data)
const asyncRouter = filterAsyncRouter(filterDatas)
asyncRouter.push({ path: '*', redirect: '/404', hidden: true }) asyncRouter.push({ path: '*', redirect: '/404', hidden: true })
store.dispatch('permission/GenerateRoutes', asyncRouter).then(() => { // 存储路由 store.dispatch('permission/GenerateRoutes', asyncRouter).then(() => { // 存储路由
router.addRoutes(asyncRouter) router.addRoutes(asyncRouter)
...@@ -74,6 +75,30 @@ export const loadMenus = (next, to) => { ...@@ -74,6 +75,30 @@ export const loadMenus = (next, to) => {
}) })
}) })
} }
// 根据权限过滤菜单
const filterRouter = routers => {
const user_permissions = store.getters.permissions
if (!user_permissions || user_permissions.length === 0) {
return routers
}
const tempResults = routers.filter(router => hasPermission(router, user_permissions))
// 如果是一级菜单(目录) 没有字菜单 那就移除
return tempResults.filter(item => item.children && item.children.length)
}
const hasPermission = (router, user_permissions) => {
// 菜单要求权限 但是当前用户权限没有包含菜单权限
if (router.permission && !user_permissions.includes(router.permission)) {
return false
}
// 如果有字菜单 则 判断是否满足 ‘任意一个子菜单有权限’
if (router.children && router.children.length) {
const permissionChilds = router.children.filter(item => hasPermission(item, user_permissions))
router.children = permissionChilds
return router.children.length > 0
}
return true
}
router.afterEach(() => { router.afterEach(() => {
// finish progress bar // finish progress bar
NProgress.done() NProgress.done()
......
...@@ -16,6 +16,7 @@ const getters = { ...@@ -16,6 +16,7 @@ const getters = {
sceneData: state => state.dataset.sceneData, sceneData: state => state.dataset.sceneData,
table: state => state.dataset.table, table: state => state.dataset.table,
loadingMap: state => state.request.loadingMap, loadingMap: state => state.request.loadingMap,
currentPath: state => state.permission.currentPath currentPath: state => state.permission.currentPath,
permissions: state => state.user.permissions
} }
export default getters export default getters
...@@ -47,7 +47,7 @@ export const filterAsyncRouter = (routers) => { // 遍历后台传来的路由 ...@@ -47,7 +47,7 @@ export const filterAsyncRouter = (routers) => { // 遍历后台传来的路由
}).map(router => { }).map(router => {
router.hasOwnProperty('id') && delete router.id router.hasOwnProperty('id') && delete router.id
router.hasOwnProperty('pid') && delete router.pid router.hasOwnProperty('pid') && delete router.pid
router.hasOwnProperty('children') && !router['children'] && delete router.children router.hasOwnProperty('children') && (!router['children'] || !router['children'].length) && delete router.children
router.hasOwnProperty('redirect') && !router['redirect'] && delete router.redirect router.hasOwnProperty('redirect') && !router['redirect'] && delete router.redirect
return router return router
}) })
......
...@@ -10,7 +10,9 @@ const getDefaultState = () => { ...@@ -10,7 +10,9 @@ const getDefaultState = () => {
roles: [], roles: [],
avatar: '', avatar: '',
// 第一次加载菜单时用到 // 第一次加载菜单时用到
loadMenus: false loadMenus: false,
// 当前用户拥有哪些资源权限
permissions: []
} }
} }
...@@ -37,6 +39,9 @@ const mutations = { ...@@ -37,6 +39,9 @@ const mutations = {
}, },
SET_LOAD_MENUS: (state, loadMenus) => { SET_LOAD_MENUS: (state, loadMenus) => {
state.loadMenus = loadMenus state.loadMenus = loadMenus
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
} }
} }
...@@ -68,12 +73,13 @@ const actions = { ...@@ -68,12 +73,13 @@ const actions = {
const currentUser = data const currentUser = data
commit('SET_USER', currentUser) commit('SET_USER', currentUser)
const roles = data.roles const { roles, nickName, permissions } = data
commit('SET_ROLES', roles) commit('SET_ROLES', roles)
const { nickName } = data
commit('SET_NAME', nickName) commit('SET_NAME', nickName)
// commit('SET_AVATAR', avatar) // commit('SET_AVATAR', avatar)
commit('SET_PERMISSIONS', permissions)
resolve(data) resolve(data)
}).catch(error => { }).catch(error => {
reject(error) reject(error)
......
...@@ -15,6 +15,6 @@ export function isExternal(path) { ...@@ -15,6 +15,6 @@ export function isExternal(path) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validUsername(str) { export function validUsername(str) {
const valid_map = ['admin', 'editor'] const valid_map = ['admin', 'cyw']
return valid_map.indexOf(str.trim()) >= 0 return valid_map.indexOf(str.trim()) >= 0
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<el-card class="table-card"> <el-card class="table-card">
<template v-slot:header> <template v-slot:header>
<ms-table-header <ms-table-header
:permission="permission"
:condition.sync="condition" :condition.sync="condition"
:create-tip="$t('organization.create')" :create-tip="$t('organization.create')"
:title="$t('commons.organization')" :title="$t('commons.organization')"
...@@ -45,7 +46,7 @@ ...@@ -45,7 +46,7 @@
<el-table-column :label="$t('commons.operating')"> <el-table-column :label="$t('commons.operating')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" /> <ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
</template> </template>
</el-table-column> --> </el-table-column> -->
</el-table> </el-table>
...@@ -167,6 +168,11 @@ export default { ...@@ -167,6 +168,11 @@ export default {
description: [ description: [
{ max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' } { max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' }
] ]
},
permission: {
add: ['dept:add'],
edit: ['dept:edit'],
del: ['dept:del']
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<el-card class="table-card"> <el-card class="table-card">
<template v-slot:header> <template v-slot:header>
<ms-table-header <ms-table-header
:permission="permission"
:condition.sync="condition" :condition.sync="condition"
:create-tip="$t('menu.create')" :create-tip="$t('menu.create')"
:title="$t('commons.menu')" :title="$t('commons.menu')"
...@@ -58,9 +59,9 @@ ...@@ -58,9 +59,9 @@
<el-table-column :label="$t('commons.operating')"> <el-table-column :label="$t('commons.operating')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" /> <ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
</template> </template>
</el-table-column> --> </el-table-column>
</el-table> </el-table>
</el-card> </el-card>
...@@ -210,6 +211,11 @@ export default { ...@@ -210,6 +211,11 @@ export default {
description: [ description: [
{ max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' } { max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' }
] ]
},
permission: {
add: ['menu:add'],
edit: ['menu:edit'],
del: ['menu:del']
} }
} }
...@@ -220,6 +226,7 @@ export default { ...@@ -220,6 +226,7 @@ export default {
}, },
methods: { methods: {
create() { create() {
this.form = Object.assign({}, this.defaultForm)
this.dialogVisible = true this.dialogVisible = true
this.formType = 'add' this.formType = 'add'
listenGoBack(this.closeFunc) listenGoBack(this.closeFunc)
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<el-aside width="70%" style="border: 1px solid #eee"> <el-aside width="70%" style="border: 1px solid #eee">
<el-card class="table-card"> <el-card class="table-card">
<template v-slot:header> <template v-slot:header>
<ms-table-header :condition.sync="condition" :create-tip="$t('role.add')" :title="$t('commons.role')" @search="search" @create="create" /> <ms-table-header :permission="permission" :condition.sync="condition" :create-tip="$t('role.add')" :title="$t('commons.role')" @search="search" @create="create" />
</template> </template>
<el-table border highlight-current-row class="adjust-table" :data="tableData" style="width: 100%;" @row-click="rowClick"> <el-table border highlight-current-row class="adjust-table" :data="tableData" style="width: 100%;" @row-click="rowClick">
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.operating')"> <el-table-column :label="$t('commons.operating')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" /> <ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -121,7 +121,12 @@ export default { ...@@ -121,7 +121,12 @@ export default {
{ required: true, message: '请输入名称', trigger: 'blur' } { required: true, message: '请输入名称', trigger: 'blur' }
] ]
}, },
currentRow: null currentRow: null,
permission: {
add: ['role:add'],
edit: ['role:edit'],
del: ['role:del']
}
} }
}, },
watch: { watch: {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<el-card class="table-card"> <el-card class="table-card">
<template v-slot:header> <template v-slot:header>
<ms-table-header <ms-table-header
:permission="permission"
:condition.sync="condition" :condition.sync="condition"
:create-tip="$t('user.create')" :create-tip="$t('user.create')"
:title="$t('commons.user')" :title="$t('commons.user')"
...@@ -38,7 +39,7 @@ ...@@ -38,7 +39,7 @@
<!-- <el-table-column prop="source" :label="$t('user.source')"/> --> <!-- <el-table-column prop="source" :label="$t('user.source')"/> -->
<el-table-column :label="$t('commons.operating')" min-width="120px"> <el-table-column :label="$t('commons.operating')" min-width="120px">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"> <ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="del(scope.row)">
<template v-slot:behind> <template v-slot:behind>
<ms-table-operator-button <ms-table-operator-button
v-if="scope.row.isLocalUser" v-if="scope.row.isLocalUser"
...@@ -274,7 +275,12 @@ export default { ...@@ -274,7 +275,12 @@ export default {
roles: [], roles: [],
roleDatas: [], roleDatas: [],
userRoles: [], userRoles: [],
formType: 'add' formType: 'add',
permission: {
add: ['user:add'],
edit: ['user:edit'],
del: ['user:del']
}
} }
}, },
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
{{ scope.row.title }} {{ scope.row.title }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="Author" width="110" align="center"> <el-table-column v-permission="['menu:del']" label="Author" width="110" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.author }}</span> <span>{{ scope.row.author }}</span>
</template> </template>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论