refactor(系统设置): 添加成员优化

--story=1008245 --user=李玉号 系统设置用户列表&添加成员优化
https://www.tapd.cn/55049933/s/1191441
This commit is contained in:
shiziyuan9527 2022-06-28 19:12:06 +08:00 committed by shiziyuan9527
parent 73896d8e1c
commit 53dc397e51
7 changed files with 184 additions and 119 deletions

View File

@ -1,9 +1,14 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserGroup implements Serializable {
private String id;

View File

@ -52,7 +52,12 @@
AND u.email like CONCAT('%', #{userRequest.email},'%')
</if>
</where>
order by u.update_time desc
<if test="userRequest.orders != null and userRequest.orders.size() > 0">
ORDER BY
<foreach collection="userRequest.orders" separator="," item="order">
${order.name} ${order.type}
</foreach>
</if>
</select>
<select id="queryTypeByIds" parameterType="java.lang.String" resultType="io.metersphere.notice.domain.UserDetail">
SELECT

View File

@ -99,7 +99,7 @@ public class UserController {
@PostMapping("/special/ws/member/add")
@MsAuditLog(module = OperLogModule.WORKSPACE_MEMBER, type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#request.userIds,#request.workspaceId)", msClass = UserService.class)
public void addMemberByAdmin(@RequestBody AddMemberRequest request) {
userService.addMember(request);
userService.addWorkspaceMember(request);
}
@GetMapping("/special/ws/member/delete/{workspaceId}/{userId}")
@ -204,16 +204,11 @@ public class UserController {
@PostMapping("/ws/member/add")
@MsAuditLog(module = OperLogModule.WORKSPACE_MEMBER, type = OperLogConstants.CREATE, title = "添加工作空间成员")
public void addMember(@RequestBody AddMemberRequest request) {
String wsId = request.getWorkspaceId();
// workspaceService.checkWorkspaceOwner(wsId);
userService.addMember(request);
userService.addWorkspaceMember(request);
}
@PostMapping("/project/member/add")
// @MsAuditLog(module = "workspace_member", type = OperLogConstants.CREATE, title = "添加项目成员成员")
public void addProjectMember(@RequestBody AddMemberRequest request) {
// workspaceService.checkWorkspaceOwner(wsId);
userService.addProjectMember(request);
}
@ -223,7 +218,6 @@ public class UserController {
@GetMapping("/ws/member/delete/{workspaceId}/{userId}")
@MsAuditLog(module = OperLogModule.WORKSPACE_MEMBER, type = OperLogConstants.DELETE, title = "删除工作空间成员")
public void deleteMember(@PathVariable String workspaceId, @PathVariable String userId) {
// workspaceService.checkWorkspaceOwner(workspaceId);
String currentUserId = SessionUtils.getUser().getId();
if (StringUtils.equals(userId, currentUserId)) {
MSException.throwException(Translator.get("cannot_remove_current"));
@ -232,7 +226,6 @@ public class UserController {
}
@GetMapping("/project/member/delete/{projectId}/{userId}")
// @MsAuditLog(module = "workspace_member", type = OperLogConstants.DELETE, title = "删除工作空间成员")
public void deleteProjectMember(@PathVariable String projectId, @PathVariable String userId) {
String currentUserId = SessionUtils.getUser().getId();
if (StringUtils.equals(userId, currentUserId)) {

View File

@ -14,4 +14,5 @@ public class UserRequest {
boolean selectAll;
List<String> unSelectIds;
private List<OrderRequest> orders;
}

View File

@ -16,7 +16,6 @@ import io.metersphere.controller.request.GroupRequest;
import io.metersphere.controller.request.group.EditGroupRequest;
import io.metersphere.controller.request.group.EditGroupUserRequest;
import io.metersphere.dto.*;
import io.metersphere.i18n.Translator;
import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails;
@ -61,6 +60,8 @@ public class GroupService {
private WorkspaceMapper workspaceMapper;
@Resource
private ProjectMapper projectMapper;
@Resource
private UserMapper userMapper;
private static final String GLOBAL = "global";
@ -412,47 +413,63 @@ public class GroupService {
}
public void addGroupUser(EditGroupUserRequest request) {
String groupId = request.getGroupId();
Group group = groupMapper.selectByPrimaryKey(groupId);
List<String> userIds = request.getUserIds();
for (String userId : userIds) {
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId)
.andGroupIdEqualTo(groupId);
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
if (userGroups.size() > 0) {
MSException.throwException(Translator.get("user_already_exists") + ": " + userId);
} else {
this.addGroupUser(group, userId, request.getSourceIds());
if (StringUtils.isBlank(request.getGroupId()) || CollectionUtils.isEmpty(request.getUserIds())) {
LogUtil.info("add group user warning, please check param!");
return;
}
Group group = groupMapper.selectByPrimaryKey(request.getGroupId());
if (group == null) {
LogUtil.info("add group user warning, group is null. group id: " + request.getGroupId());
return;
}
if (StringUtils.equals(group.getType(), UserGroupType.SYSTEM)) {
this.addSystemGroupUser(group, request.getUserIds());
} else {
if (CollectionUtils.isNotEmpty(request.getSourceIds())) {
this.addNotSystemGroupUser(group, request.getUserIds(), request.getSourceIds());
}
}
}
private void addGroupUser(Group group, String userId, List<String> sourceIds) {
String id = group.getId();
String type = group.getType();
if (StringUtils.equals(type, UserGroupType.SYSTEM)) {
UserGroup userGroup = new UserGroup();
userGroup.setId(UUID.randomUUID().toString());
userGroup.setUserId(userId);
userGroup.setGroupId(id);
userGroup.setSourceId("system");
userGroup.setCreateTime(System.currentTimeMillis());
userGroup.setUpdateTime(System.currentTimeMillis());
userGroupMapper.insertSelective(userGroup);
} else {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
private void addSystemGroupUser(Group group, List<String> userIds) {
for (String userId : userIds) {
User user = userMapper.selectByPrimaryKey(userId);
if (user == null) {
continue;
}
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId).andGroupIdEqualTo(group.getId());
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
if (userGroups.size() <= 0) {
UserGroup userGroup = new UserGroup(UUID.randomUUID().toString(), userId, group.getId(),
"system", System.currentTimeMillis(), System.currentTimeMillis());
userGroupMapper.insertSelective(userGroup);
}
}
}
private void addNotSystemGroupUser(Group group, List<String> userIds, List<String> sourceIds) {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
for (String userId : userIds) {
User user = userMapper.selectByPrimaryKey(userId);
if (user == null) {
continue;
}
checkQuota(quotaService, group.getType(), sourceIds, 1);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserGroupMapper mapper = sqlSession.getMapper(UserGroupMapper.class);
checkQuota(quotaService, type, sourceIds, 1);
for (String sourceId : sourceIds) {
UserGroup userGroup = new UserGroup();
userGroup.setId(UUID.randomUUID().toString());
userGroup.setUserId(userId);
userGroup.setGroupId(id);
userGroup.setSourceId(sourceId);
userGroup.setCreateTime(System.currentTimeMillis());
userGroup.setUpdateTime(System.currentTimeMillis());
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId).andGroupIdEqualTo(group.getId());
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
List<String> existSourceIds = userGroups.stream().map(UserGroup::getSourceId).collect(Collectors.toList());
List<String> toAddSourceIds = new ArrayList<>(sourceIds);
toAddSourceIds.removeAll(existSourceIds);
for (String sourceId : toAddSourceIds) {
UserGroup userGroup = new UserGroup(UUID.randomUUID().toString(), userId, group.getId(),
sourceId, System.currentTimeMillis(), System.currentTimeMillis());
mapper.insertSelective(userGroup);
}
sqlSession.flushStatements();

View File

@ -9,10 +9,7 @@ import io.metersphere.base.mapper.ext.*;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.CodingUtil;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.commons.utils.*;
import io.metersphere.controller.ResultHolder;
import io.metersphere.controller.request.LoginRequest;
import io.metersphere.controller.request.WorkspaceRequest;
@ -165,13 +162,6 @@ public class UserService {
}
}
private void checkQuota(QuotaService quotaService, String type, List<String> sourceIds, int size) {
if (quotaService != null) {
Map<String, Integer> addMemberMap = sourceIds.stream().collect(Collectors.toMap(id -> id, id -> size));
quotaService.checkMemberCount(addMemberMap, type);
}
}
public User selectUser(String userId, String email) {
User user = userMapper.selectByPrimaryKey(userId);
if (user == null) {
@ -328,6 +318,7 @@ public class UserService {
}
public List<User> getUserListWithRequest(io.metersphere.controller.request.UserRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders(), "create_time"));
return extUserMapper.getUserList(request);
}
@ -458,32 +449,8 @@ public class UserService {
return extUserGroupMapper.getMemberList(request);
}
public void addMember(AddMemberRequest request) {
if (!CollectionUtils.isEmpty(request.getUserIds())) {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
if (CollectionUtils.isNotEmpty(request.getUserIds())) {
checkQuota(quotaService, "WORKSPACE", Collections.singletonList(request.getWorkspaceId()), request.getUserIds().size());
}
for (String userId : request.getUserIds()) {
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId).andSourceIdEqualTo(request.getWorkspaceId());
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
if (userGroups.size() > 0) {
MSException.throwException(Translator.get("user_already_exists"));
} else {
for (String groupId : request.getGroupIds()) {
UserGroup userGroup = new UserGroup();
userGroup.setGroupId(groupId);
userGroup.setSourceId(request.getWorkspaceId());
userGroup.setUserId(userId);
userGroup.setId(UUID.randomUUID().toString());
userGroup.setUpdateTime(System.currentTimeMillis());
userGroup.setCreateTime(System.currentTimeMillis());
userGroupMapper.insertSelective(userGroup);
}
}
}
}
public void addWorkspaceMember(AddMemberRequest request) {
this.addGroupMember("WORKSPACE", request.getWorkspaceId(), request.getUserIds(), request.getGroupIds());
}
public void deleteMember(String workspaceId, String userId) {
@ -1198,32 +1165,78 @@ public class UserService {
}
public void addProjectMember(AddMemberRequest request) {
if (CollectionUtils.isEmpty(request.getUserIds())) {
LogUtil.info("add project member warning, request param user id list empty!");
this.addGroupMember("PROJECT", request.getProjectId(), request.getUserIds(), request.getGroupIds());
}
/**
* 添加项目工作空间成员
*
* @param type 项目工作空间
* @param sourceId project_id | workspace_id
* @param userIds 成员ID列表
* @param groupIds 用户组ID列表
*/
private void addGroupMember(String type, String sourceId, List<String> userIds, List<String> groupIds) {
if (!StringUtils.equalsAny(type, "PROJECT", "WORKSPACE") || StringUtils.isBlank(sourceId)
|| CollectionUtils.isEmpty(userIds) || CollectionUtils.isEmpty(groupIds)) {
LogUtil.info("add member warning, please check param!");
return;
}
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
if (CollectionUtils.isNotEmpty(request.getUserIds())) {
checkQuota(quotaService, "PROJECT", Collections.singletonList(request.getProjectId()), request.getUserIds().size());
}
for (String userId : request.getUserIds()) {
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId).andSourceIdEqualTo(request.getProjectId());
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
if (userGroups.size() > 0) {
MSException.throwException(Translator.get("user_already_exists"));
} else {
for (String groupId : request.getGroupIds()) {
UserGroup userGroup = new UserGroup();
userGroup.setGroupId(groupId);
userGroup.setSourceId(request.getProjectId());
userGroup.setUserId(userId);
userGroup.setId(UUID.randomUUID().toString());
userGroup.setUpdateTime(System.currentTimeMillis());
userGroup.setCreateTime(System.currentTimeMillis());
userGroupMapper.insertSelective(userGroup);
}
this.checkQuotaOfMemberSize(type, sourceId, userIds);
List<String> dbOptionalGroupIds = this.getGroupIdsByType(type, sourceId);
for (String userId : userIds) {
User user = userMapper.selectByPrimaryKey(userId);
if (user == null) {
LogUtil.info("add member warning, invalid user id: " + userId);
continue;
}
List<String> toAddGroupIds = new ArrayList<>(groupIds);
List<String> existGroupIds = this.getUserExistSourceGroup(userId, sourceId);
toAddGroupIds.removeAll(existGroupIds);
toAddGroupIds.retainAll(dbOptionalGroupIds);
for (String groupId : toAddGroupIds) {
UserGroup userGroup = new UserGroup(UUID.randomUUID().toString(), userId, groupId,
sourceId, System.currentTimeMillis(), System.currentTimeMillis());
userGroupMapper.insertSelective(userGroup);
}
}
}
private List<String> getUserExistSourceGroup(String userId, String sourceId) {
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andUserIdEqualTo(userId).andSourceIdEqualTo(sourceId);
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
return userGroups.stream().map(UserGroup::getGroupId).collect(Collectors.toList());
}
private List<String> getGroupIdsByType(String type, String sourceId) {
// 某项目/工作空间下能查看到的用户组
List<String> scopeList = Arrays.asList("global", sourceId);
GroupExample groupExample = new GroupExample();
groupExample.createCriteria().andScopeIdIn(scopeList)
.andTypeEqualTo(type);
List<Group> groups = groupMapper.selectByExample(groupExample);
return groups.stream().map(Group::getId).collect(Collectors.toList());
}
/**
* 向单个工作空间或单个项目中添加成员时检查成员数量配额
*
* @param type PROJECT WORKSPACE
* @param sourceId project_id | workspace_id
* @param userIds 添加的用户id
*/
private void checkQuotaOfMemberSize(String type, String sourceId, List<String> userIds) {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
if (CollectionUtils.isNotEmpty(userIds)) {
checkQuota(quotaService, type, Collections.singletonList(sourceId), userIds.size());
}
}
private void checkQuota(QuotaService quotaService, String type, List<String> sourceIds, int size) {
if (quotaService != null) {
Map<String, Integer> addMemberMap = sourceIds.stream().collect(Collectors.toMap(id -> id, id -> size));
quotaService.checkMemberCount(addMemberMap, type);
}
}

View File

@ -12,6 +12,8 @@
<el-table border class="adjust-table ms-select-all-fixed" :data="tableData" style="width: 100%"
@select-all="handleSelectAll"
@select="handleSelect"
@sort-change="sort"
:header-cell-class-name="handleHeadAddClass"
:height="screenHeight"
ref="userTable">
<el-table-column type="selection" width="50"/>
@ -37,7 +39,7 @@
</template>
</el-table-column>
<el-table-column prop="email" :label="$t('commons.email')"/>
<el-table-column prop="status" :label="$t('commons.status')" width="120">
<el-table-column prop="status" :label="$t('commons.status')" width="120" sortable="custom">
<template v-slot:default="scope">
<el-switch :disabled="currentUserId === scope.row.id" v-model="scope.row.status"
inactive-color="#DCDFE6"
@ -47,7 +49,7 @@
/>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')">
<el-table-column prop="createTime" :label="$t('commons.create_time')" sortable="custom">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
@ -112,15 +114,15 @@ import MsTableHeader from "../../common/components/MsTableHeader";
import MsTableOperator from "../../common/components/MsTableOperator";
import MsDialogFooter from "../../common/components/MsDialogFooter";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import {getCurrentProjectID, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import {getCurrentProjectID, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsRolesTag from "../../common/components/MsRolesTag";
import {getCurrentUser} from "@/common/js/utils";
import {PHONE_REGEX} from "@/common/js/regex";
import UserImport from "@/business/components/settings/system/components/UserImport";
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
import {
_handleSelect,
_handleSelectAll,
_sort,
getSelectDataCounts,
setUnSelectIds,
toggleAllSelection
@ -492,19 +494,48 @@ export default {
param.condition = this.condition;
return param;
},
sort(column) {
if (this.condition.orders) {
let index = this.condition.orders.findIndex(o => o.name.replace('_', '').toLowerCase() === column.column.property.toLowerCase());
if (index !== -1) {
this.condition.orders.splice(index, 1);
}
}
_sort(column, this.condition);
this.clearSelectRows();
this.search();
},
handleHeadAddClass({column}) {
if (!column || !column.property || !column.sortable || !this.condition.orders) {
return;
}
let order = this.condition.orders.find(o => o.name.replace('_', '').toLowerCase() === column.property.toLowerCase());
if (!order) {
return;
}
if (!order.type) {
column.order = '';
} else {
column.order = order.type === 'desc' ? 'descending' : 'ascending';
}
},
clearSelectRows() {
this.selectRows.clear();
this.selectIds = [];
if(!this.condition.selectAll){
this.condition.selectAll = false;
this.condition.unSelectIds = [];
}
this.selectDataCounts = 0;
if (this.$refs.userTable) {
this.$refs.userTable.clearSelection();
}
},
}
}
</script>
<style scoped>
/*/deep/ .el-table__fixed-right {*/
/* height: 100% !important;*/
/*}*/
/*/deep/ .el-table__fixed {*/
/* height: 110px !important;*/
/*}*/
/deep/ .ms-select-all-fixed th:first-child.el-table-column--selection {
margin-top: 0px;
}