角色切换

This commit is contained in:
shiziyuan9527 2020-02-17 23:58:09 +08:00
parent a30af57c28
commit dac30f47a5
13 changed files with 426 additions and 28 deletions

View File

@ -0,0 +1,11 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.dto.UserRoleHelpDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtUserRoleMapper {
List<UserRoleHelpDTO> getUserRoleHelpList(@Param("userId") String userId);
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtUserRoleMapper">
<resultMap id="BaseResultMap" type="io.metersphere.dto.LoadTestDTO"
extends="io.metersphere.base.mapper.LoadTestMapper.BaseResultMap">
<result column="project_name" property="projectName"/>
</resultMap>
<select id="getUserRoleHelpList" parameterType="java.lang.String"
resultType="io.metersphere.dto.UserRoleHelpDTO">
SELECT
user_role.role_id AS roleId,
role.`name` AS roleName,
user_role.source_id AS sourceId,
IF(workspace.id IS NULL,IF(organization.id IS NULL,'',organization.`name`),workspace.name) AS sourceName,
IF(workspace.id IS NULL,NULL,workspace.organization_id) AS parentId
FROM user_role LEFT JOIN role ON role.id = user_role.role_id
LEFT JOIN workspace ON workspace.id = user_role.source_id
LEFT JOIN organization ON organization.id = user_role.source_id
WHERE user_role.user_id = #{userId}
</select>
</mapper>

View File

@ -3,10 +3,10 @@ package io.metersphere.controller;
import io.metersphere.base.domain.Role;
import io.metersphere.base.domain.User;
import io.metersphere.dto.UserDTO;
import io.metersphere.dto.UserOperateDTO;
import io.metersphere.dto.UserRoleDTO;
import io.metersphere.service.UserService;
import io.metersphere.user.SessionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@ -35,4 +35,20 @@ public class UserController {
public List<Role> getUserRolesList(@PathVariable(value = "userId") String userId) {
return userService.getUserRolesList(userId);
}
@GetMapping("/rolelist/{userId}")
public List<UserRoleDTO> convertUserRoleDTO(@PathVariable(value = "userId") String userId) {
return userService.getUserRoleList(userId);
}
@PostMapping("/switch/source/{sourceId}")
public void switchUserRole(@PathVariable (value = "sourceId") String sourceId) {
UserDTO user = SessionUtils.getUser();
userService.switchUserRole(user, sourceId);
}
@GetMapping("/info/{userId}")
public User getUserInfo(@PathVariable(value = "userId") String userId) {
return userService.getUserInfo(userId);
}
}

View File

@ -20,6 +20,16 @@ public class UserDTO {
private Long updateTime;
private String lastSourceId;
public String getLastSourceId() {
return lastSourceId;
}
public void setLastSourceId(String lastSourceId) {
this.lastSourceId = lastSourceId;
}
private List<Role> roles = new ArrayList<>();
public List<Role> getRoles() {

View File

@ -0,0 +1,68 @@
package io.metersphere.dto;
public class UserRoleDTO {
private String id;
private String roleId;
private String type;
private String name;
private String desc;
private String parentId;
private Boolean switchable = true;
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Boolean getSwitchable() {
return switchable;
}
public void setSwitchable(Boolean switchable) {
this.switchable = switchable;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
}

View File

@ -0,0 +1,50 @@
package io.metersphere.dto;
public class UserRoleHelpDTO {
private String roleId;
private String roleName;
private String sourceId;
private String sourceName;
private String parentId;
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getSourceId() {
return sourceId;
}
public void setSourceId(String sourceId) {
this.sourceId = sourceId;
}
public String getSourceName() {
return sourceName;
}
public void setSourceName(String sourceName) {
this.sourceName = sourceName;
}
}

View File

@ -1,12 +1,16 @@
package io.metersphere.service;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.OrganizationMapper;
import io.metersphere.base.mapper.RoleMapper;
import io.metersphere.base.mapper.UserMapper;
import io.metersphere.base.mapper.UserRoleMapper;
import io.metersphere.base.mapper.ext.ExtUserRoleMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.dto.UserDTO;
import io.metersphere.dto.UserOperateDTO;
import io.metersphere.dto.UserRoleDTO;
import io.metersphere.dto.UserRoleHelpDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -14,7 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -27,6 +31,10 @@ public class UserService {
private RoleMapper roleMapper;
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private ExtUserRoleMapper extUserRoleMapper;
@Resource
private OrganizationMapper organizationMapper;
public UserDTO insert(User user) {
checkUserParam(user);
@ -113,4 +121,106 @@ public class UserService {
roleExample.createCriteria().andIdIn(roleIds);
return roleMapper.selectByExample(roleExample);
}
public List<UserRoleDTO> getUserRoleList(String userId) {
if (StringUtils.isEmpty(userId)) {
return new ArrayList<>();
}
return convertUserRoleDTO(extUserRoleMapper.getUserRoleHelpList(userId));
}
private List<UserRoleDTO> convertUserRoleDTO(List<UserRoleHelpDTO> helpDTOList) {
StringBuilder buffer = new StringBuilder();
Map<String, UserRoleDTO> roleMap = new HashMap<>();
List<UserRoleDTO> resultList = new ArrayList<>();
List<UserRoleDTO> otherList = new ArrayList<>();
Set<String> orgSet = new HashSet<>();
Set<String> workspaceSet = new HashSet<>();
for (UserRoleHelpDTO helpDTO : helpDTOList) {
UserRoleDTO userRoleDTO = roleMap.get(helpDTO.getSourceId());
if (userRoleDTO == null) {
userRoleDTO = new UserRoleDTO();
if (!StringUtils.isEmpty(helpDTO.getParentId())) {
workspaceSet.add(helpDTO.getParentId());
userRoleDTO.setType("workspace");
} else {
orgSet.add(helpDTO.getSourceId());
userRoleDTO.setType("organization");
}
userRoleDTO.setId(helpDTO.getSourceId());
userRoleDTO.setRoleId(helpDTO.getRoleId());
userRoleDTO.setName(helpDTO.getSourceName());
userRoleDTO.setParentId(helpDTO.getParentId());
userRoleDTO.setDesc(helpDTO.getRoleName());
} else {
userRoleDTO.setDesc(userRoleDTO.getDesc() + "," + helpDTO.getRoleName());
}
roleMap.put(helpDTO.getSourceId(), userRoleDTO);
}
if (!StringUtils.isEmpty(buffer.toString())) {
UserRoleDTO dto = new UserRoleDTO();
dto.setId("admin");
dto.setType("admin");
dto.setDesc(buffer.toString());
resultList.add(dto);
}
for (String org : orgSet) {
workspaceSet.remove(org);
}
List<UserRoleDTO> orgWorkSpace = new ArrayList<>(roleMap.values());
if (!CollectionUtils.isEmpty(workspaceSet)) {
for (String orgId : workspaceSet) {
Organization organization = organizationMapper.selectByPrimaryKey(orgId);
if (organization != null) {
UserRoleDTO dto = new UserRoleDTO();
dto.setId(orgId);
dto.setName(organization.getName());
dto.setSwitchable(false);
dto.setType("organization");
orgWorkSpace.add(dto);
}
}
}
orgWorkSpace.sort((o1, o2) -> {
if (o1.getParentId() == null) {
return -1;
}
if (o2.getParentId() == null) {
return 1;
}
return o1.getParentId().compareTo(o2.getParentId());
});
resultList.addAll(orgWorkSpace);
resultList.addAll(otherList);
return resultList;
}
public void switchUserRole(UserDTO user, String sourceId) {
User newUser = new User();
BeanUtils.copyProperties(user, newUser);
newUser.setLastSourceId(sourceId);
userMapper.updateByPrimaryKeySelective(newUser);
}
public User getUserInfo(String userId) {
return userMapper.selectByPrimaryKey(userId);
}
}

View File

@ -109,6 +109,8 @@
this.$post("signin", this.form, (response) => {
// cookie
Cookies.set(TokenKey, response.data);
//
localStorage.setItem("lastSourceId", JSON.parse(Cookies.get(TokenKey)).lastSourceId);
window.location.href = "/"
});
} else {

View File

@ -2,6 +2,7 @@
<el-col v-if="auth">
<el-row id="header-top" type="flex" justify="space-between" align="middle">
<a class="logo"/>
<ms-switch-user/>
<ms-user/>
</el-row>
<el-row id="header-bottom" type="flex" justify="space-between" align="middle">
@ -29,6 +30,7 @@
import MsSetting from "./components/HeaderSetting";
import MsView from "./components/router/View";
import MsUser from "./components/HeaderUser";
import MsSwitchUser from "./components/HeaderSwitchUser";
import MsWebSocket from "./components/websocket/WebSocket";
export default {
@ -49,7 +51,7 @@
window.location.href = "/login"
});
},
components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView},
components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView, MsSwitchUser},
methods: {
}
}

View File

@ -0,0 +1,114 @@
<template>
<el-row>
<el-button type="text" @click="open">切换角色-{{ currentUserRole }}</el-button>
<el-dialog title="角色列表" :visible.sync="createVisible" width="30%">
<el-tree :data="userRoleList"
@node-click="handleNodeClick"
:props="defaultProps"
></el-tree>
<div style="text-align: center; margin-top: 20px;">
<el-button type="info" size="mini" class="ms-button" @click="closeDialog">取消</el-button>
<el-button type="primary" size="mini" style="margin-left: 50px;" @click="changeSubmit">保存</el-button>
</div>
</el-dialog>
</el-row>
</template>
<script>
import Cookies from "js-cookie"
import {TokenKey} from "../../common/constants"
export default {
name: "MsSwitchUser",
computed: {
currentUserRole() {
return this.userInfo.lastSourceId;
}
},
created() {
this.getUserRoleList();
this.getUserInfo();
},
data() {
return {
createVisible: false,
defaultProps: {
children: 'children',
label: 'switchInfo'
},
switchInfo: '',
userRoleList: [],
selectNode:[],
userInfo: {},
userId: JSON.parse(Cookies.get(TokenKey)).id
}
},
methods: {
open() {
this.createVisible = true;
},
getUserRoleList() {
this.$get('user/rolelist/' + this.userId).then(response => {
let roleList = response.data.data;
let newRoleList = [];
roleList.forEach(item => {
// item.current = item.id === this.userInfo.lastSourceId;
item.current = item.roleId;
if (item.current) {
if (item.name) {
item.switchInfo = item.name + " [" + item.desc + "]";
} else {
item.switchInfo = "MeterSphere[系统管理员]";
}
}
if (!item.parentId) {
item.hasChild = false;
item.children = [];
newRoleList.push(item);
} else {
newRoleList.forEach(userRole => {
if (userRole.id === item.parentId) {
userRole.children.push(item);
userRole.hasChild = true;
}
})
}
})
this.userRoleList = newRoleList;
})
},
closeDialog() {
this.createVisible = false;
},
switchRole(selectNode) {
if (!selectNode.switchable) {
return;
}
this.$post("user/switch/source/" + selectNode.roleId).then(() => {
this.getUserInfo();
// localStorage.setItem("lastSourceId", "bbbbb");
this.closeDialog();
});
localStorage.setItem("lastSourceId", selectNode.roleId);
window.location.reload();
},
changeSubmit() {
this.switchRole(this.selectNode);
},
handleNodeClick(data) {
this.selectNode = data;
window.console.log(data)
},
getUserInfo() {
this.$get("/user/info/" + this.userId).then(response => {
this.userInfo = response.data.data;
})
}
}
}
</script>
<style scoped>
</style>

View File

@ -5,9 +5,9 @@
<font-awesome-icon class="icon account" :icon="['far', 'address-card']" size="lg"/>
<span>账号</span>
</template>
<el-menu-item index="/setting/user" v-permission="['admin']">用户</el-menu-item>
<el-menu-item index="/setting/testresourcepool" v-permission="['admin','org_admin']">测试资源池</el-menu-item>
<el-menu-item index="/setting/organization" v-permission="['test_user']">组织</el-menu-item>
<el-menu-item index="/setting/user" v-permission="['admin','test_user']">用户</el-menu-item>
<el-menu-item index="/setting/testresourcepool" v-permission="['test_user']">测试资源池</el-menu-item>
<el-menu-item index="/setting/organization" v-permission="['org_admin']">组织</el-menu-item>
<el-menu-item index="/setting/workspace">工作空间</el-menu-item>
<el-menu-item>API Keys</el-menu-item>
</el-submenu>

View File

@ -1,20 +1,16 @@
import router from './components/router/router'
import Cookies from 'js-cookie' // get token from cookie
import {TokenKey} from '../common/constants';
import store from "./store";
const whiteList = ['/login']; // no redirect whitelist
export const permission = {
inserted(el, binding) {
const { value } = binding
// user role list
const roles = store.state.roles
const { value } = binding;
const roles = localStorage.getItem("lastSourceId");
if (value && value instanceof Array && value.length > 0) {
const permissionRoles = value
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
const permissionRoles = value;
const hasPermission = permissionRoles.includes(roles);
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
@ -29,13 +25,12 @@ router.beforeEach(async (to, from, next) => {
// determine whether the user has logged in
const user = JSON.parse(Cookies.get(TokenKey));
if (user && user.roles.length > 0) {
if (user) {
if (to.path === '/login') {
next({path: '/'});
} else {
// const roles = user.roles.filter(r => r.id);
// TODO 设置路由的权限
store.commit("setRoles", user.roles.map(r => r.id))
next()
}
} else {

View File

@ -3,17 +3,7 @@ import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
roles: []
},
mutations: {
setRoles(state, data) {
state.roles = data
}
}
})
export default store
export default new Vuex.Store({})