fix(项目设置): 全局用户组权限可以被修改

--bug=1014839 --user=李玉号 【项目设置】项目设置中系统级别的全局用户组权限可以被修改
https://www.tapd.cn/55049933/s/1203887
This commit is contained in:
shiziyuan9527 2022-07-19 10:56:49 +08:00 committed by shiziyuan9527
parent 0310f45203
commit aa50a5ee42
14 changed files with 124 additions and 101 deletions

View File

@ -41,6 +41,23 @@
</foreach> </foreach>
</if> </if>
</where> </where>
union distinct
select g.*, p.name as scopeName from `group` g, project p
<where>
and g.scope_id = p.id
<if test="request.types != null and request.types.size() > 0">
AND g.type in
<foreach collection="request.types" item="type" separator="," open="(" close=")">
#{type}
</foreach>
</if>
<if test="request.scopes != null and request.scopes.size() > 0">
AND g.scope_id in
<foreach collection="request.scopes" item="scope" separator="," open="(" close=")">
#{scope}
</foreach>
</if>
</where>
) temp ) temp
<if test="request.name != null and request.name!=''"> <if test="request.name != null and request.name!=''">
where temp.name like CONCAT('%', #{request.name},'%') where temp.name like CONCAT('%', #{request.name},'%')

View File

@ -5,5 +5,6 @@ import lombok.Data;
@Data @Data
public class GroupRequest { public class GroupRequest {
private String resourceId; private String resourceId;
private String projectId;
private String type; private String type;
} }

View File

@ -28,4 +28,5 @@ public class EditGroupRequest extends Group {
private String userGroupId; private String userGroupId;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private boolean onlyQueryCurrentProject = false; private boolean onlyQueryCurrentProject = false;
private boolean onlyQueryGlobal = false;
} }

View File

@ -26,7 +26,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.poi.ss.formula.functions.T;
import org.mybatis.spring.SqlSessionUtils; import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -229,6 +228,9 @@ public class GroupService {
if (!StringUtils.equals(type, UserGroupType.SYSTEM)) { if (!StringUtils.equals(type, UserGroupType.SYSTEM)) {
criteria.andTypeEqualTo(type); criteria.andTypeEqualTo(type);
} }
if (BooleanUtils.isTrue(request.isOnlyQueryGlobal())) {
criteria.andScopeIdEqualTo(GLOBAL);
}
return groupMapper.selectByExample(example); return groupMapper.selectByExample(example);
} }
@ -262,6 +264,9 @@ public class GroupService {
String resourceId = request.getResourceId(); String resourceId = request.getResourceId();
String type = request.getType(); String type = request.getType();
List<String> scopeList = Arrays.asList(GLOBAL, resourceId); List<String> scopeList = Arrays.asList(GLOBAL, resourceId);
if (StringUtils.equals(type, UserGroupType.PROJECT) && StringUtils.isNotBlank(request.getProjectId())) {
scopeList = Arrays.asList(GLOBAL, resourceId, request.getProjectId());
}
GroupExample groupExample = new GroupExample(); GroupExample groupExample = new GroupExample();
groupExample.createCriteria().andScopeIdIn(scopeList) groupExample.createCriteria().andScopeIdIn(scopeList)
.andTypeEqualTo(type); .andTypeEqualTo(type);
@ -313,7 +318,8 @@ public class GroupService {
private Pager<List<GroupDTO>> getUserGroup(String groupType, EditGroupRequest request) { private Pager<List<GroupDTO>> getUserGroup(String groupType, EditGroupRequest request) {
List<String> types; List<String> types;
String workspaceId = SessionUtils.getCurrentWorkspaceId(); String workspaceId = SessionUtils.getCurrentWorkspaceId();
List<String> scopes = Arrays.asList(GLOBAL, workspaceId); String projectId = SessionUtils.getCurrentProjectId();
List<String> scopes = Arrays.asList(GLOBAL, workspaceId, projectId);
int goPage = request.getGoPage(); int goPage = request.getGoPage();
int pageSize = request.getPageSize(); int pageSize = request.getPageSize();
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
@ -323,7 +329,6 @@ public class GroupService {
types = map.get(groupType); types = map.get(groupType);
request.setTypes(types); request.setTypes(types);
request.setScopes(scopes); request.setScopes(scopes);
// request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<GroupDTO> groups = extGroupMapper.getGroupList(request); List<GroupDTO> groups = extGroupMapper.getGroupList(request);
buildUserInfo(groups); buildUserInfo(groups);
return PageUtils.setPageInfo(page, groups); return PageUtils.setPageInfo(page, groups);
@ -341,36 +346,17 @@ public class GroupService {
} }
public List<?> getResource(String type, String groupId) { public List<?> getResource(String type, String groupId) {
List<T> resource = new ArrayList<>();
Group group = groupMapper.selectByPrimaryKey(groupId); Group group = groupMapper.selectByPrimaryKey(groupId);
String workspaceId = group.getScopeId(); if (group == null) {
return new ArrayList<>();
}
if (StringUtils.equals(UserGroupType.WORKSPACE, type)) { if (StringUtils.equals(UserGroupType.WORKSPACE, type)) {
WorkspaceExample workspaceExample = new WorkspaceExample(); return workspaceService.getWorkspaceGroupResource(group.getScopeId());
WorkspaceExample.Criteria criteria = workspaceExample.createCriteria();
if (!StringUtils.equals(workspaceId, GLOBAL)) {
criteria.andIdEqualTo(workspaceId);
}
return workspaceMapper.selectByExample(workspaceExample);
} }
if (StringUtils.equals(UserGroupType.PROJECT, type)) { if (StringUtils.equals(UserGroupType.PROJECT, type)) {
ProjectExample projectExample = new ProjectExample(); return workspaceService.getProjectGroupResource(group.getScopeId());
ProjectExample.Criteria pc = projectExample.createCriteria();
WorkspaceExample workspaceExample = new WorkspaceExample();
WorkspaceExample.Criteria criteria = workspaceExample.createCriteria();
if (!StringUtils.equals(workspaceId, GLOBAL)) {
criteria.andIdEqualTo(workspaceId);
List<Workspace> workspaces = workspaceMapper.selectByExample(workspaceExample);
List<String> list = workspaces.stream().map(Workspace::getId).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(list)) {
pc.andWorkspaceIdIn(list);
}
}
return projectMapper.selectByExample(projectExample);
} }
return new ArrayList<>();
return resource;
} }
public List<User> getGroupUser(EditGroupRequest request) { public List<User> getGroupUser(EditGroupRequest request) {

View File

@ -60,6 +60,8 @@ public class WorkspaceService {
@Resource @Resource
private EnvironmentGroupService environmentGroupService; private EnvironmentGroupService environmentGroupService;
private static final String GLOBAL = "global";
public Workspace saveWorkspace(Workspace workspace) { public Workspace saveWorkspace(Workspace workspace) {
if (StringUtils.isBlank(workspace.getName())) { if (StringUtils.isBlank(workspace.getName())) {
MSException.throwException(Translator.get("workspace_name_is_null")); MSException.throwException(Translator.get("workspace_name_is_null"));
@ -299,37 +301,47 @@ public class WorkspaceService {
public WorkspaceResource listResource(String groupId, String type) { public WorkspaceResource listResource(String groupId, String type) {
Group group = groupMapper.selectByPrimaryKey(groupId); Group group = groupMapper.selectByPrimaryKey(groupId);
String workspaceId = group.getScopeId();
WorkspaceResource resource = new WorkspaceResource(); WorkspaceResource resource = new WorkspaceResource();
if (group == null) {
return resource;
}
if (StringUtils.equals(UserGroupType.WORKSPACE, type)) { if (StringUtils.equals(UserGroupType.WORKSPACE, type)) {
WorkspaceExample workspaceExample = new WorkspaceExample(); resource.setWorkspaces(getWorkspaceGroupResource(group.getScopeId()));
WorkspaceExample.Criteria criteria = workspaceExample.createCriteria();
if (!StringUtils.equals(workspaceId, "global")) {
criteria.andIdEqualTo(workspaceId);
}
List<Workspace> workspaces = workspaceMapper.selectByExample(workspaceExample);
resource.setWorkspaces(workspaces);
} }
if (StringUtils.equals(UserGroupType.PROJECT, type)) { if (StringUtils.equals(UserGroupType.PROJECT, type)) {
ProjectExample projectExample = new ProjectExample(); resource.setProjects(getProjectGroupResource(group.getScopeId()));
ProjectExample.Criteria pc = projectExample.createCriteria();
WorkspaceExample workspaceExample = new WorkspaceExample();
WorkspaceExample.Criteria criteria = workspaceExample.createCriteria();
if (!StringUtils.equals(workspaceId, "global")) {
criteria.andIdEqualTo(workspaceId);
List<Workspace> workspaces = workspaceMapper.selectByExample(workspaceExample);
List<String> list = workspaces.stream().map(Workspace::getId).collect(Collectors.toList());
pc.andWorkspaceIdIn(list);
}
List<Project> projects = projectMapper.selectByExample(projectExample);
resource.setProjects(projects);
} }
return resource; return resource;
} }
public List<Workspace> getWorkspaceGroupResource(String scopeId) {
WorkspaceExample workspaceExample = new WorkspaceExample();
WorkspaceExample.Criteria criteria = workspaceExample.createCriteria();
if (!StringUtils.equals(scopeId, GLOBAL)) {
criteria.andIdEqualTo(scopeId);
}
return workspaceMapper.selectByExample(workspaceExample);
}
public List<Project> getProjectGroupResource(String scopeId) {
ProjectExample projectExample = new ProjectExample();
ProjectExample.Criteria criteria = projectExample.createCriteria();
if (StringUtils.equals(scopeId, GLOBAL)) {
return projectMapper.selectByExample(projectExample);
}
Workspace workspace = workspaceMapper.selectByPrimaryKey(scopeId);
if (workspace != null) {
criteria.andWorkspaceIdEqualTo(workspace.getId());
return projectMapper.selectByExample(projectExample);
}
Project project = projectMapper.selectByPrimaryKey(scopeId);
List<Project> list = new ArrayList<>();
if (project != null) {
list.add(project);
}
return list;
}
public List<String> getWorkspaceIds() { public List<String> getWorkspaceIds() {
return extWorkspaceMapper.getWorkspaceIds(); return extWorkspaceMapper.getWorkspaceIds();
} }

View File

@ -23,11 +23,9 @@
<el-form-item :label="$t('group.description')" prop="description"> <el-form-item :label="$t('group.description')" prop="description">
<el-input type="textarea" v-model="form.description" style="width: 83%"></el-input> <el-input type="textarea" v-model="form.description" style="width: 83%"></el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('group.global_group')"> <el-form-item :label="form.scopeId === 'global' ? $t('group.global_group') : $t('group.ws_share')">
<el-switch v-model="form.global" :disabled="dialogType === 'edit'" <el-switch v-model="isShare" :disabled="dialogType === 'edit'" @change="change"/>
@change="change(form.global)"></el-switch>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
@ -39,7 +37,7 @@
<script> <script>
import {GROUP_SYSTEM} from "@/common/js/constants"; import {GROUP_SYSTEM} from "@/common/js/constants";
import {getCurrentUserId, getCurrentWorkspaceId} from "@/common/js/utils"; import {getCurrentProjectID, getCurrentWorkspaceId} from "@/common/js/utils";
export default { export default {
name: "EditUserGroup", name: "EditUserGroup",
@ -69,7 +67,7 @@ export default {
show: true, show: true,
workspaces: [], workspaces: [],
title: this.$t('group.create'), title: this.$t('group.create'),
flag: false isShare: false
} }
}, },
props: { props: {
@ -95,7 +93,9 @@ export default {
create() { create() {
this.$refs['form'].validate(valid => { this.$refs['form'].validate(valid => {
if (valid) { if (valid) {
this.form.scopeId = getCurrentWorkspaceId(); if (!this.form.scopeId) {
this.form.scopeId = getCurrentProjectID();
}
this.$post("/user/group/add", this.form, () => { this.$post("/user/group/add", this.form, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.$emit("refresh") this.$emit("refresh")
@ -125,28 +125,16 @@ export default {
this.show = true; this.show = true;
this.dialogVisible = true; this.dialogVisible = true;
this.dialogType = type; this.dialogType = type;
this.form = Object.assign({type: 'PROJECT' ,global: false , scopeId: getCurrentWorkspaceId()}, row); if (row) {
this.isShare = row.scopeId === getCurrentWorkspaceId();
}
this.form = Object.assign({type: 'PROJECT' ,global: false , scopeId: ''}, row);
}, },
cancel() { cancel() {
this.dialogVisible = false; this.dialogVisible = false;
}, },
change(global) { change(share) {
this.$get("/user/group/list/ws/" + getCurrentWorkspaceId() + "/" + getCurrentUserId(), res => { this.form.scopeId = share ? getCurrentWorkspaceId() : getCurrentProjectID();
let data = res.data;
if (data) {
data.forEach(row => {
if (row.id === 'ws_admin') {
this.flag = true;
}
})
}
if (this.flag === true) {
this.show = this.isSystem ? false : !global;
} else {
this.form.global = false;
this.$warning(this.$t('group.ws_admin_global'))
}
})
}, },
changeGroup(val) { changeGroup(val) {
if (val === GROUP_SYSTEM) { if (val === GROUP_SYSTEM) {

View File

@ -48,15 +48,14 @@
<ms-table-operator :edit-permission="['PROJECT_GROUP:READ+EDIT']" <ms-table-operator :edit-permission="['PROJECT_GROUP:READ+EDIT']"
:delete-permission="['PROJECT_GROUP:READ+DELETE']" :delete-permission="['PROJECT_GROUP:READ+DELETE']"
@editClick="edit(scope.row)" @deleteClick="del(scope.row)" @editClick="edit(scope.row)" @deleteClick="del(scope.row)"
:isShow="flagChange(scope.row.scopeId ==='global')"> :isShow="isDisable(scope.row.scopeId)">
<template v-slot:middle> <template v-slot:middle>
<!-- <ms-table-operator-button tip="复制" icon="el-icon-document-copy" @exec="copy(scope.row)"/>-->
<ms-table-operator-button <ms-table-operator-button
v-permission="['PROJECT_GROUP:READ+SETTING_PERMISSION']" v-permission="['PROJECT_GROUP:READ+SETTING_PERMISSION']"
:tip="$t('group.set_permission')" :tip="$t('group.set_permission')"
icon="el-icon-s-tools" icon="el-icon-s-tools"
@exec="setPermission(scope.row)" @exec="setPermission(scope.row)"
:disabled="flagChange(scope.row.scopeId ==='global')"/> :disabled="isDisable(scope.row.scopeId)"/>
<ms-table-operator-button :tip="$t('group.view_permission')" icon="el-icon-view" @exec="viewPermission(scope.row)"/> <ms-table-operator-button :tip="$t('group.view_permission')" icon="el-icon-view" @exec="viewPermission(scope.row)"/>
</template> </template>
</ms-table-operator> </ms-table-operator>
@ -116,18 +115,20 @@ export default {
screenHeight: 'calc(100vh - 160px)', screenHeight: 'calc(100vh - 160px)',
groups: [], groups: [],
currentGroup: {}, currentGroup: {},
flag: false isWorkspaceAdmin: false
}; };
}, },
created() { created() {
this.$get("/user/group/list/ws/" + getCurrentWorkspaceId() + "/" + getCurrentUserId(), res => { this.$get("/user/group/list/ws/" + getCurrentWorkspaceId() + "/" + getCurrentUserId(), res => {
let data = res.data; let data = res.data;
if (data) { if (!data) {
data.forEach(row => { return;
if (row.id === 'ws_admin') { }
this.flag = true; for (let da of data) {
} if (da.id === 'ws_admin') {
}) this.isWorkspaceAdmin = true;
break;
}
} }
}) })
}, },
@ -156,13 +157,12 @@ export default {
}); });
} }
}, },
flagChange(data) { isDisable(scopeId) {
if (this.flag) { if (scopeId === 'global') {
return false; return true; //
} else if (data) {
return true;
} else { } else {
return false; // .
return scopeId === getCurrentProjectID() ? false : !this.isWorkspaceAdmin;
} }
}, },
viewPermission(row) { viewPermission(row) {

View File

@ -48,6 +48,8 @@
<script> <script>
import UserOptionItem from "@/business/components/settings/common/UserOptionItem"; import UserOptionItem from "@/business/components/settings/common/UserOptionItem";
import {GROUP_PROJECT} from "@/common/js/constants";
import {getCurrentProjectID} from "@/common/js/utils";
export default { export default {
name: "AddMember", name: "AddMember",
@ -82,6 +84,12 @@ export default {
return ''; return '';
} }
}, },
projectId: {
type: String,
default() {
return '';
}
},
userResourceUrl: { userResourceUrl: {
type: String, type: String,
default() { default() {
@ -112,9 +120,13 @@ export default {
this.userList = response.data; this.userList = response.data;
this.copyUserList = response.data; this.copyUserList = response.data;
}) })
this.result = this.$post('/user/group/list', {type: this.groupType, resourceId: this.groupScopeId}, response => { let param = {type: this.groupType, resourceId: this.groupScopeId};
if (this.groupType === GROUP_PROJECT) {
param.projectId = this.projectId || getCurrentProjectID();
}
this.result = this.$post('/user/group/list', param, response => {
this.$set(this.form, "groups", response.data); this.$set(this.form, "groups", response.data);
}) });
}, },
close() { close() {
this.dialogVisible = false; this.dialogVisible = false;

View File

@ -43,7 +43,7 @@
<script> <script>
import ElUploadList from "element-ui/packages/upload/src/upload-list"; import ElUploadList from "element-ui/packages/upload/src/upload-list";
import MsTableButton from '../../../../components/common/components/MsTableButton'; import MsTableButton from '../../../../components/common/components/MsTableButton';
import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter"; import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
import {GROUP_PROJECT} from "@/common/js/constants"; import {GROUP_PROJECT} from "@/common/js/constants";
@ -171,7 +171,7 @@ export default {
getProjectUserGroup() { getProjectUserGroup() {
// //
if (this.cascaderLevel === 2) { if (this.cascaderLevel === 2) {
this.$post("/user/group/get", {type: GROUP_PROJECT}, (res) => { this.$post("/user/group/get", {type: GROUP_PROJECT, onlyQueryGlobal: true}, (res) => {
this.projectUserGroups = res.data ? res.data : []; this.projectUserGroups = res.data ? res.data : [];
}); });
} else if (this.cascaderLevel === 1) { } else if (this.cascaderLevel === 1) {

View File

@ -132,7 +132,7 @@ export default {
}) })
}, },
getWorkspaceUserGroup() { getWorkspaceUserGroup() {
this.$post("/user/group/get", {type: GROUP_WORKSPACE}, (res) => { this.$post("/user/group/get", {type: GROUP_WORKSPACE, onlyQueryGlobal: true}, (res) => {
this.workspaceUserGroups = res.data ? res.data : []; this.workspaceUserGroups = res.data ? res.data : [];
}) })
} }

View File

@ -171,6 +171,7 @@
<add-member <add-member
:group-type="'PROJECT'" :group-type="'PROJECT'"
:group-scope-id="workspaceId" :group-scope-id="workspaceId"
:project-id="rowProjectId"
ref="addMember" ref="addMember"
:user-resource-url="'user/ws/current/member/list'" :user-resource-url="'user/ws/current/member/list'"
@submit="submitForm"/> @submit="submitForm"/>
@ -268,7 +269,8 @@ export default {
dialogTotal: 0, dialogTotal: 0,
currentProjectId: "", currentProjectId: "",
userList: [], userList: [],
labelWidth: '150px' labelWidth: '150px',
rowProjectId: ""
}; };
}, },
props: { props: {
@ -408,6 +410,7 @@ export default {
return path + "/" + this.dialogCurrentPage + "/" + this.dialogPageSize; return path + "/" + this.dialogCurrentPage + "/" + this.dialogPageSize;
}, },
cellClick(row) { cellClick(row) {
this.rowProjectId = row.id;
// currentRow // currentRow
this.currentWorkspaceRow = row; this.currentWorkspaceRow = row;
this.currentProjectId = row.id; this.currentProjectId = row.id;

View File

@ -933,7 +933,8 @@ export default {
please_select_group: 'Please Select Group', please_select_group: 'Please Select Group',
global: 'Global', global: 'Global',
unable_to_remove_current_member: 'Unable to remove currently logged in user!', unable_to_remove_current_member: 'Unable to remove currently logged in user!',
ws_admin_global: 'Only workspace administrators can create global user groups' ws_admin_global: 'Only workspace administrators can create global user groups',
ws_share: 'Workspace sharing'
}, },
role: { role: {
please_choose_role: 'Please Choose Role', please_choose_role: 'Please Choose Role',

View File

@ -940,7 +940,8 @@ export default {
please_select_group: '请选择用户组', please_select_group: '请选择用户组',
global: '全局', global: '全局',
unable_to_remove_current_member: '无法移除当前登录用户!', unable_to_remove_current_member: '无法移除当前登录用户!',
ws_admin_global: '工作空间管理员才可以创建全局用户组' ws_admin_global: '工作空间管理员才可以创建全局用户组',
ws_share: '工作空间共享'
}, },
role: { role: {
please_choose_role: '请选择角色', please_choose_role: '请选择角色',

View File

@ -937,7 +937,8 @@ export default {
please_select_group: '請選擇用戶組', please_select_group: '請選擇用戶組',
global: '全局', global: '全局',
unable_to_remove_current_member: '無法移除當前登錄用戶!', unable_to_remove_current_member: '無法移除當前登錄用戶!',
ws_admin_global: '工作空間管理員才可以創建全局用戶組' ws_admin_global: '工作空間管理員才可以創建全局用戶組',
ws_share: '工作空間共享'
}, },
role: { role: {
please_choose_role: '請選擇角色', please_choose_role: '請選擇角色',