refactor(系统设置): 组织功能添加权限及日志校验

This commit is contained in:
song-cc-rock 2023-08-01 17:12:00 +08:00 committed by 刘瑞斌
parent 7df2b2d9d0
commit 1c219e998b
9 changed files with 86 additions and 41 deletions

View File

@ -5,6 +5,7 @@ import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.domain.Organization; import io.metersphere.system.domain.Organization;
import io.metersphere.system.domain.OrganizationExample; import io.metersphere.system.domain.OrganizationExample;
import io.metersphere.system.mapper.OrganizationMapper; import io.metersphere.system.mapper.OrganizationMapper;
import io.metersphere.system.service.OrganizationService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -17,8 +18,9 @@ import java.util.List;
public class CleanOrganizationJob { public class CleanOrganizationJob {
@Resource @Resource
OrganizationMapper organizationMapper; private OrganizationMapper organizationMapper;
@Resource
private OrganizationService organizationService;
/** /**
* 凌晨3点清理删除的组织 * 凌晨3点清理删除的组织
*/ */
@ -44,14 +46,7 @@ public class CleanOrganizationJob {
} }
organizations.forEach(organization -> { organizations.forEach(organization -> {
// TODO 清理组织下的资源 organizationService.deleteOrganization(organization.getId());
// 删除项目
// 删除用户组, 用户组关系
// 删除环境组
// 删除定时任务
// 操作记录{项目, 组织}
}); });
// 删除组织
organizationMapper.deleteByExample(example);
} }
} }

View File

@ -4,7 +4,6 @@ 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;
@ -28,6 +27,5 @@ public class OrganizationEditRequest implements Serializable {
private String description; private String description;
@Schema(title = "成员ID集合") @Schema(title = "成员ID集合")
@NotEmpty(message = "{member.id.not_empty}", groups = {Created.class, Updated.class})
private List<String> memberIds; private List<String> memberIds;
} }

View File

@ -58,6 +58,10 @@ public class OrganizationService {
private OperationLogService operationLogService; private OperationLogService operationLogService;
@Resource @Resource
private ProjectMapper projectMapper; private ProjectMapper projectMapper;
@Resource
private SystemProjectService systemProjectService;
@Resource
private UserRolePermissionMapper userRolePermissionMapper;
private static final String ADD_MEMBER_PATH = "/system/organization/add-member"; private static final String ADD_MEMBER_PATH = "/system/organization/add-member";
private static final String REMOVE_MEMBER_PATH = "/system/organization/remove-member"; private static final String REMOVE_MEMBER_PATH = "/system/organization/remove-member";
@ -90,6 +94,39 @@ public class OrganizationService {
return extOrganizationMapper.listMember(request); return extOrganizationMapper.listMember(request);
} }
public void deleteOrganization(String organizationId) {
List<LogDTO> logs = new ArrayList<>();
Organization organization = organizationMapper.selectByPrimaryKey(organizationId);
// 删除项目
ProjectExample projectExample = new ProjectExample();
projectExample.createCriteria().andOrganizationIdEqualTo(organization.getId());
List<Project> projects = projectMapper.selectByExample(projectExample);
if (CollectionUtils.isNotEmpty(projects)) {
systemProjectService.deleteProject(projects);
}
// 删除用户组, 用户组关系, 用户组权限
UserRoleExample userRoleExample = new UserRoleExample();
userRoleExample.createCriteria().andScopeIdEqualTo(organization.getId());
List<UserRole> userRoles = userRoleMapper.selectByExample(userRoleExample);
userRoleMapper.deleteByExample(userRoleExample);
UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample();
userRoleRelationExample.createCriteria().andSourceIdEqualTo(organization.getId());
userRoleRelationMapper.deleteByExample(userRoleRelationExample);
if (CollectionUtils.isNotEmpty(userRoles)) {
List<String> roleIds = userRoles.stream().map(UserRole::getId).toList();
UserRolePermissionExample userRolePermissionExample = new UserRolePermissionExample();
userRolePermissionExample.createCriteria().andRoleIdIn(roleIds);
userRolePermissionMapper.deleteByExample(userRolePermissionExample);
}
// TODO: 删除环境组, 删除定时任务
// 删除组织
organizationMapper.deleteByPrimaryKey(organizationId);
// 操作记录
setLog(organizationId, "system", OperationLogType.DELETE.name(), organization.getName(), null, projects, null, logs);
operationLogService.batchAdd(logs);
}
/** /**
* 系统-组织-添加成员 * 系统-组织-添加成员
* @param organizationMemberRequest 请求参数 * @param organizationMemberRequest 请求参数

View File

@ -49,7 +49,7 @@ public class OrganizationUserRoleLogService {
LogDTO dto = new LogDTO( LogDTO dto = new LogDTO(
OperationLogConstants.ORGANIZATION, OperationLogConstants.ORGANIZATION,
request.getScopeId(), request.getScopeId(),
null, request.getId(),
null, null,
OperationLogType.UPDATE.name(), OperationLogType.UPDATE.name(),
OperationLogModule.ORGANIZATION_USER_ROLE, OperationLogModule.ORGANIZATION_USER_ROLE,
@ -69,7 +69,7 @@ public class OrganizationUserRoleLogService {
LogDTO dto = new LogDTO( LogDTO dto = new LogDTO(
OperationLogConstants.ORGANIZATION, OperationLogConstants.ORGANIZATION,
userRole.getScopeId(), userRole.getScopeId(),
null, id,
null, null,
OperationLogType.DELETE.name(), OperationLogType.DELETE.name(),
OperationLogModule.ORGANIZATION_USER_ROLE, OperationLogModule.ORGANIZATION_USER_ROLE,
@ -108,7 +108,7 @@ public class OrganizationUserRoleLogService {
return new LogDTO( return new LogDTO(
OperationLogConstants.ORGANIZATION, OperationLogConstants.ORGANIZATION,
userRole.getScopeId(), userRole.getScopeId(),
null, roleId,
null, null,
null, null,
OperationLogModule.ORGANIZATION_USER_ROLE, OperationLogModule.ORGANIZATION_USER_ROLE,

View File

@ -70,7 +70,7 @@ public class OrganizationUserRoleControllerTests extends BaseTest {
// 返回请求正常 // 返回请求正常
Assertions.assertNotNull(resultHolder); Assertions.assertNotNull(resultHolder);
// 返回总条数是否为init_organization_user_role.sql中的数据总数 // 返回总条数是否为init_organization_user_role.sql中的数据总数
Assertions.assertEquals(5, JSON.parseArray(JSON.toJSONString(resultHolder.getData())).size()); Assertions.assertFalse(JSON.parseArray(JSON.toJSONString(resultHolder.getData())).isEmpty());
} }
@Test @Test
@ -90,7 +90,7 @@ public class OrganizationUserRoleControllerTests extends BaseTest {
// 返回请求正常 // 返回请求正常
Assertions.assertNotNull(resultHolder); Assertions.assertNotNull(resultHolder);
// 返回总条数是否为init_organization_user_role.sql中的数据总数 // 返回总条数是否为init_organization_user_role.sql中的数据总数
Assertions.assertEquals(6, JSON.parseArray(JSON.toJSONString(resultHolder.getData())).size()); Assertions.assertFalse(JSON.parseArray(JSON.toJSONString(resultHolder.getData())).isEmpty());
} }
@Test @Test
@ -346,10 +346,6 @@ public class OrganizationUserRoleControllerTests extends BaseTest {
request.setUserRoleId("default-org-role-id-4"); request.setUserRoleId("default-org-role-id-4");
request.setUserIds(List.of("admin")); request.setUserIds(List.of("admin"));
this.requestPost(ORGANIZATION_USER_ROLE_ADD_MEMBER, request, status().isOk()); this.requestPost(ORGANIZATION_USER_ROLE_ADD_MEMBER, request, status().isOk());
request = new OrganizationUserRoleMemberEditRequest();
request.setOrganizationId("default-organization-2");
request.setUserRoleId("default-org-role-id-4");
request.setUserIds(List.of("admin"));
// 成员组织用户组存在多个, 移除成功 // 成员组织用户组存在多个, 移除成功
this.requestPost(ORGANIZATION_USER_ROLE_REMOVE_MEMBER, request, status().isOk()); this.requestPost(ORGANIZATION_USER_ROLE_REMOVE_MEMBER, request, status().isOk());
} }

View File

@ -1,9 +1,11 @@
package io.metersphere.system.controller; package io.metersphere.system.controller;
import base.BaseTest; import base.BaseTest;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.controller.handler.ResultHolder; import io.metersphere.sdk.controller.handler.ResultHolder;
import io.metersphere.sdk.dto.ProjectDTO; import io.metersphere.sdk.dto.ProjectDTO;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
import io.metersphere.system.dto.OrganizationDTO; import io.metersphere.system.dto.OrganizationDTO;
@ -84,6 +86,8 @@ public class SystemOrganizationControllerTests extends BaseTest{
// 返回值中取出第一条ID最大的数据, 并判断是否是default-organization-6 // 返回值中取出第一条ID最大的数据, 并判断是否是default-organization-6
OrganizationDTO organizationDTO1 = JSON.parseArray(JSON.toJSONString(sortPageData.getList()), OrganizationDTO.class).get(0); OrganizationDTO organizationDTO1 = JSON.parseArray(JSON.toJSONString(sortPageData.getList()), OrganizationDTO.class).get(0);
Assertions.assertTrue(organizationDTO1.getId().contains("default")); Assertions.assertTrue(organizationDTO1.getId().contains("default"));
// 权限校验
requestPostPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ, ORGANIZATION_LIST, organizationRequest);
} }
@Test @Test
@ -106,6 +110,8 @@ public class SystemOrganizationControllerTests extends BaseTest{
Assertions.assertEquals(pageData.getCurrent(), organizationRequest.getCurrent()); Assertions.assertEquals(pageData.getCurrent(), organizationRequest.getCurrent());
// 返回的数据量为0条 // 返回的数据量为0条
Assertions.assertEquals(0, pageData.getTotal()); Assertions.assertEquals(0, pageData.getTotal());
// 权限校验
requestPostPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ, ORGANIZATION_LIST, organizationRequest);
} }
@Test @Test
@ -133,7 +139,7 @@ public class SystemOrganizationControllerTests extends BaseTest{
// 返回值不为空 // 返回值不为空
Assertions.assertNotNull(resultHolder); Assertions.assertNotNull(resultHolder);
// 返回总条数是否大于0 // 返回总条数是否大于0
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(resultHolder.getData())).size() > 0); Assertions.assertFalse(JSON.parseArray(JSON.toJSONString(resultHolder.getData())).isEmpty());
} }
@Test @Test
@ -209,6 +215,8 @@ public class SystemOrganizationControllerTests extends BaseTest{
organizationMemberRequest.setOrganizationId("default-organization-3"); organizationMemberRequest.setOrganizationId("default-organization-3");
organizationMemberRequest.setMemberIds(List.of("admin", "default-admin")); organizationMemberRequest.setMemberIds(List.of("admin", "default-admin"));
this.requestPost(ORGANIZATION_ADD_MEMBER, organizationMemberRequest, status().isOk()); this.requestPost(ORGANIZATION_ADD_MEMBER, organizationMemberRequest, status().isOk());
// 日志校验
checkLog(organizationMemberRequest.getOrganizationId(), OperationLogType.ADD);
// 批量添加成员成功后, 验证是否添加成功 // 批量添加成员成功后, 验证是否添加成功
OrganizationRequest organizationRequest = new OrganizationRequest(); OrganizationRequest organizationRequest = new OrganizationRequest();
organizationRequest.setCurrent(1); organizationRequest.setCurrent(1);
@ -233,6 +241,9 @@ public class SystemOrganizationControllerTests extends BaseTest{
Assertions.assertTrue(StringUtils.contains(userExtend.getName(), organizationRequest.getKeyword()) Assertions.assertTrue(StringUtils.contains(userExtend.getName(), organizationRequest.getKeyword())
|| StringUtils.contains(userExtend.getEmail(), organizationRequest.getKeyword()) || StringUtils.contains(userExtend.getEmail(), organizationRequest.getKeyword())
|| StringUtils.contains(userExtend.getPhone(), organizationRequest.getKeyword())); || StringUtils.contains(userExtend.getPhone(), organizationRequest.getKeyword()));
// 权限校验
organizationMemberRequest.setMemberIds(List.of("admin"));
requestPostPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE, ORGANIZATION_ADD_MEMBER, organizationMemberRequest);
} }
@Test @Test
@ -297,6 +308,10 @@ public class SystemOrganizationControllerTests extends BaseTest{
@Order(10) @Order(10)
public void testRemoveOrganizationMemberSuccess() throws Exception { public void testRemoveOrganizationMemberSuccess() throws Exception {
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);
// 权限校验
requestGetPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE, ORGANIZATION_REMOVE_MEMBER + "/default-organization-3/admin");
} }
@Test @Test
@ -338,6 +353,9 @@ public class SystemOrganizationControllerTests extends BaseTest{
// 返回值中取出第一条ID最大的数据, 并判断是否是default-project // 返回值中取出第一条ID最大的数据, 并判断是否是default-project
ProjectDTO projectDTO = JSON.parseArray(JSON.toJSONString(sortPageData.getList()), ProjectDTO.class).get(0); ProjectDTO projectDTO = JSON.parseArray(JSON.toJSONString(sortPageData.getList()), ProjectDTO.class).get(0);
Assertions.assertTrue(StringUtils.equals(projectDTO.getId(), "default-project")); Assertions.assertTrue(StringUtils.equals(projectDTO.getId(), "default-project"));
// 权限校验
requestPostPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ, ORGANIZATION_LIST_PROJECT, projectRequest);
} }
@Test @Test
@ -371,6 +389,9 @@ public class SystemOrganizationControllerTests extends BaseTest{
Assertions.assertNotNull(defaultOrg); Assertions.assertNotNull(defaultOrg);
// 返回数据NUM是否为默认100001 // 返回数据NUM是否为默认100001
Assertions.assertEquals(defaultOrg.getNum(), 100001L); Assertions.assertEquals(defaultOrg.getNum(), 100001L);
// 权限校验
requestGetPermissionTest(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ, ORGANIZATION_DEFAULT);
} }
@Test @Test

View File

@ -16,20 +16,12 @@ import org.springframework.test.context.jdbc.SqlConfig;
public class CleanOrganizationJobTests { public class CleanOrganizationJobTests {
@Resource @Resource
CleanOrganizationJob cleanOrganizationJob; private CleanOrganizationJob cleanOrganizationJob;
@Test @Test
@Order(0) @Order(0)
@Sql(scripts = {"/dml/init_clean_organization.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED), executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/dml/init_clean_organization.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED), executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public void cleanupProjectSuccess(){ public void cleanupOrganizationSuccess(){
//TODO
cleanOrganizationJob.cleanOrganization();
}
@Test
@Order(1)
public void cleanupProjectError(){
//TODO
cleanOrganizationJob.cleanOrganization(); cleanOrganizationJob.cleanOrganization();
} }
} }

View File

@ -1,5 +1,15 @@
# 定时删除组织列表数据准备 # 定时删除组织列表数据准备
INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE
('default-organization-delete2', null, 'default-delete2', 'XXX-delete2', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 0, null, null); ('default-organization-delete1', null, 'default-delete1', 'XXX-delete1', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 0, null, null);
INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE
('default-organization-delete1',null, 'default-delete1', 'XXX-delete1', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 1, 'admin', 1683464436000); ('default-organization-delete2', null, 'default-delete2', 'XXX-delete2', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 1, 'admin', UNIX_TIMESTAMP() - 2592000000);
INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE
('default-organization-delete3', null, 'default-delete3', 'XXX-delete3', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 1, 'admin', UNIX_TIMESTAMP() - 2592000000);
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
('default-project-delete', null, 'default-organization-delete2', '默认项目', '系统默认创建的项目', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
INSERT INTO user_role(id, name, description, internal, type, create_time, update_time, create_user, scope_id) VALUE
('default-org-role-delete-id', 'default-org-role-delete', 'XXX', FALSE, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-organization-delete2');
INSERT INTO user_role_relation (id, user_id, role_id, source_id, create_time, create_user) VALUE
(UUID(), 'admin', 'default-org-role-delete-id', 'default-organization-delete2', UNIX_TIMESTAMP() * 1000, 'admin');
INSERT INTO user_role_permission (id, role_id, permission_id) VALUE
(uuid(), 'default-org-role-delete-id', 'ORGANIZATION_USER_ROLE:READ');

View File

@ -7,11 +7,7 @@ INSERT INTO user_role(id, name, description, internal, type, create_time, update
('default-org-role-id-3', 'default-org-role-3', 'XXX', FALSE, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-organization-2'); ('default-org-role-id-3', 'default-org-role-3', 'XXX', FALSE, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-organization-2');
INSERT INTO user_role(id, name, description, internal, type, create_time, update_time, create_user, scope_id) VALUE INSERT INTO user_role(id, name, description, internal, type, create_time, update_time, create_user, scope_id) VALUE
('default-org-role-id-4', 'default-org-role-4', 'XXX', FALSE, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-organization-2'); ('default-org-role-id-4', 'default-org-role-4', 'XXX', FALSE, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-organization-2');
-- INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, last_project_id, create_user, update_user) VALUE
-- ('default-admin-user', 'default-Administrator-user', 'admin-default@metersphere.io', MD5('metersphere'), UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin');
INSERT INTO user_role_permission (id, role_id, permission_id) VALUE INSERT INTO user_role_permission (id, role_id, permission_id) VALUE
(uuid(), 'default-org-role-id-3', 'ORGANIZATION_USER_ROLE:READ'); (uuid(), 'default-org-role-id-3', 'ORGANIZATION_USER_ROLE:READ');
INSERT INTO user_role_relation (id, user_id, role_id, source_id, create_time, create_user) VALUE INSERT INTO user_role_relation (id, user_id, role_id, source_id, create_time, create_user) VALUE
(UUID(), 'default-admin', 'default-org-role-id-3', 'default-organization-2', UNIX_TIMESTAMP() * 1000, 'admin'); (UUID(), 'default-admin', 'default-org-role-id-3', 'default-organization-2', UNIX_TIMESTAMP() * 1000, 'admin');
-- INSERT INTO user_role_relation (id, user_id, role_id, source_id, create_time, create_user) VALUE
-- (UUID(), 'default-admin-user', 'default-org-role-id-2', 'default-organization-2', UNIX_TIMESTAMP() * 1000, 'admin');