fix(系统设置): 修复删除用户时没有处理掉删除用户邮箱的缺陷
This commit is contained in:
parent
411e2d1e5d
commit
bc0efbc73e
|
@ -26,4 +26,6 @@ public interface BaseUserMapper {
|
|||
List<String> selectUnDeletedUserIdByIdList(@Param("idList") List<String> userIdList);
|
||||
|
||||
List<User> selectUserByIdList(List<String> userIds);
|
||||
|
||||
long deleteUser(String id);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.sdk.mapper.BaseUserMapper">
|
||||
<update id="deleteUser">
|
||||
UPDATE `user` SET `deleted` = 1, `email` = id WHERE `id` = #{id}
|
||||
</update>
|
||||
<select id="selectById" resultType="io.metersphere.sdk.dto.UserDTO">
|
||||
SELECT *
|
||||
FROM user
|
||||
|
@ -21,13 +24,13 @@
|
|||
</select>
|
||||
|
||||
<insert id="batchSave">
|
||||
INSERT INTO user(id, name, email, password, status, create_time, update_time, language, last_organization_id,
|
||||
INSERT INTO user(id, name, email, password, status, create_time, update_time,update_user, language, last_organization_id,
|
||||
phone,
|
||||
source, last_project_id, create_user,deleted)
|
||||
VALUES
|
||||
<foreach collection="users" item="user" separator=",">
|
||||
(#{user.id}, #{user.name}, #{user.email}, #{user.password}, #{user.status}, #{user.createTime},
|
||||
#{user.updateTime}, #{user.language},
|
||||
#{user.updateTime},#{user.updateUser}, #{user.language},
|
||||
#{user.lastOrganizationId}, #{user.phone}, #{user.source}, #{user.lastProjectId}, #{user.createUser}, #{user.deleted})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
|
|
@ -44,24 +44,28 @@ public class UserController {
|
|||
private GlobalUserRoleService globalUserRoleService;
|
||||
|
||||
@GetMapping("/get/{email}")
|
||||
@Operation(summary = "通过email查找用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_READ)
|
||||
public UserDTO getUser(@PathVariable String email) {
|
||||
return userService.getUserDTOByEmail(email);
|
||||
}
|
||||
|
||||
@GetMapping("/get/global/system/role")
|
||||
@Operation(summary = "查找系统级用户权限")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_ADD)
|
||||
public List<UserRoleOption> getGlobalSystemRole() {
|
||||
return globalUserRoleService.getGlobalSystemRoleList();
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "添加用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_ADD)
|
||||
public UserBatchCreateDTO addUser(@Validated({Created.class}) @RequestBody UserBatchCreateDTO userCreateDTO) {
|
||||
return userService.addUser(userCreateDTO, UserSourceEnum.LOCAL.name(), SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "修改用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = UserService.class)
|
||||
public UserEditRequest updateUser(@Validated({Updated.class}) @RequestBody UserEditRequest request) {
|
||||
|
@ -69,6 +73,7 @@ public class UserController {
|
|||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "分页查找用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ)
|
||||
public Pager<List<UserTableResponse>> list(@Validated @RequestBody BasePageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
|
@ -77,18 +82,21 @@ public class UserController {
|
|||
}
|
||||
|
||||
@PostMapping("/update/enable")
|
||||
@Operation(summary = "启用/禁用用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE)
|
||||
public UserBatchProcessResponse updateUserEnable(@Validated @RequestBody UserChangeEnableRequest request) {
|
||||
return userService.updateUserEnable(request, SessionUtils.getSessionId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/import", consumes = {"multipart/form-data"})
|
||||
@Operation(summary = "导入用户")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_IMPORT)
|
||||
public UserImportResponse importUser(@RequestPart(value = "file", required = false) MultipartFile excelFile) {
|
||||
return userService.importByExcel(excelFile, UserSourceEnum.LOCAL.name(), SessionUtils.getSessionId());
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@Operation(summary = "删除用户")
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#userBatchProcessRequest)", msClass = UserService.class)
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_DELETE)
|
||||
public UserBatchProcessResponse deleteUser(@Validated @RequestBody UserChangeEnableRequest userBatchProcessRequest) {
|
||||
|
|
|
@ -32,6 +32,10 @@ import jakarta.validation.constraints.NotEmpty;
|
|||
import jakarta.validation.constraints.NotNull;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -57,6 +61,8 @@ public class UserService {
|
|||
private GlobalUserRoleService globalUserRoleService;
|
||||
@Resource
|
||||
private UserRoleService userRoleService;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
|
||||
//批量添加用户记录日志
|
||||
public List<LogDTO> getBatchAddLogs(@Valid List<User> userList) {
|
||||
|
@ -273,20 +279,35 @@ public class UserService {
|
|||
|
||||
public UserBatchProcessResponse deleteUser(@Valid @NotEmpty List<String> userIdList) {
|
||||
this.checkUserInDb(userIdList);
|
||||
|
||||
UserBatchProcessResponse response = new UserBatchProcessResponse();
|
||||
response.setTotalCount(userIdList.size());
|
||||
|
||||
UserExample userExample = new UserExample();
|
||||
userExample.createCriteria().andIdIn(userIdList);
|
||||
//更新删除标志位
|
||||
response.setSuccessCount(userMapper.updateByExampleSelective(new User() {{
|
||||
setDeleted(true);
|
||||
}}, userExample));
|
||||
response.setSuccessCount(this.deleteUserByList(userIdList));
|
||||
//删除用户角色关系
|
||||
userRoleRelationService.deleteByUserIdList(userIdList);
|
||||
return response;
|
||||
}
|
||||
|
||||
private int deleteUserByList(List<String> updateUserList){
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
BaseUserMapper batchDeleteMapper = sqlSession.getMapper(BaseUserMapper.class);
|
||||
int insertIndex = 0;
|
||||
for (String userId : updateUserList) {
|
||||
batchDeleteMapper.deleteUser(userId);
|
||||
insertIndex++;
|
||||
if (insertIndex % 50 == 0) {
|
||||
sqlSession.flushStatements();
|
||||
}
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
return insertIndex;
|
||||
}
|
||||
|
||||
public LogDTO updateLog(UserEditRequest request) {
|
||||
User user = userMapper.selectByPrimaryKey(request.getId());
|
||||
if (user != null) {
|
||||
|
|
|
@ -105,13 +105,6 @@ public class UserControllerTests extends BaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkUserDeleted() throws Exception {
|
||||
if (CollectionUtils.isEmpty(DELETED_USER_ID_LIST)) {
|
||||
//测试数据初始化入库
|
||||
this.testUserDeleteSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
private void requestPost(String url, Object param, ResultMatcher resultMatcher) throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.post(url)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
|
@ -134,20 +127,19 @@ public class UserControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
|
||||
private MvcResult responseByString(String url, String param,ResultMatcher resultMatcher) throws Exception {
|
||||
return mockMvc.perform(MockMvcRequestBuilders.post(url)
|
||||
private void requestResetPassword(String param, ResultMatcher resultMatcher) throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.post(UserTestUtils.URL_USER_RESET_PASSWORD)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.content(param)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(resultMatcher).andDo(print())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
|
||||
private MvcResult responseFile(String url, MockMultipartFile file) throws Exception {
|
||||
return mockMvc.perform(MockMvcRequestBuilders.multipart(url)
|
||||
private MvcResult responseFile(MockMultipartFile file) throws Exception {
|
||||
return mockMvc.perform(MockMvcRequestBuilders.multipart(UserTestUtils.URL_USER_IMPORT)
|
||||
.file(file)
|
||||
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
|
@ -196,6 +188,23 @@ public class UserControllerTests extends BaseTest {
|
|||
MvcResult mvcResult = this.responsePost(UserTestUtils.URL_USER_CREATE, userMaintainRequest);
|
||||
this.addUser2List(mvcResult);
|
||||
|
||||
|
||||
//批量添加一百多个用户
|
||||
List<UserCreateInfo> userCreateInfoList = new ArrayList<>();
|
||||
for (int i = 0; i < 123; i++) {
|
||||
int finalI = i;
|
||||
userCreateInfoList.add(new UserCreateInfo() {{
|
||||
setName("tianyang.no.batch" + finalI);
|
||||
setEmail("tianyang.no.batch" + finalI + "@126.com");
|
||||
}});
|
||||
}
|
||||
userMaintainRequest = UserTestUtils.getUserCreateDTO(
|
||||
defaultUserRoleList,
|
||||
userCreateInfoList
|
||||
);
|
||||
mvcResult = this.responsePost(UserTestUtils.URL_USER_CREATE, userMaintainRequest);
|
||||
this.addUser2List(mvcResult);
|
||||
|
||||
//含有重复的用户名称
|
||||
userMaintainRequest = UserTestUtils.getUserCreateDTO(
|
||||
|
||||
|
@ -568,10 +577,10 @@ public class UserControllerTests extends BaseTest {
|
|||
int[] errorDataIndex = {};//出错数据的行数
|
||||
UserImportResponse response;//导入返回值
|
||||
//导入正常文件
|
||||
String filePath = this.getClass().getClassLoader().getResource("file/user_import_success.xlsx").getPath();
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_success.xlsx")).getPath();
|
||||
MockMultipartFile file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
ExcelParseDTO<UserExcelRowDTO> userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);//检查返回值
|
||||
List<UserDTO> userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
|
||||
for (UserDTO item : userDTOList){
|
||||
|
@ -579,25 +588,25 @@ public class UserControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
//导入空文件. 应当导入成功的数据为0
|
||||
filePath = this.getClass().getClassLoader().getResource("file/user_import_success_empty.xlsx").getPath();
|
||||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_success_empty.xlsx")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
importSuccessData = 0;
|
||||
errorDataIndex = new int[]{};
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
|
||||
|
||||
//文件内没有一条合格数据 应当导入成功的数据为0
|
||||
filePath = this.getClass().getClassLoader().getResource("file/user_import_error_all.xlsx").getPath();
|
||||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_error_all.xlsx")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
errorDataIndex = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
|
||||
|
||||
//邮箱和数据库里的重复 应当导入成功的数据为8
|
||||
filePath = this.getClass().getClassLoader().getResource("file/user_import_error_email_repeat_db.xlsx").getPath();
|
||||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_error_email_repeat_db.xlsx")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
importSuccessData = 8;
|
||||
errorDataIndex = new int[]{1, 7};
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
|
||||
|
@ -607,10 +616,10 @@ public class UserControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
//文件内邮箱重复 应当导入成功的数据为8
|
||||
filePath = this.getClass().getClassLoader().getResource("file/user_import_error_email_repeat_in_file.xlsx").getPath();
|
||||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_error_email_repeat_in_file.xlsx")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
errorDataIndex = new int[]{9, 10};
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
|
||||
userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
|
||||
|
@ -621,7 +630,7 @@ public class UserControllerTests extends BaseTest {
|
|||
//文件不符合规范 应当导入成功的数据为0
|
||||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/abcde.gif")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
importSuccessData = 0;
|
||||
errorDataIndex = new int[]{};
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
|
||||
|
@ -630,7 +639,7 @@ public class UserControllerTests extends BaseTest {
|
|||
filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/user_import_success_03.xls")).getPath();
|
||||
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
|
||||
userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
|
||||
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(file), UserImportResponse.class);
|
||||
importSuccessData = 10;//应该导入成功的数据数量
|
||||
errorDataIndex = new int[]{};//出错数据的行数
|
||||
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);//检查返回值
|
||||
|
@ -662,7 +671,7 @@ public class UserControllerTests extends BaseTest {
|
|||
Assertions.assertEquals(1, userMapper.updateByPrimaryKeySelective(user));
|
||||
|
||||
//调用重置密码的接口
|
||||
this.responseByString(UserTestUtils.URL_USER_RESET_PASSWORD, userId,status().isOk());
|
||||
this.requestResetPassword(userId,status().isOk());
|
||||
//检查数据库
|
||||
UserExample example = new UserExample();
|
||||
example.createCriteria().andIdEqualTo(userId).andPasswordEqualTo(CodingUtil.md5(userEmail));
|
||||
|
@ -674,7 +683,7 @@ public class UserControllerTests extends BaseTest {
|
|||
@Order(8)
|
||||
public void testUserResetPasswordError() throws Exception {
|
||||
//用户不存在
|
||||
this.responseByString(UserTestUtils.URL_USER_RESET_PASSWORD, "none user",ERROR_REQUEST_MATCHER);
|
||||
this.requestResetPassword("none user",ERROR_REQUEST_MATCHER);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -696,14 +705,16 @@ public class UserControllerTests extends BaseTest {
|
|||
}
|
||||
//记录已经删除了的用户,用于反例
|
||||
DELETED_USER_ID_LIST.clear();
|
||||
USER_LIST.clear();
|
||||
DELETED_USER_ID_LIST.addAll(request.getUserIdList());
|
||||
//检查删除了的用户,可以用其邮箱继续注册
|
||||
this.testAddSuccess();
|
||||
}
|
||||
|
||||
//删除失败的方法要放在删除成功方法后面执行
|
||||
@Test
|
||||
@Order(10)
|
||||
public void testUserDeleteError() throws Exception {
|
||||
this.checkUserDeleted();
|
||||
//参数为空
|
||||
UserBatchProcessRequest request = new UserBatchProcessRequest();
|
||||
this.requestPost(UserTestUtils.URL_USER_DELETE, request, BAD_REQUEST_MATCHER);
|
||||
|
@ -711,6 +722,9 @@ public class UserControllerTests extends BaseTest {
|
|||
request.getUserIdList().add("123456789012345678901234");
|
||||
this.requestPost(UserTestUtils.URL_USER_DELETE, request, ERROR_REQUEST_MATCHER);
|
||||
//用户已经被删除
|
||||
if(CollectionUtils.isEmpty(DELETED_USER_ID_LIST)){
|
||||
this.testUserDeleteSuccess();
|
||||
}
|
||||
request.setUserIdList(DELETED_USER_ID_LIST);
|
||||
this.requestPost(UserTestUtils.URL_USER_DELETE, request, ERROR_REQUEST_MATCHER);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue