refactor(系统设置): 组织至少保留一个管理员
This commit is contained in:
parent
68bd55647d
commit
5662e5abe7
|
@ -9,6 +9,7 @@ import io.metersphere.project.request.ProjectMemberBatchDeleteRequest;
|
||||||
import io.metersphere.project.request.ProjectMemberEditRequest;
|
import io.metersphere.project.request.ProjectMemberEditRequest;
|
||||||
import io.metersphere.project.request.ProjectMemberRequest;
|
import io.metersphere.project.request.ProjectMemberRequest;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
|
import io.metersphere.sdk.constants.InternalUserRole;
|
||||||
import io.metersphere.sdk.constants.UserRoleEnum;
|
import io.metersphere.sdk.constants.UserRoleEnum;
|
||||||
import io.metersphere.sdk.constants.UserRoleType;
|
import io.metersphere.sdk.constants.UserRoleType;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
@ -223,6 +224,14 @@ public class ProjectMemberService {
|
||||||
List<LogDTO> logs = new ArrayList<>();
|
List<LogDTO> logs = new ArrayList<>();
|
||||||
// 项目不存在, 则不移除
|
// 项目不存在, 则不移除
|
||||||
checkProjectExist(projectId);
|
checkProjectExist(projectId);
|
||||||
|
//判断用户是不是最后一个管理员 如果是 就报错
|
||||||
|
UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample();
|
||||||
|
userRoleRelationExample.createCriteria().andUserIdNotEqualTo(userId)
|
||||||
|
.andSourceIdEqualTo(projectId)
|
||||||
|
.andRoleIdEqualTo(InternalUserRole.PROJECT_ADMIN.getValue());
|
||||||
|
if (userRoleRelationMapper.countByExample(userRoleRelationExample) == 0) {
|
||||||
|
throw new MSException(Translator.get("keep_at_least_one_administrator"));
|
||||||
|
}
|
||||||
// 移除成员, 则移除该成员在该项目下的所有用户组
|
// 移除成员, 则移除该成员在该项目下的所有用户组
|
||||||
UserRoleRelationExample example = new UserRoleRelationExample();
|
UserRoleRelationExample example = new UserRoleRelationExample();
|
||||||
example.createCriteria().andSourceIdEqualTo(projectId).andUserIdEqualTo(userId);
|
example.createCriteria().andSourceIdEqualTo(projectId).andUserIdEqualTo(userId);
|
||||||
|
@ -331,6 +340,7 @@ public class ProjectMemberService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取项目评论下拉成员选项
|
* 获取项目评论下拉成员选项
|
||||||
|
*
|
||||||
* @param keyword 搜索关键字
|
* @param keyword 搜索关键字
|
||||||
* @param projectId 项目ID
|
* @param projectId 项目ID
|
||||||
* @return 用户集合信息
|
* @return 用户集合信息
|
||||||
|
|
|
@ -196,6 +196,7 @@ public class ProjectMemberControllerTests extends BaseTest {
|
||||||
@Order(12)
|
@Order(12)
|
||||||
public void testRemoveMemberError() throws Exception {
|
public void testRemoveMemberError() throws Exception {
|
||||||
this.requestGet(REMOVE_MEMBER + "/default-project-member-x/default-project-member-user-1", status().is5xxServerError());
|
this.requestGet(REMOVE_MEMBER + "/default-project-member-x/default-project-member-user-1", status().is5xxServerError());
|
||||||
|
this.requestGet(REMOVE_MEMBER + "/default-project-member-test-1/admin", status().is5xxServerError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -21,7 +21,8 @@ INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id
|
||||||
INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUES
|
INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUES
|
||||||
(UUID(), 'default-project-member-user-1', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin'),
|
(UUID(), 'default-project-member-user-1', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin'),
|
||||||
(UUID(), 'default-project-member-user-2', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin'),
|
(UUID(), 'default-project-member-user-2', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin'),
|
||||||
(UUID(), 'default-project-member-user-del', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin');
|
(UUID(), 'default-project-member-user-del', 'project_admin', 'default-project-member-test', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin'),
|
||||||
|
(UUID(), 'admin', 'org_admin', 'default-project-member-test-1', 'default-organization-member-test', UNIX_TIMESTAMP() * 1000, 'admin');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import io.metersphere.validation.groups.Created;
|
||||||
import io.metersphere.validation.groups.Updated;
|
import io.metersphere.validation.groups.Updated;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -27,5 +28,6 @@ public class OrganizationEditRequest implements Serializable {
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Schema(description = "成员ID集合")
|
@Schema(description = "成员ID集合")
|
||||||
|
@NotEmpty(message = "{project.member_count.not_blank}", groups = {Created.class, Updated.class})
|
||||||
private List<String> userIds;
|
private List<String> userIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新组织名称
|
* 更新组织名称
|
||||||
|
*
|
||||||
* @param organizationDTO 组织请求参数
|
* @param organizationDTO 组织请求参数
|
||||||
*/
|
*/
|
||||||
public void updateName(OrganizationDTO organizationDTO) {
|
public void updateName(OrganizationDTO organizationDTO) {
|
||||||
|
@ -120,6 +121,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新组织
|
* 更新组织
|
||||||
|
*
|
||||||
* @param organizationDTO 组织请求参数
|
* @param organizationDTO 组织请求参数
|
||||||
*/
|
*/
|
||||||
public void update(OrganizationDTO organizationDTO) {
|
public void update(OrganizationDTO organizationDTO) {
|
||||||
|
@ -134,7 +136,6 @@ public class OrganizationService {
|
||||||
List<String> addOrgAdmins = organizationDTO.getUserIds();
|
List<String> addOrgAdmins = organizationDTO.getUserIds();
|
||||||
// 旧的组织管理员ID
|
// 旧的组织管理员ID
|
||||||
List<String> oldOrgAdmins = getOrgAdminIds(organizationDTO.getId());
|
List<String> oldOrgAdmins = getOrgAdminIds(organizationDTO.getId());
|
||||||
if (CollectionUtils.isNotEmpty(addOrgAdmins)) {
|
|
||||||
// 需要新增组织管理员ID
|
// 需要新增组织管理员ID
|
||||||
List<String> addIds = addOrgAdmins.stream().filter(addOrgAdmin -> !oldOrgAdmins.contains(addOrgAdmin)).toList();
|
List<String> addIds = addOrgAdmins.stream().filter(addOrgAdmin -> !oldOrgAdmins.contains(addOrgAdmin)).toList();
|
||||||
// 需要删除的组织管理员ID
|
// 需要删除的组织管理员ID
|
||||||
|
@ -152,18 +153,11 @@ public class OrganizationService {
|
||||||
deleteExample.createCriteria().andSourceIdEqualTo(organizationDTO.getId()).andRoleIdEqualTo(InternalUserRole.ORG_ADMIN.getValue()).andUserIdIn(deleteIds);
|
deleteExample.createCriteria().andSourceIdEqualTo(organizationDTO.getId()).andRoleIdEqualTo(InternalUserRole.ORG_ADMIN.getValue()).andUserIdIn(deleteIds);
|
||||||
userRoleRelationMapper.deleteByExample(deleteExample);
|
userRoleRelationMapper.deleteByExample(deleteExample);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 前端传入的组织管理员ID为空,删除所有组织管理员
|
|
||||||
if (CollectionUtils.isNotEmpty(oldOrgAdmins)) {
|
|
||||||
UserRoleRelationExample example = new UserRoleRelationExample();
|
|
||||||
example.createCriteria().andSourceIdEqualTo(organizationDTO.getId()).andRoleIdEqualTo(InternalUserRole.ORG_ADMIN.getValue());
|
|
||||||
userRoleRelationMapper.deleteByExample(example);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除组织
|
* 删除组织
|
||||||
|
*
|
||||||
* @param organizationDeleteRequest 组织删除参数
|
* @param organizationDeleteRequest 组织删除参数
|
||||||
*/
|
*/
|
||||||
public void delete(OrganizationDeleteRequest organizationDeleteRequest) {
|
public void delete(OrganizationDeleteRequest organizationDeleteRequest) {
|
||||||
|
@ -176,6 +170,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复组织
|
* 恢复组织
|
||||||
|
*
|
||||||
* @param id 组织ID
|
* @param id 组织ID
|
||||||
*/
|
*/
|
||||||
public void recover(String id) {
|
public void recover(String id) {
|
||||||
|
@ -185,6 +180,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开启组织
|
* 开启组织
|
||||||
|
*
|
||||||
* @param id 组织ID
|
* @param id 组织ID
|
||||||
*/
|
*/
|
||||||
public void enable(String id) {
|
public void enable(String id) {
|
||||||
|
@ -194,6 +190,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 结束组织
|
* 结束组织
|
||||||
|
*
|
||||||
* @param id 组织ID
|
* @param id 组织ID
|
||||||
*/
|
*/
|
||||||
public void disable(String id) {
|
public void disable(String id) {
|
||||||
|
@ -318,6 +315,14 @@ public class OrganizationService {
|
||||||
public void removeMember(String organizationId, String userId, String currentUser) {
|
public void removeMember(String organizationId, String userId, String currentUser) {
|
||||||
List<LogDTO> logs = new ArrayList<>();
|
List<LogDTO> logs = new ArrayList<>();
|
||||||
checkOrgExistById(organizationId);
|
checkOrgExistById(organizationId);
|
||||||
|
//检查用户是不是最后一个管理员
|
||||||
|
UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample();
|
||||||
|
userRoleRelationExample.createCriteria().andUserIdNotEqualTo(userId)
|
||||||
|
.andSourceIdEqualTo(organizationId)
|
||||||
|
.andRoleIdEqualTo(InternalUserRole.ORG_ADMIN.getValue());
|
||||||
|
if (userRoleRelationMapper.countByExample(userRoleRelationExample) == 0) {
|
||||||
|
throw new MSException(Translator.get("keep_at_least_one_administrator"));
|
||||||
|
}
|
||||||
//删除组织下项目与成员的关系
|
//删除组织下项目与成员的关系
|
||||||
List<String> projectIds = getProjectIds(organizationId);
|
List<String> projectIds = getProjectIds(organizationId);
|
||||||
if (CollectionUtils.isNotEmpty(projectIds)) {
|
if (CollectionUtils.isNotEmpty(projectIds)) {
|
||||||
|
@ -1015,6 +1020,7 @@ public class OrganizationService {
|
||||||
/**
|
/**
|
||||||
* 校验组织是否存在
|
* 校验组织是否存在
|
||||||
* 这里使用静态方法,避免需要注入,导致循环依赖
|
* 这里使用静态方法,避免需要注入,导致循环依赖
|
||||||
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -1024,6 +1030,7 @@ public class OrganizationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 剩余天数
|
* 剩余天数
|
||||||
|
*
|
||||||
* @param deleteTime 删除时间
|
* @param deleteTime 删除时间
|
||||||
* @return 剩余天数
|
* @return 剩余天数
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -282,7 +282,7 @@ public class OrganizationControllerTests extends BaseTest {
|
||||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= organizationRequest.getPageSize());
|
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= organizationRequest.getPageSize());
|
||||||
//判断是否为空
|
//判断是否为空
|
||||||
List<OrgUserExtend> orgUserExtends = JSON.parseArray(JSON.toJSONString(pageData.getList()), OrgUserExtend.class);
|
List<OrgUserExtend> orgUserExtends = JSON.parseArray(JSON.toJSONString(pageData.getList()), OrgUserExtend.class);
|
||||||
Assertions.assertTrue(CollectionUtils.isEmpty(orgUserExtends));
|
Assertions.assertTrue(CollectionUtils.isNotEmpty(orgUserExtends));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,13 +309,14 @@ public class OrganizationControllerTests extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(14)
|
@Order(14)
|
||||||
public void removeOrgMemberSuccess() throws Exception {
|
public void removeOrgMemberSuccess() throws Exception {
|
||||||
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/sys_default_organization_6/sys_default_user", status().isOk());
|
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/sys_default_organization_6/sys_default_user4", status().isOk());
|
||||||
|
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/sys_default_organization_6/sys_default_user", status().is5xxServerError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(15)
|
@Order(15)
|
||||||
public void removeOrgMemberSuccessWithNoProject() throws Exception {
|
public void removeOrgMemberSuccessWithNoProject() throws Exception {
|
||||||
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/sys_default_organization_3/sys_default_user", status().isOk());
|
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/sys_default_organization_3/sys_default_user4", status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -425,7 +426,6 @@ public class OrganizationControllerTests extends BaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(23)
|
@Order(23)
|
||||||
public void getNotExistUserListByOrgSuccess() throws Exception {
|
public void getNotExistUserListByOrgSuccess() throws Exception {
|
||||||
|
@ -474,7 +474,6 @@ public class OrganizationControllerTests extends BaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void listByKeyWord(String keyWord, String orgId, boolean compare, String userRoleId, String projectId, boolean checkPart, String noUserRoleId, String noProjectId) throws Exception {
|
private void listByKeyWord(String keyWord, String orgId, boolean compare, String userRoleId, String projectId, boolean checkPart, String noUserRoleId, String noProjectId) throws Exception {
|
||||||
OrganizationRequest organizationRequest = new OrganizationRequest();
|
OrganizationRequest organizationRequest = new OrganizationRequest();
|
||||||
organizationRequest.setCurrent(1);
|
organizationRequest.setCurrent(1);
|
||||||
|
|
|
@ -145,8 +145,8 @@ public class SystemOrganizationControllerTests extends BaseTest{
|
||||||
request.setUserIds(List.of("user-id1"));
|
request.setUserIds(List.of("user-id1"));
|
||||||
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isOk());
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isOk());
|
||||||
request.setUserIds(List.of());
|
request.setUserIds(List.of());
|
||||||
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isOk());
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isBadRequest());
|
||||||
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isOk());
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -154,12 +154,15 @@ public class SystemOrganizationControllerTests extends BaseTest{
|
||||||
public void testUpdateOrganizationError() throws Exception {
|
public void testUpdateOrganizationError() throws Exception {
|
||||||
OrganizationEditRequest request = new OrganizationEditRequest();
|
OrganizationEditRequest request = new OrganizationEditRequest();
|
||||||
request.setName("default-4");
|
request.setName("default-4");
|
||||||
|
request.setUserIds(List.of("user-id1", "user-id2"));
|
||||||
// 组织不存在
|
// 组织不存在
|
||||||
request.setId("default-organization-x");
|
request.setId("default-organization-x");
|
||||||
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().is5xxServerError());
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().is5xxServerError());
|
||||||
// 组织存在, 但是名称重复
|
// 组织存在, 但是名称重复
|
||||||
request.setId("default-organization-5");
|
request.setId("default-organization-5");
|
||||||
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().is5xxServerError());
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().is5xxServerError());
|
||||||
|
request.setUserIds(new ArrayList<>());
|
||||||
|
this.requestPost(ORGANIZATION_UPDATE, request).andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -381,6 +384,8 @@ public class SystemOrganizationControllerTests extends BaseTest{
|
||||||
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/default-organization-3/admin", status().isOk());
|
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/default-organization-3/admin", status().isOk());
|
||||||
// 日志校验
|
// 日志校验
|
||||||
checkLog("default-organization-3", OperationLogType.DELETE);
|
checkLog("default-organization-3", OperationLogType.DELETE);
|
||||||
|
|
||||||
|
this.requestGet(ORGANIZATION_REMOVE_MEMBER + "/default-organization-5/user-id1", status().is5xxServerError());
|
||||||
// 权限校验
|
// 权限校验
|
||||||
requestGetPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_MEMBER_DELETE, ORGANIZATION_REMOVE_MEMBER + "/default-organization-3/admin");
|
requestGetPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_MEMBER_DELETE, ORGANIZATION_REMOVE_MEMBER + "/default-organization-3/admin");
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,4 +50,9 @@ INSERT INTO user_role(id, name, description, internal, type, create_time, update
|
||||||
|
|
||||||
INSERT INTO user_role_relation(id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUE
|
INSERT INTO user_role_relation(id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUE
|
||||||
('gyq_user_role_relation_test', 'sys_default_user4', 'sys_default_org_role_id_5', 'sys_default_organization_6', 'sys_default_organization_6', UNIX_TIMESTAMP() * 1000, 'admin');
|
('gyq_user_role_relation_test', 'sys_default_user4', 'sys_default_org_role_id_5', 'sys_default_organization_6', 'sys_default_organization_6', UNIX_TIMESTAMP() * 1000, 'admin');
|
||||||
|
INSERT INTO user_role_relation(id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUE
|
||||||
|
('gyq_user_role_relation_test-1', 'sys_default_user', 'org_admin', 'sys_default_organization_6', 'sys_default_organization_6', UNIX_TIMESTAMP() * 1000, 'admin');
|
||||||
|
INSERT INTO user_role_relation(id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUE
|
||||||
|
('gyq_user_role_relation_test-2', 'admin', 'org_admin', 'sys_default_organization_3', 'sys_default_organization_3', UNIX_TIMESTAMP() * 1000, 'admin');
|
||||||
|
INSERT INTO user_role_relation(id, user_id, role_id, source_id, organization_id, create_time, create_user) VALUE
|
||||||
|
('gyq_user_role_relation_test-3', 'sys_default_user4', 'sys_default_project_role_id_3', 'sys_org_projectId', 'sys_default_organization_3', UNIX_TIMESTAMP() * 1000, 'admin');
|
Loading…
Reference in New Issue