refactor(系统设置): 用户组接口添加参数校验和日志校验

--story=1012250 --user=陈建星 系统设置-用户组管理 https://www.tapd.cn/55049933/s/1390501
This commit is contained in:
jianxing 2023-07-07 19:29:11 +08:00 committed by jianxing
parent bd19642df8
commit 67bf1bc381
36 changed files with 896 additions and 167 deletions

View File

@ -7,7 +7,13 @@ package io.metersphere.sdk.controller.handler.result;
*/
public enum CommonResultCode implements IResultCode {
PLUGIN_GET_INSTANCE(100001, "get_plugin_instance_error");
PLUGIN_GET_INSTANCE(100001, "get_plugin_instance_error"),
USER_ROLE_RELATION_EXIST(100002, "user_role_relation_exist_error"),
/**
* 调用获取全局用户组接口如果操作的是内置的用户组会返回该响应码
*/
INTERNAL_USER_ROLE_PERMISSION(101003, "internal_user_role_permission_error"),
USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION(100004, "user_role_relation_remove_admin_user_permission_error");
private int code;
private String message;

View File

@ -1,6 +1,7 @@
package io.metersphere.sdk.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@ -17,6 +18,7 @@ public class PermissionSettingUpdateRequest {
private String userRoleId;
@NotNull
@Schema(title = "菜单下的权限列表", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
private List<PermissionUpdateRequest> permissions;
@Data

View File

@ -37,7 +37,7 @@ public @interface Log {
/**
* 资源ID
*/
String sourceId() default "NONE";
String sourceId() default "";
/**
* 创建用户

View File

@ -75,4 +75,10 @@ public class BaseUserRolePermissionService {
}
});
}
public void deleteByRoleId(String roleId) {
UserRolePermissionExample example = new UserRolePermissionExample();
example.createCriteria().andRoleIdEqualTo(roleId);
userRolePermissionMapper.deleteByExample(example);
}
}

View File

@ -0,0 +1,101 @@
package io.metersphere.sdk.service;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.domain.UserRoleRelationExample;
import io.metersphere.system.mapper.UserRoleRelationMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.UUID;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.*;
/**
* @author jianxing
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseUserRoleRelationService {
@Resource
protected UserRoleRelationMapper userRoleRelationMapper;
@Resource
@Lazy
protected BaseUserRoleService baseUserRoleService;
protected UserRoleRelation add(UserRoleRelation userRoleRelation) {
checkExist(userRoleRelation);
userRoleRelation.setCreateTime(System.currentTimeMillis());
userRoleRelation.setId(UUID.randomUUID().toString());
userRoleRelationMapper.insert(userRoleRelation);
return userRoleRelation;
}
/**
* 校验用户是否已在当前用户组
*/
public void checkExist(UserRoleRelation userRoleRelation) {
UserRoleRelationExample example = new UserRoleRelationExample();
example.createCriteria()
.andUserIdEqualTo(userRoleRelation.getUserId())
.andRoleIdEqualTo(userRoleRelation.getRoleId());
List<UserRoleRelation> userRoleRelations = userRoleRelationMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(userRoleRelations)) {
throw new MSException(USER_ROLE_RELATION_EXIST);
}
}
public UserRole getUserRole(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
return baseUserRoleService.get(userRoleRelation.getRoleId());
}
protected void delete(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
checkAdminPermissionRemove(userRoleRelation.getUserId(), userRoleRelation.getRoleId());
userRoleRelationMapper.deleteByPrimaryKey(id);
}
public void deleteByRoleId(String roleId) {
List<UserRoleRelation> userRoleRelations = getByRoleId(roleId);
userRoleRelations.forEach(userRoleRelation ->
checkAdminPermissionRemove(userRoleRelation.getUserId(), userRoleRelation.getRoleId()));
UserRoleRelationExample example = new UserRoleRelationExample();
example.createCriteria().andRoleIdEqualTo(roleId);
userRoleRelationMapper.deleteByExample(example);
}
public List<UserRoleRelation> getByRoleId(String roleId) {
UserRoleRelationExample example = new UserRoleRelationExample();
example.createCriteria().andRoleIdEqualTo(roleId);
return userRoleRelationMapper.selectByExample(example);
}
/**
* admin 不能从系统管理员用户组删除
*/
private static void checkAdminPermissionRemove(String userId, String roleId) {
if (StringUtils.equals(roleId, ADMIN.getValue()) && StringUtils.equals(userId, ADMIN.getValue())) {
throw new MSException(USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION);
}
}
public String getLogDetails(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
if (userRoleRelation != null) {
UserRole userRole = baseUserRoleService.get(userRoleRelation.getRoleId());
return userRole == null ? null : userRole.getName();
}
return null;
}
}

View File

@ -3,11 +3,13 @@ package io.metersphere.sdk.service;
import io.metersphere.sdk.dto.Permission;
import io.metersphere.sdk.dto.PermissionDefinitionItem;
import io.metersphere.sdk.dto.request.PermissionSettingUpdateRequest;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.PermissionCache;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.mapper.UserRoleMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -16,6 +18,8 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.INTERNAL_USER_ROLE_PERMISSION;
/**
* @author jianxing
*/
@ -29,6 +33,8 @@ public class BaseUserRoleService {
private UserRoleMapper userRoleMapper;
@Resource
private BaseUserRolePermissionService baseUserRolePermissionService;
@Resource
private BaseUserRoleRelationService baseUserRoleRelationService;
/**
* 根据用户组获取对应的权限配置项
@ -100,4 +106,34 @@ public class BaseUserRoleService {
userRoleMapper.updateByPrimaryKeySelective(userRole);
return userRole;
}
/**
* 删除用户组并且删除用户组与用户的关联关系用户组与权限的关联关系
* @param userRole
*/
public void delete(UserRole userRole) {
String id = userRole.getId();
checkInternalUserRole(userRole);
baseUserRolePermissionService.deleteByRoleId(id);
baseUserRoleRelationService.deleteByRoleId(id);
userRoleMapper.deleteByPrimaryKey(id);
}
/**
* 校验是否是内置用户组是内置抛异常
*/
public void checkInternalUserRole(UserRole userRole) {
if (BooleanUtils.isTrue(userRole.getInternal())) {
throw new MSException(INTERNAL_USER_ROLE_PERMISSION);
}
}
public UserRole get(String id) {
return userRoleMapper.selectByPrimaryKey(id);
}
public String getLogDetails(String id) {
UserRole userRole = userRoleMapper.selectByPrimaryKey(id);
return userRole == null ? null : userRole.getName();
}
}

View File

@ -388,6 +388,10 @@ source_bug_template_is_empty=Copy error, source project is empty
#plugin
get_plugin_instance_error=Get the plugin instance error!
# userRole
user_role_relation_exist_error=The user is already in the current user group
internal_user_role_permission_error=Internal user groups cannot be edited or deleted
user_role_relation_remove_admin_user_permission_error=Unable to delete the admin user from the system administrator user group
#result message
http_result_success=operate success

View File

@ -387,6 +387,10 @@ source_bug_template_is_empty=复制错误,源项目为空
#plugin
get_plugin_instance_error=获取插件接口实现类错误!
# userRole
user_role_relation_exist_error=用户已在当前用户组!
internal_user_role_permission_error=内置用户组无法编辑与删除!
user_role_relation_remove_admin_user_permission_error=无法将 admin 用户将系统管理员用户组删除!
#result message
http_result_success=操作成功

View File

@ -385,6 +385,10 @@ source_bug_template_is_empty=複製錯誤,源項目為空
#plugin
get_plugin_instance_error=獲取插件接口實現類錯誤!
# userRole
user_role_relation_exist_error=用戶已在當前用戶組!
internal_user_role_permission_error=內置用戶組無法編輯與刪除!
user_role_relation_remove_admin_user_permission_error=無法將 admin 用戶將系統管理員用戶組刪除!
#result message
http_result_success=操作成功

View File

@ -153,4 +153,9 @@ organization.create_user.length_range=工作空间创建人长度必须在{min}
and_add_organization_admin=并添加组织管理员
organization_add_member_ids_empty=组织添加成员不能为空
organization_not_exist=组织不存在
organization_member_not_exist=组织成员不存在
organization_member_not_exist=组织成员不存在
# userRole
global_user_role_permission_error=没有权限操作非全局用户组
global_user_role_exist_error=全局用户组已存在
global_user_role_relation_system_permission_error=没有权限操作非系统级别用户组

View File

@ -1,13 +1,20 @@
package base;
import base.param.InvalidateParamInfo;
import base.param.ParamGeneratorFactory;
import com.jayway.jsonpath.JsonPath;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.controller.handler.result.IResultCode;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Pager;
import io.metersphere.system.domain.OperationLogExample;
import io.metersphere.system.mapper.OperationLogMapper;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestMethodOrder;
@ -23,8 +30,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.List;
import java.util.Map;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
@ -77,8 +83,8 @@ public abstract class BaseTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
protected MvcResult requestPostAndReturn(String url, Object... uriVariables) throws Exception {
return this.requestPost(url, uriVariables).andReturn();
protected MvcResult requestPostAndReturn(String url, Object param, Object... uriVariables) throws Exception {
return this.requestPost(url, param, uriVariables).andReturn();
}
protected ResultActions requestGet(String url, Object... uriVariables) throws Exception {
@ -120,6 +126,17 @@ public abstract class BaseTest {
return JSON.parseArray(JSON.toJSONString(data), clazz);
}
/**
* 校验错误响应码
*/
protected void assertErrorCode(ResultActions resultActions, IResultCode resultCode) throws Exception {
resultActions
.andExpect(
jsonPath("$.code")
.value(resultCode.getCode())
);
}
protected <T> Pager<List<T>> getPageResult(MvcResult mvcResult, Class<T> clazz) throws Exception {
Map<String, Object> pagerResult = (Map<String, Object>) JSON.parseMap(mvcResult.getResponse().getContentAsString()).get("data");
List<T> list = JSON.parseArray(JSON.toJSONString(pagerResult.get("list")), clazz);
@ -131,15 +148,64 @@ public abstract class BaseTest {
return pager;
}
protected void checkLog(String resourceId, String type) throws Exception {
protected void checkLog(String resourceId, OperationLogType operationLogType) throws Exception {
OperationLogExample example = new OperationLogExample();
example.createCriteria().andSourceIdEqualTo(resourceId).andTypeEqualTo(type);
example.createCriteria().andSourceIdEqualTo(resourceId).andTypeEqualTo(operationLogType.name());
operationLogMapper.selectByExample(example).stream()
.filter(operationLog -> operationLog.getSourceId().equals(resourceId))
.filter(operationLog -> operationLog.getType().equals(type))
.filter(operationLog -> operationLog.getType().equals(operationLogType.name()))
.filter(operationLog -> StringUtils.isNotBlank(operationLog.getProjectId()))
.filter(operationLog -> StringUtils.isNotBlank(operationLog.getModule()))
.findFirst()
.orElseThrow(() -> new Exception("日志不存在,请补充操作日志"));
}
/**
* Created 分组参数校验
*/
protected <T> void createdGroupParamValidateTest(Class<T> clazz, String path) throws Exception {
paramValidateTest(Created.class, clazz, path);
}
/**
* Updated 分组参数校验
*/
protected <T> void updatedGroupParamValidateTest(Class<T> clazz, String path) throws Exception {
paramValidateTest(Updated.class, clazz, path);
}
/**
* 没有分组的参数校验
*/
protected <T> void paramValidateTest(Class<T> clazz, String path) throws Exception {
paramValidateTest(null, clazz, path);
}
/**
* 根据指定的参数定义自动生成异常参数进行参数校验的测试
*
* @param group 分组
* @param clazz 参数类名
* @param path 请求路径
* @param <T> 参数类型
* @throws Exception
*/
private <T> void paramValidateTest(Class group, Class<T> clazz, String path) throws Exception {
System.out.println("paramValidateTest-start: ====================================");
System.out.println("url: " + getBasePath() + path);
List<InvalidateParamInfo> invalidateParamInfos = ParamGeneratorFactory.generateInvalidateParams(group, clazz);
for (InvalidateParamInfo invalidateParamInfo : invalidateParamInfos) {
System.out.println("valid: " + invalidateParamInfo.getName() + " " + invalidateParamInfo.getAnnotation().getSimpleName());
System.out.println("param: " + JSON.toJSONString(invalidateParamInfo.getValue()));
MvcResult mvcResult = this.requestPostAndReturn(path, invalidateParamInfo.getValue());
// 校验错误是否是参数错误
Assertions.assertEquals(400, mvcResult.getResponse().getStatus());
Map resultData = getResultData(mvcResult, Map.class);
System.out.println("result: " + resultData);
// 校验错误信息中包含了该字段
Assertions.assertTrue(resultData.containsKey(invalidateParamInfo.getName()));
}
System.out.println("paramValidateTest-end: ====================================");
}
}

View File

@ -0,0 +1,18 @@
package base.param;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class EmailParamGenerator extends ParamGenerator {
/**
* 返回非邮件格式的字符串
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
return "111111111";
}
}

View File

@ -0,0 +1,40 @@
package base.param;
import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.sdk.valid.EnumValue;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class EnumValueParamGenerator extends ParamGenerator {
/**
* 生成一个不在枚举值中的数值
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
EnumValue enumValue = (EnumValue) annotation;
Class<? extends Enum> enumClass = enumValue.enumClass();
String[] excludeValues = enumValue.excludeValues();
// 获取枚举的所有实例
Enum<? extends Enum>[] enums = enumClass.getEnumConstants();
boolean isStr = true;
if (enums[0] instanceof ValueEnum) {
Object value = ((ValueEnum<?>) enums[0]).getValue();
// 获取枚举值判断是否是字符串类型
if (value != null && !(value instanceof String)) {
isStr = false;
}
}
// 如果有排除值则返回排除值
if (excludeValues != null && excludeValues.length > 0) {
return excludeValues[0];
}
// 这里伪生成一个不在枚举值中的数值仅支持字符串和整型
return isStr ? "1" : Integer.MAX_VALUE;
}
}

View File

@ -0,0 +1,16 @@
package base.param;
import lombok.Data;
@Data
public class InvalidateParamInfo {
private String name;
private Object value;
private Class annotation;
public InvalidateParamInfo(String name, Object value, Class annotation) {
this.name = name;
this.value = value;
this.annotation = annotation;
}
}

View File

@ -0,0 +1,24 @@
package base.param;
import jakarta.validation.constraints.Max;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class MaxParamGenerator extends ParamGenerator {
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
Max maxAnnotation = (Max) annotation;
if (isNumberType(field.getType())) {
return convertToNumberType(field.getType(), maxAnnotation.value() + 1);
} else {
// todo 做缓存优化
return RandomStringUtils.random((int) (maxAnnotation.value() + 1));
}
}
}

View File

@ -0,0 +1,27 @@
package base.param;
import jakarta.validation.constraints.Min;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class MinParamGenerator extends ParamGenerator {
/**
* 返回 null
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
Min minAnnotation = (Min) annotation;
if (isNumberType(field.getType())) {
return convertToNumberType(field.getType(), minAnnotation.value() - 1);
} else {
// todo 做缓存优化
return RandomStringUtils.random((int) (minAnnotation.value() - 1));
}
}
}

View File

@ -0,0 +1,20 @@
package base.param;
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class NotBlankParamGenerator extends ParamGenerator {
/**
* 生成空字符串
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
return StringUtils.EMPTY;
}
}

View File

@ -0,0 +1,18 @@
package base.param;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class NotNullParamGenerator extends ParamGenerator {
/**
* 返回 null
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
return null;
}
}

View File

@ -0,0 +1,75 @@
package base.param;
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 单元测试参数生成器
* @author jianxing
*/
public abstract class ParamGenerator {
/**
* 生成非法参数
* @param annotation 注解
* @param field 字段
* @return 非法参数
*/
public abstract Object invalidGenerate(Annotation annotation, Field field);
/**
* 通过反射获取注解上的分组信息判断是否匹配
* @param group 当前分组
* @param annotation 注解
* @return 是否匹配
*/
public boolean isGroupMatch(Class group, Annotation annotation) {
Method[] methods = annotation.getClass().getDeclaredMethods();
for (Method method : methods) {
if (StringUtils.equals(method.getName(), "groups")) {
try {
Class[] groups = (Class[]) method.invoke(annotation);
if (groups.length == 0) {
// 注解上没有分组如果当前分组为空则匹配否则不匹配
return group == null;
}
for (Class groupItem : groups) {
if (groupItem.equals(group)) {
// 有一个匹配成功则返回true
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return false;
}
protected boolean isNumberType(Class<?> clazz) {
return (clazz.isPrimitive() && clazz != boolean.class && clazz != char.class)
|| Number.class.isAssignableFrom(clazz);
}
protected <T> T convertToNumberType(Class<T> clazz, long value) {
if (clazz == int.class || clazz == Integer.class) {
return (T) Integer.valueOf((int) value);
} else if (clazz == long.class || clazz == Long.class) {
return (T) Long.valueOf(value);
} else if (clazz == short.class || clazz == Short.class) {
return (T) Short.valueOf((short) value);
} else if (clazz == byte.class || clazz == Byte.class) {
return (T) Byte.valueOf((byte) value);
} else if (clazz == float.class || clazz == Float.class) {
return (T) Float.valueOf((float) value);
} else if (clazz == double.class || clazz == Double.class) {
return (T) Double.valueOf((double) value);
} else {
throw new IllegalArgumentException("不支持的类型:" + clazz);
}
}
}

View File

@ -0,0 +1,128 @@
package base.param;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author jianxing
*/
public class ParamGeneratorFactory {
private static final Map<String, ParamGenerator> paramGeneratorMap = new HashMap<>() {{
put(Size.class.getName(), new SizeParamGenerator());
put(NotBlank.class.getName(), new NotBlankParamGenerator());
put(NotNull.class.getName(), new NotNullParamGenerator());
put(EnumValue.class.getName(), new EnumValueParamGenerator());
put(Min.class.getName(), new MinParamGenerator());
put(Max.class.getName(), new MaxParamGenerator());
put(Email.class.getName(), new EmailParamGenerator());
}};
public static ParamGenerator getParamGenerator(Annotation annotation) {
return paramGeneratorMap.get(annotation.annotationType().getName());
}
/**
* 根据指定的参数定义和分组自动生成异常参数列表
* @param group 接口分组
* @param clazz 参数类型
* @return 异常参数列表
* @param <T> 参数类型
* @throws Exception
*/
public static <T> List<InvalidateParamInfo> generateInvalidateParams(Class group, Class<T> clazz) throws Exception {
List<InvalidateParamInfo> paramList = new ArrayList();
// 通过反射获取当前类的所有属性
Field[] fields = clazz.getDeclaredFields();
// 遍历属性获取每个属性上的所有注解
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
// 遍历注解获取注解的类型
for (Annotation annotation : annotations) {
// 获取处理指定注解的生成器
ParamGenerator paramGenerator = getParamGenerator(annotation);
// 生成器不为空并且如果有指定 group 需要匹配 group
if (paramGenerator != null && paramGenerator.isGroupMatch(group, annotation)) {
T param = clazz.getConstructor().newInstance();
// 生成异常数据
Object invalidValue = paramGenerator.invalidGenerate(annotation, field);
// 将参数值赋为异常数据
getSetMethod(clazz, field).invoke(param, invalidValue);
InvalidateParamInfo invalidateParamInfo =
new InvalidateParamInfo(field.getName(), param, annotation.annotationType());
paramList.add(invalidateParamInfo);
}
// 如果是嵌套的校验注解需要递归处理
if (StringUtils.equalsAny(annotation.annotationType().getName(), Valid.class.getName(), Validated.class.getName())) {
Class<?> fieldClazz = Class.forName(field.getType().getName());
if (List.class.isAssignableFrom(fieldClazz)) {
// 如果是数组解析数组里的泛型
Class genericClazz = getaGenericClass(field, 0);
List<InvalidateParamInfo> genericParamList = generateInvalidateParams(group, genericClazz);
for (InvalidateParamInfo genericParam : genericParamList) {
List list = new ArrayList(1);
list.add(genericParam.getValue());
T param = clazz.getConstructor().newInstance();
getSetMethod(clazz, field).invoke(param, list);
InvalidateParamInfo invalidateParamInfo = new InvalidateParamInfo(field.getName() + "[0]" + "." + genericParam.getName(),
param, genericParam.getAnnotation());
paramList.add(invalidateParamInfo);
}
} else if (Map.class.isAssignableFrom(fieldClazz)) {
// 如果是 Map解析数组里的泛型
Class genericClazz = getaGenericClass(field, 1);
List<InvalidateParamInfo> genericParamList = generateInvalidateParams(group, genericClazz);
for (InvalidateParamInfo genericParam : genericParamList) {
Map map = new HashMap(1);
map.put("key", genericParam.getValue());
T param = clazz.getConstructor().newInstance();
getSetMethod(clazz, field).invoke(param, map);
InvalidateParamInfo invalidateParamInfo = new InvalidateParamInfo(field.getName() + "[key]" + "." + genericParam.getName(),
param, genericParam.getAnnotation());
paramList.add(invalidateParamInfo);
}
} else {
// 如果是对象解析对象里的泛型
List<InvalidateParamInfo> objParamList = generateInvalidateParams(group, field.getType());
for (InvalidateParamInfo objParam : objParamList) {
T newParam = clazz.getConstructor().newInstance();
BeanUtils.copyBean(newParam, newParam);
getSetMethod(clazz, field).invoke(newParam, objParam.getValue());
InvalidateParamInfo invalidateParamInfo = new InvalidateParamInfo(field.getName() + "." + objParam.getName(),
newParam, objParam.getAnnotation());
paramList.add(invalidateParamInfo);
}
}
}
}
}
return paramList;
}
private static Class getaGenericClass(Field field, int index) throws ClassNotFoundException {
Class genericClazz = Class.forName(
(
(Class) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[index]
).getName()
);
return genericClazz;
}
private static Method getSetMethod(Class clazz, Field field) throws Exception {
return clazz.getMethod("set" + StringUtils.capitalize(field.getName()), field.getType());
}
}

View File

@ -0,0 +1,28 @@
package base.param;
import jakarta.validation.constraints.Size;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author jianxing
*/
public class SizeParamGenerator extends ParamGenerator {
/**
* 生成超过指定长度的字符串
*/
@Override
public Object invalidGenerate(Annotation annotation, Field field) {
Size sizeAnnotation = (Size) annotation;
int max = sizeAnnotation.max();
if (isNumberType(field.getType())) {
return max + 1;
} else {
// todo 做缓存优化
return RandomStringUtils.random(max + 1);
}
}
}

View File

@ -51,7 +51,7 @@ public class GlobalUserRoleController {
@PostMapping("/permission/update")
@Operation(summary = "编辑全局用户组对应的权限配置")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE)
@Log(isBefore = true, type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE,
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE,
details = "#msClass.getLogDetails(#request.userRoleId)", msClass = GlobalUserRoleService.class)
public void updatePermissionSetting(@Validated @RequestBody PermissionSettingUpdateRequest request) {
globalUserRoleService.updatePermissionSetting(request);
@ -60,8 +60,7 @@ public class GlobalUserRoleController {
@PostMapping("/add")
@Operation(summary = "添加自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_ADD)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE,
sourceId = "#request.id", details = "#request.name")
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE, details = "#request.name")
public UserRole add(@Validated({Created.class}) @RequestBody UserRoleUpdateRequest request) {
UserRole userRole = new UserRole();
userRole.setCreateUser(SessionUtils.getUserId());
@ -72,7 +71,7 @@ public class GlobalUserRoleController {
@PostMapping("/update")
@Operation(summary = "更新自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE)
@Log(isBefore = true, type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE,
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE,
sourceId = "#request.id", details = "#request.name")
public UserRole update(@Validated({Updated.class}) @RequestBody UserRoleUpdateRequest request) {
UserRole userRole = new UserRole();
@ -84,7 +83,7 @@ public class GlobalUserRoleController {
@Operation(summary = "删除自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_DELETE)
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_USER_ROLE,
details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleService.class)
sourceId = "#id", details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleService.class)
public void delete(@PathVariable String id) {
globalUserRoleService.delete(id);
}

View File

@ -48,8 +48,7 @@ public class GlobalUserRoleRelationController {
@PostMapping("/add")
@Operation(summary = "创建全局用户组和用户的关联关系")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_ADD)
@Log(isBefore = true, type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE_RELATION,
details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleRelationService.class)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE_RELATION, details = "#request.name")
public UserRoleRelation add(@Validated({Created.class}) @RequestBody GlobalUserRoleRelationUpdateRequest request) {
UserRoleRelation userRoleRelation = new UserRoleRelation();
BeanUtils.copyBean(userRoleRelation, request);
@ -60,7 +59,7 @@ public class GlobalUserRoleRelationController {
@GetMapping("/delete/{id}")
@Operation(summary = "删除全局用户组和用户的关联关系")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_DELETE)
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_USER_ROLE_RELATION,
@Log(isBefore = true, type = OperationLogType.DELETE, sourceId = "#id", module = OperationLogModule.SYSTEM_USER_ROLE_RELATION,
details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleRelationService.class)
public void delete(@PathVariable String id) {
globalUserRoleRelationService.delete(id);

View File

@ -10,15 +10,9 @@ public enum SystemResultCode implements IResultCode {
/**
* 调用获取全局用户组接口如果操作的是非全局的用户组会返回该响应码
*/
GLOBAL_USER_ROLE_PERMISSION(101001, "没有权限操作非全局用户组"),
/**
* 调用获取全局用户组接口如果操作的是内置的用户组会返回该响应码
*/
INTERNAL_USER_ROLE_PERMISSION(101002, "内置用户组无法编辑与删除"),
GLOBAL_USER_ROLE_EXIST(101003, "全局用户组已存在"),
GLOBAL_USER_ROLE_RELATION_EXIST(101004, "用户已在当前用户组"),
GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION(101005, "没有权限操作非系统级别用户组"),
GLOBAL_USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION(101005, "无法将 admin 用户将系统管理员用户组删除")
GLOBAL_USER_ROLE_PERMISSION(101001, "global_user_role_permission_error"),
GLOBAL_USER_ROLE_EXIST(101002, "global_user_role_exist_error"),
GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION(101003, "global_user_role_relation_system_permission_error")
;
private final int code;

View File

@ -1,30 +1,23 @@
package io.metersphere.system.service;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.dto.UserRoleRelationUserDTO;
import io.metersphere.sdk.service.BaseUserRoleRelationService;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.domain.UserRoleRelationExample;
import io.metersphere.sdk.dto.UserRoleRelationUserDTO;
import io.metersphere.system.dto.request.GlobalUserRoleRelationQueryRequest;
import io.metersphere.system.mapper.ExtUserRoleRelationMapper;
import io.metersphere.system.mapper.UserRoleRelationMapper;
import java.util.List;
import java.util.UUID;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import io.metersphere.system.dto.request.GlobalUserRoleRelationQueryRequest;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.system.controller.result.SystemResultCode.*;
import java.util.List;
/**
* @author jianxing
* @date : 2023-6-12
*/
@Service
public class GlobalUserRoleRelationService {
public class GlobalUserRoleRelationService extends BaseUserRoleRelationService {
@Resource
private UserRoleRelationMapper userRoleRelationMapper;
@ -40,58 +33,20 @@ public class GlobalUserRoleRelationService {
return extUserRoleRelationMapper.listGlobal(request);
}
@Override
public UserRoleRelation add(UserRoleRelation userRoleRelation) {
UserRole userRole = globalUserRoleService.get(userRoleRelation.getRoleId());
checkExist(userRoleRelation);
globalUserRoleService.checkSystemUserGroup(userRole);
globalUserRoleService.checkGlobalUserRole(userRole);
userRoleRelation.setSourceId(GlobalUserRoleService.SYSTEM_TYPE);
userRoleRelation.setCreateTime(System.currentTimeMillis());
userRoleRelation.setId(UUID.randomUUID().toString());
userRoleRelationMapper.insert(userRoleRelation);
return userRoleRelation;
}
/**
* 校验用户是否已在当前用户组
*/
public void checkExist(UserRoleRelation userRoleRelation) {
UserRoleRelationExample example = new UserRoleRelationExample();
example.createCriteria()
.andUserIdEqualTo(userRoleRelation.getUserId())
.andRoleIdEqualTo(userRoleRelation.getRoleId());
List<UserRoleRelation> userRoleRelations = userRoleRelationMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(userRoleRelations)) {
throw new MSException(GLOBAL_USER_ROLE_RELATION_EXIST);
}
return super.add(userRoleRelation);
}
@Override
public void delete(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
UserRole userRole = globalUserRoleService.get(userRoleRelation.getRoleId());
checkAdminPermissionRemove(userRoleRelation, userRole);
UserRole userRole = getUserRole(id);
globalUserRoleService.checkSystemUserGroup(userRole);
globalUserRoleService.checkGlobalUserRole(userRole);
userRoleRelationMapper.deleteByPrimaryKey(id);
}
/**
* admin 不能从系统管理员用户组删除
*/
private static void checkAdminPermissionRemove(UserRoleRelation userRoleRelation, UserRole userRole) {
if (StringUtils.equals(userRole.getId(), ADMIN.getValue()) && StringUtils.equals(userRoleRelation.getUserId(), ADMIN.getValue())) {
throw new MSException(GLOBAL_USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION);
}
}
public String getLogDetails(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
if (userRoleRelation != null) {
UserRole userRole = globalUserRoleService.get(userRoleRelation.getRoleId());
return userRole == null ? null : userRole.getName();
}
return null;
super.delete(id);
}
}

View File

@ -14,7 +14,6 @@ import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -55,15 +54,6 @@ public class GlobalUserRoleService extends BaseUserRoleService {
}
}
/**
* 校验是否是内置用户组是内置抛异常
*/
public void checkInternalUserRole(UserRole userRole) {
if (BooleanUtils.isTrue(userRole.getInternal())) {
throw new MSException(INTERNAL_USER_ROLE_PERMISSION);
}
}
/**
* 校验用户是否是系统用户组
*/
@ -105,15 +95,10 @@ public class GlobalUserRoleService extends BaseUserRoleService {
return super.update(userRole);
}
public UserRole get(String id) {
return userRoleMapper.selectByPrimaryKey(id);
}
public void delete(String id) {
UserRole userRole = get(id);
checkGlobalUserRole(userRole);
checkInternalUserRole(userRole);
userRoleMapper.deleteByPrimaryKey(id);
delete(userRole);
}
public void checkRoleIsGlobalAndHaveMember(@Valid @NotEmpty List<String> roleIdList, boolean isSystem) {
@ -155,9 +140,4 @@ public class GlobalUserRoleService extends BaseUserRoleService {
checkInternalUserRole(userRole);
super.updatePermissionSetting(request);
}
public String getLogDetails(String id) {
UserRole userRole = userRoleMapper.selectByPrimaryKey(id);
return userRole == null ? null : userRole.getName();
}
}

View File

@ -0,0 +1,42 @@
package io.metersphere.system.controller;
import base.BaseTest;
import io.metersphere.system.controller.param.BasePageRequestDefinition;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MvcResult;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class CommonParamTest extends BaseTest {
/**
* 校验 BasePageRequestDefinition 参数
* @throws Exception
*/
@Test
void testBasePageRequestDefinition() throws Exception {
String url = GlobalUserRoleRelationControllerTest.BASE_URL + GlobalUserRoleRelationControllerTest.LIST;
paramValidateTest(BasePageRequestDefinition.class, url);
BasePageRequestDefinition basePageRequestDefinition = new BasePageRequestDefinition();
// @@校验 sort 字段 sql 防注入,有点复杂,手动写校验
String sortName = "SELECT * FROM user";
basePageRequestDefinition.setSort(new HashMap<>() {{
put(sortName, "asc");
}});
MvcResult mvcResult = this.requestPostAndReturn(url, basePageRequestDefinition);
// 校验错误是否是参数错误
Assertions.assertEquals(400, mvcResult.getResponse().getStatus());
Map resultData = getResultData(mvcResult, Map.class);
// 校验错误信息中包含了该字段
Assertions.assertTrue(resultData.containsKey(String.format("sort[%s]", sortName)));
}
}

View File

@ -8,8 +8,12 @@ import io.metersphere.sdk.dto.Permission;
import io.metersphere.sdk.dto.PermissionDefinitionItem;
import io.metersphere.sdk.dto.request.PermissionSettingUpdateRequest;
import io.metersphere.sdk.dto.request.UserRoleUpdateRequest;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.BaseUserRolePermissionService;
import io.metersphere.sdk.service.BaseUserRoleRelationService;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.controller.param.PermissionSettingUpdateRequestDefinition;
import io.metersphere.system.controller.param.UserRoleUpdateRequestDefinition;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.mapper.UserRoleMapper;
import jakarta.annotation.Resource;
@ -24,9 +28,9 @@ import java.util.*;
import java.util.stream.Collectors;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.INTERNAL_USER_ROLE_PERMISSION;
import static io.metersphere.system.controller.result.SystemResultCode.*;
import static io.metersphere.system.service.GlobalUserRoleService.GLOBAL_SCOPE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@SpringBootTest
@AutoConfigureMockMvc
@ -36,7 +40,8 @@ class GlobalUserRoleControllerTest extends BaseTest {
private UserRoleMapper userRoleMapper;
@Resource
private BaseUserRolePermissionService baseUserRolePermissionService;
@Resource
private BaseUserRoleRelationService baseUserRoleRelationService;
private static final String BASE_PATH = "/user/role/global/";
private static final String LIST = "list";
private static final String ADD = "add";
@ -54,7 +59,6 @@ class GlobalUserRoleControllerTest extends BaseTest {
@Test
void list() throws Exception {
// @@请求成功
MvcResult mvcResult = this.requestGetWithOk(LIST)
.andReturn();
@ -74,7 +78,6 @@ class GlobalUserRoleControllerTest extends BaseTest {
@Test
@Order(0)
void add() throws Exception {
// @@请求成功
UserRoleUpdateRequest request = new UserRoleUpdateRequest();
request.setName("test");
@ -84,23 +87,23 @@ class GlobalUserRoleControllerTest extends BaseTest {
UserRole resultData = getResultData(mvcResult, UserRole.class);
UserRole userRole = userRoleMapper.selectByPrimaryKey(resultData.getId());
// 校验请求成功数据
this.addUserRole = userRole;
Assertions.assertEquals(request.getName(), userRole.getName());
Assertions.assertEquals(request.getType(), userRole.getType());
Assertions.assertEquals(request.getDescription(), userRole.getDescription());
this.addUserRole = userRole;
// @@校验日志
checkLog(this.addUserRole.getId(), OperationLogType.ADD);
// @@重名校验异常
this.requestPost(ADD, request)
.andExpect(
jsonPath("$.code")
.value(GLOBAL_USER_ROLE_EXIST.getCode())
);
assertErrorCode(this.requestPost(ADD, request), GLOBAL_USER_ROLE_EXIST);
// @@异常参数校验
createdGroupParamValidateTest(UserRoleUpdateRequestDefinition.class, ADD);
}
@Test
@Order(1)
void update() throws Exception {
// @@请求成功
UserRoleUpdateRequest request = new UserRoleUpdateRequest();
request.setId(addUserRole.getId());
@ -114,23 +117,25 @@ class GlobalUserRoleControllerTest extends BaseTest {
Assertions.assertEquals(request.getType(), userRoleResult.getType());
Assertions.assertEquals(request.getDescription(), userRoleResult.getDescription());
// @@校验日志
checkLog(request.getId(), OperationLogType.UPDATE);
// @@操作非全局用户组异常
BeanUtils.copyBean(request, getNonGlobalUserRole());
this.requestPost(UPDATE, request)
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestPost(UPDATE, request), GLOBAL_USER_ROLE_PERMISSION);
// @@操作内置用户组异常
request.setId(ADMIN.getValue());
request.setName(ADMIN.getValue());
this.requestPost(UPDATE, request)
.andExpect(jsonPath("$.code").value(INTERNAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestPost(UPDATE, request), INTERNAL_USER_ROLE_PERMISSION);
// @@重名校验异常
request.setId(addUserRole.getId());
request.setName("系统管理员");
this.requestPost(UPDATE, request)
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_EXIST.getCode()));
this.requestPost(UPDATE, new UserRole());
assertErrorCode(this.requestPost(UPDATE, request), GLOBAL_USER_ROLE_EXIST);
// @@异常参数校验
updatedGroupParamValidateTest(UserRoleUpdateRequestDefinition.class, UPDATE);
}
@Test
@ -176,15 +181,13 @@ class GlobalUserRoleControllerTest extends BaseTest {
Assertions.assertTrue(CollectionUtils.isEmpty(permissionIds));
// @@操作非全局用户组异常
this.requestGet(PERMISSION_SETTING, getNonGlobalUserRole().getId())
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestGet(PERMISSION_SETTING, getNonGlobalUserRole().getId()), GLOBAL_USER_ROLE_PERMISSION);
}
@Test
@Order(2)
void updatePermissionSetting() throws Exception {
PermissionSettingUpdateRequest request = new PermissionSettingUpdateRequest();
request.setPermissions(new ArrayList<>() {{
PermissionSettingUpdateRequest.PermissionUpdateRequest permission1
@ -211,15 +214,19 @@ class GlobalUserRoleControllerTest extends BaseTest {
// 校验请求成功数据
Assertions.assertEquals(requestPermissionIds, permissionIds);
// @@校验日志
checkLog(request.getUserRoleId(), OperationLogType.UPDATE);
// @@操作非全局用户组异常
request.setUserRoleId(getNonGlobalUserRole().getId());
this.requestPost(PERMISSION_UPDATE, request)
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestPost(PERMISSION_UPDATE, request), GLOBAL_USER_ROLE_PERMISSION);
// @@操作内置用户组异常
request.setUserRoleId(ADMIN.getValue());
this.requestPost(PERMISSION_UPDATE, request)
.andExpect(jsonPath("$.code").value(INTERNAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestPost(PERMISSION_UPDATE, request), INTERNAL_USER_ROLE_PERMISSION);
// @@异常参数校验
paramValidateTest(PermissionSettingUpdateRequestDefinition.class, PERMISSION_UPDATE);
}
@Test
@ -229,21 +236,25 @@ class GlobalUserRoleControllerTest extends BaseTest {
this.requestGet(DELETE, addUserRole.getId());
// 校验请求成功数据
Assertions.assertNull(userRoleMapper.selectByPrimaryKey(addUserRole.getId()));
// 校验用户组与权限的关联关系是否删除
Assertions.assertTrue(CollectionUtils.isEmpty(baseUserRolePermissionService.getByRoleId(addUserRole.getId())));
// 校验用户组与用户的关联关系是否删除
Assertions.assertTrue(CollectionUtils.isEmpty(baseUserRoleRelationService.getByRoleId(addUserRole.getId())));
// @@校验日志
checkLog(addUserRole.getId(), OperationLogType.DELETE);
// @@操作非全局用户组异常
this.requestGet(DELETE, getNonGlobalUserRole().getId())
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestGet(DELETE, getNonGlobalUserRole().getId()), GLOBAL_USER_ROLE_PERMISSION);
// @@操作内置用户组异常
this.requestGet(DELETE, ADMIN.getValue())
.andExpect(jsonPath("$.code").value(INTERNAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestGet(DELETE, ADMIN.getValue()), INTERNAL_USER_ROLE_PERMISSION);
}
/**
* 插入一条非全局用户组并返回
*/
private UserRole getNonGlobalUserRole() {
protected UserRole getNonGlobalUserRole() {
// 插入一条非全局用户组数据
UserRole nonGlobalUserRole = userRoleMapper.selectByPrimaryKey(ADMIN.getValue());
nonGlobalUserRole.setName("非全局用户组");

View File

@ -3,7 +3,10 @@ package io.metersphere.system.controller;
import base.BaseTest;
import io.metersphere.sdk.dto.UserRoleRelationUserDTO;
import io.metersphere.sdk.dto.request.GlobalUserRoleRelationUpdateRequest;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.Pager;
import io.metersphere.system.controller.param.GlobalUserRoleRelationQueryRequestDefinition;
import io.metersphere.system.controller.param.GlobalUserRoleRelationUpdateRequestDefinition;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.domain.UserRoleRelationExample;
@ -24,17 +27,18 @@ import java.util.stream.Collectors;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.sdk.constants.InternalUserRole.ORG_ADMIN;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.USER_ROLE_RELATION_EXIST;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION;
import static io.metersphere.system.controller.result.SystemResultCode.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@SpringBootTest
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class GlobalUserRoleRelationControllerTest extends BaseTest {
private static final String BASE_URL = "/user/role/relation/global/";
private static final String LIST = "list";
private static final String ADD = "add";
private static final String DELETE = "delete/{0}";
public static final String BASE_URL = "/user/role/relation/global/";
public static final String LIST = "list";
public static final String ADD = "add";
public static final String DELETE = "delete/{0}";
// 保存创建的数据方便之后的修改和删除测试使用
private static UserRoleRelation addUserRoleRelation;
@Resource
@ -70,18 +74,17 @@ class GlobalUserRoleRelationControllerTest extends BaseTest {
// 检查查询结果和数据库结果是否一致
Assertions.assertEquals(userIdSet, dbUserIdSet);
// @@操作非系统级别用户组异常
request.setRoleId(ORG_ADMIN.getValue());
this.requestPost(LIST, request)
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION.getCode()));
assertErrorCode(this.requestPost(LIST, request), GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION);
// @@操作非全局用户组异常
UserRole nonGlobalUserRole = getNonGlobalUserRole();
request.setRoleId(nonGlobalUserRole.getId());
this.requestPost(LIST, request)
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestPost(LIST, request), GLOBAL_USER_ROLE_PERMISSION);
// @@异常参数校验
paramValidateTest(GlobalUserRoleRelationQueryRequestDefinition.class, LIST);
}
@Test
@ -103,33 +106,27 @@ class GlobalUserRoleRelationControllerTest extends BaseTest {
Assertions.assertTrue(CollectionUtils.isNotEmpty(userRoleRelationMapper.selectByExample(example)));
addUserRoleRelation = userRoleRelationMapper.selectByExample(example).get(0);
// @@校验日志
checkLog(addUserRoleRelation.getId(), OperationLogType.ADD);
// @@重复添加校验
request.setUserId(ADMIN.getValue());
request.setRoleId(ADMIN.getValue());
this.requestPost(ADD, request)
.andExpect(
jsonPath("$.code")
.value(GLOBAL_USER_ROLE_RELATION_EXIST.getCode())
);
assertErrorCode(this.requestPost(ADD, request), USER_ROLE_RELATION_EXIST);
// @@操作非系统用户组异常
request.setUserId(ADMIN.getValue());
request.setRoleId(ORG_ADMIN.getValue());
this.requestPost(ADD, request)
.andExpect(
jsonPath("$.code")
.value(GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION.getCode())
);
assertErrorCode(this.requestPost(ADD, request), GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION);
// @@操作非全局用户组异常
UserRole nonGlobalUserRole = getNonGlobalUserRole();
request.setUserId(ADMIN.getValue());
request.setRoleId(nonGlobalUserRole.getId());
this.requestPost(ADD, request)
.andExpect(
jsonPath("$.code")
.value(GLOBAL_USER_ROLE_PERMISSION.getCode())
);
assertErrorCode(this.requestPost(ADD, request), GLOBAL_USER_ROLE_PERMISSION);
// @@异常参数校验
createdGroupParamValidateTest(GlobalUserRoleRelationUpdateRequestDefinition.class, ADD);
}
@Test
@ -140,13 +137,15 @@ class GlobalUserRoleRelationControllerTest extends BaseTest {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(addUserRoleRelation.getId());
Assertions.assertNull(userRoleRelation);
// @@校验日志
checkLog(addUserRoleRelation.getId(), OperationLogType.DELETE);
// @@操作非系统级别用户组异常
this.requestGet(DELETE, getNonSystemUserRoleRelation().getId())
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION.getCode()));
assertErrorCode(this.requestGet(DELETE, getNonSystemUserRoleRelation().getId()),
GLOBAL_USER_ROLE_RELATION_SYSTEM_PERMISSION);
// @@操作非全局用户组异常
this.requestGet(DELETE, getNonGlobalUserRoleRelation().getId())
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_PERMISSION.getCode()));
assertErrorCode(this.requestGet(DELETE, getNonGlobalUserRoleRelation().getId()), GLOBAL_USER_ROLE_PERMISSION);
// @@删除admin系统管理员用户组异常
UserRoleRelationExample example = new UserRoleRelationExample();
@ -154,8 +153,8 @@ class GlobalUserRoleRelationControllerTest extends BaseTest {
.andRoleIdEqualTo(ADMIN.getValue())
.andUserIdEqualTo(ADMIN.getValue());
List<UserRoleRelation> userRoleRelations = userRoleRelationMapper.selectByExample(example);
this.requestGet(DELETE, userRoleRelations.get(0).getId())
.andExpect(jsonPath("$.code").value(GLOBAL_USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION.getCode()));
assertErrorCode(this.requestGet(DELETE, userRoleRelations.get(0).getId()),
USER_ROLE_RELATION_REMOVE_ADMIN_USER_PERMISSION);
}
/**

View File

@ -169,7 +169,7 @@ public class SystemProjectControllerTests extends BaseTest {
List<Project> projects = projectMapper.selectByExample(projectExample);
projectId = result.getId();
// 校验日志
checkLog(projectId, OperationLogType.ADD.name());
checkLog(projectId, OperationLogType.ADD);
this.compareProjectDTO(projects.get(0), result);
UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample();

View File

@ -95,7 +95,7 @@ public class UserControllerTests extends BaseTest {
UserBatchCreateDTO userMaintainRequest = UserTestUtils.parseObjectFromMvcResult(mvcResult, UserBatchCreateDTO.class);
userMaintainRequest.getUserInfoList().forEach(item ->{
try {
checkLog(item.getId(), OperationLogType.ADD.name());
checkLog(item.getId(), OperationLogType.ADD);
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@ -0,0 +1,26 @@
package io.metersphere.system.controller.param;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import java.util.Map;
/**
* BasePageRequest 约束定义
* @author jianxing
*/
@Data
public class BasePageRequestDefinition {
@Min(value = 1)
private int current;
@Min(value = 5)
@Max(value = 100)
private int pageSize;
private Map<@Valid @Pattern(regexp = "^[A-Za-z]+$") String, @Valid @NotBlank String> sort;
}

View File

@ -0,0 +1,15 @@
package io.metersphere.system.controller.param;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
/**
* @author : jianxing
*/
@Getter
@Setter
public class GlobalUserRoleRelationQueryRequestDefinition {
@NotBlank
private String roleId;
}

View File

@ -0,0 +1,22 @@
package io.metersphere.system.controller.param;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* @author jianxing
*/
@Data
public class GlobalUserRoleRelationUpdateRequestDefinition {
@NotBlank(groups = {Created.class})
@Size(min = 1, max = 50, groups = {Created.class, Updated.class})
private String userId;
@NotBlank(groups = {Created.class})
@Size(min = 1, max = 50, groups = {Created.class, Updated.class})
private String roleId;
}

View File

@ -0,0 +1,30 @@
package io.metersphere.system.controller.param;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* PermissionSettingUpdateRequest 约束定义
* 基于该定义生成非法参数进行参数校验
* 相对 PermissionSettingUpdateRequest 不需要写 swagger 的注解也不用写 massage
* 有继承通用的参数的话可以单独针对通用参数写一次校验就行就不继承了例如 BasePageRequestDefinition
* @author jianxing
*/
@Data
public class PermissionSettingUpdateRequestDefinition {
@NotBlank
private String userRoleId;
@NotNull
@Valid
private List<PermissionUpdateRequest> permissions;
@Data
public static class PermissionUpdateRequest {
@NotBlank
private String id;
}
}

View File

@ -0,0 +1,29 @@
package io.metersphere.system.controller.param;
import io.metersphere.sdk.constants.UserRoleType;
import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* UserRoleUpdateRequest 约束定义
* @author jianxing
*/
@Data
public class UserRoleUpdateRequestDefinition {
@NotBlank(groups = {Updated.class})
@Size(min = 1, max = 50, groups = {Created.class, Updated.class})
private String id;
@NotBlank(groups = {Created.class})
@Size(min = 1, max = 255, groups = {Created.class, Updated.class})
private String name;
@NotBlank(groups = {Created.class})
@EnumValue(enumClass = UserRoleType.class, groups = {Created.class})
@Size(min = 1, max = 20, groups = {Created.class, Updated.class})
private String type;
}