feat(系统设置): 增加用户重置密码的功能

This commit is contained in:
song-tianyang 2023-07-28 14:32:00 +08:00 committed by 建国
parent 56c366aa1c
commit 67283d673d
5 changed files with 155 additions and 38 deletions

View File

@ -88,7 +88,6 @@ public class UserController {
return userService.importByExcel(excelFile, UserSourceEnum.LOCAL.name(), SessionUtils.getSessionId());
}
@PostMapping("/delete")
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#userBatchProcessRequest)", msClass = UserService.class)
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_DELETE)
@ -102,4 +101,13 @@ public class UserController {
public List<User> getUserList() {
return userService.getUserList();
}
@PostMapping("/reset/password")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.resetPasswordLog(#userId)", msClass = UserService.class)
public boolean resetPassword(@RequestBody String userId) {
return userService.resetPassword(userId,SessionUtils.getUserId());
}
}

View File

@ -182,6 +182,7 @@ public class SystemProjectService {
public void addProjectMember(ProjectAddMemberRequest request, String createUser, boolean isAdmin, String path, String type,
String method, String content) {
List<LogDTO> logDTOList = new ArrayList<>();
//TODO 添加项目成员需要检查配额 这个需要等后续定下来补全逻辑
request.getUserIds().forEach(userId -> {
@ -216,7 +217,6 @@ public class SystemProjectService {
}
});
operationLogService.batchAdd(logDTOList);
}
public int removeProjectMember(String projectId, String userId) {

View File

@ -31,6 +31,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -306,6 +307,25 @@ public class UserService {
return null;
}
public LogDTO resetPasswordLog(String userId){
User user = userMapper.selectByPrimaryKey(userId);
if (user != null) {
LogDTO dto = new LogDTO(
"system",
"",
userId,
null,
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_USER,
user.getName());
dto.setPath("/reset/password");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(user));
return dto;
}
return null;
}
public List<LogDTO> deleteLog(UserChangeEnableRequest request) {
List<LogDTO> logDTOList = new ArrayList<>();
request.getUserIdList().forEach(item -> {
@ -335,4 +355,21 @@ public class UserService {
example.setOrderByClause("update_time desc");
return userMapper.selectByExample(example);
}
public boolean resetPassword(String userId,String operator) {
User user = userMapper.selectByPrimaryKey(userId);
if(user == null){
throw new MSException(Translator.get("user.not.exist"));
}
User updateModel = new User();
updateModel.setId(userId);
if(StringUtils.equalsIgnoreCase("admin",user.getId())){
updateModel.setPassword(CodingUtil.md5("metersphere"));
}else {
updateModel.setPassword(CodingUtil.md5(user.getEmail()));
}
updateModel.setUpdateTime(System.currentTimeMillis());
updateModel.setUpdateUser(operator);
return userMapper.updateByPrimaryKeySelective(updateModel) > 0;
}
}

View File

@ -8,6 +8,7 @@ import io.metersphere.sdk.dto.ExcelParseDTO;
import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CodingUtil;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Pager;
import io.metersphere.system.domain.User;
@ -41,10 +42,7 @@ import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@ -90,15 +88,11 @@ public class UserControllerTests extends BaseTest {
}
//成功入库的用户保存内存中其他用例会使用到
private void addUser2List(MvcResult mvcResult){
private void addUser2List(MvcResult mvcResult) throws Exception {
UserBatchCreateDTO userMaintainRequest = UserTestUtils.parseObjectFromMvcResult(mvcResult, UserBatchCreateDTO.class);
userMaintainRequest.getUserInfoList().forEach(item ->{
try {
checkLog(item.getId(), OperationLogType.ADD);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
for(UserCreateInfo item : userMaintainRequest.getUserInfoList()){
checkLog(item.getId(), OperationLogType.ADD);
}
//返回值不为空
Assertions.assertNotNull(userMaintainRequest);
USER_LIST.addAll(userMaintainRequest.getUserInfoList());
@ -139,6 +133,19 @@ public class UserControllerTests extends BaseTest {
.andReturn();
}
private MvcResult responseByString(String url, String param,ResultMatcher resultMatcher) throws Exception {
return mockMvc.perform(MockMvcRequestBuilders.post(url)
.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();
}
private MvcResult responseFile(String url, MockMultipartFile file) throws Exception {
return mockMvc.perform(MockMvcRequestBuilders.multipart(url)
.file(file)
@ -433,18 +440,21 @@ public class UserControllerTests extends BaseTest {
user.setName("TEST-UPDATE");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkLog(response.getId(), OperationLogType.UPDATE);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改邮箱
user.setEmail("songtianyang-test-email@12138.com");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkLog(response.getId(), OperationLogType.UPDATE);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改手机号
user.setPhone("18511112222");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkLog(response.getId(), OperationLogType.UPDATE);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改用户组(这里只改成用户成员权限)
@ -453,10 +463,12 @@ public class UserControllerTests extends BaseTest {
);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
checkLog(response.getId(), OperationLogType.UPDATE);
UserTestUtils.compareUserDTO(response, checkDTO);
//更改用户组(把上面的情况添加别的权限)
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkLog(response.getId(), OperationLogType.UPDATE);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//用户信息复原
@ -464,6 +476,7 @@ public class UserControllerTests extends BaseTest {
BeanUtils.copyBean(user, USER_LIST.get(0));
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(UserTestUtils.URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkLog(response.getId(), OperationLogType.UPDATE);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
}
@ -522,6 +535,10 @@ public class UserControllerTests extends BaseTest {
}});
userChangeEnableRequest.setEnable(false);
this.requestPost(UserTestUtils.URL_USER_UPDATE_ENABLE, userChangeEnableRequest, status().isOk());
for(String item : userChangeEnableRequest.getUserIdList()){
checkLog(item, OperationLogType.UPDATE);
}
UserDTO userDTO = this.getUserByEmail(userInfo.getEmail());
Assertions.assertEquals(userDTO.getEnable(), userChangeEnableRequest.isEnable());
}
@ -556,10 +573,12 @@ public class UserControllerTests extends BaseTest {
ExcelParseDTO<UserExcelRowDTO> userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
response = UserTestUtils.parseObjectFromMvcResult(this.responseFile(UserTestUtils.URL_USER_IMPORT, file), UserImportResponse.class);
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);//检查返回值
this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
List<UserDTO> userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
for (UserDTO item : userDTOList){
checkLog(item.getId(), OperationLogType.ADD);
}
//导入空文件
//导入空文件. 应当导入成功的数据为0
filePath = 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);
@ -567,15 +586,14 @@ public class UserControllerTests extends BaseTest {
errorDataIndex = new int[]{};
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
//文件内没有一条合格数据
//文件内没有一条合格数据 应当导入成功的数据为0
filePath = 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);
importSuccessData = 0;
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();
file = new MockMultipartFile("file", "userImport.xlsx", MediaType.APPLICATION_OCTET_STREAM_VALUE, UserTestUtils.getFileBytes(filePath));
userImportReportDTOByFile = userService.getUserExcelParseDTO(file);
@ -583,39 +601,84 @@ public class UserControllerTests extends BaseTest {
importSuccessData = 8;
errorDataIndex = new int[]{1, 7};
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
for (UserDTO item : userDTOList){
checkLog(item.getId(), OperationLogType.ADD);
}
//文件内邮箱重复
//文件内邮箱重复 应当导入成功的数据为8
filePath = 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);
importSuccessData = 8;
errorDataIndex = new int[]{9, 10};
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
for (UserDTO item : userDTOList){
checkLog(item.getId(), OperationLogType.ADD);
}
//文件不符合规范
filePath = this.getClass().getClassLoader().getResource("file/abcde.gif").getPath();
//文件不符合规范 应当导入成功的数据为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);
importSuccessData = 0;
errorDataIndex = new int[]{};
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);
//测试03版excel正常导入
filePath = this.getClass().getClassLoader().getResource("file/user_import_success_03.xls").getPath();
//测试03版excel正常导入 应当导入成功的数据为10
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);
importSuccessData = 10;//应该导入成功的数据数量
errorDataIndex = new int[]{};//出错数据的行数
UserTestUtils.checkImportResponse(response, importSuccessData, errorDataIndex);//检查返回值
this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
userDTOList = this.checkImportUserInDb(userImportReportDTOByFile);//检查数据已入库
for (UserDTO item : userDTOList){
checkLog(item.getId(), OperationLogType.ADD);
}
}
@Test
@Order(8)
public void testUserResetPasswordSuccess() throws Exception {
this.checkUserList();
String userId = USER_LIST.get(0).getId();
String userEmail = USER_LIST.get(0).getEmail();
//重置普通用户密码
this.resetPasswordAndCheck(userId,userEmail);
this.checkLog(userId, OperationLogType.UPDATE);
//重置admin的密码
this.resetPasswordAndCheck("admin","metersphere");
this.checkLog(userId, OperationLogType.UPDATE);
}
private void resetPasswordAndCheck(String userId,String userEmail) throws Exception{
User user = new User();
user.setId(userId);
user.setPassword("I can't say any dirty words");
Assertions.assertEquals(1, userMapper.updateByPrimaryKeySelective(user));
//调用重置密码的接口
this.responseByString(UserTestUtils.URL_USER_RESET_PASSWORD, userId,status().isOk());
//检查数据库
UserExample example = new UserExample();
example.createCriteria().andIdEqualTo(userId).andPasswordEqualTo(CodingUtil.md5(userEmail));
Assertions.assertEquals(1, userMapper.countByExample(example));
checkLog(userId, OperationLogType.UPDATE);
}
@Test
@Order(8)
public void testUserResetPasswordError() throws Exception {
//用户不存在
this.responseByString(UserTestUtils.URL_USER_RESET_PASSWORD, "none user",ERROR_REQUEST_MATCHER);
}
@Test
@Order(9)
public void testUserDeleteSuccess() throws Exception {
this.checkUserList();
//删除已存的所有用户
@ -636,8 +699,9 @@ public class UserControllerTests extends BaseTest {
DELETED_USER_ID_LIST.addAll(request.getUserIdList());
}
//删除失败的方法要放在删除成功方法后面执行
@Test
@Order(9)
@Order(10)
public void testUserDeleteError() throws Exception {
this.checkUserDeleted();
//参数为空
@ -651,9 +715,15 @@ public class UserControllerTests extends BaseTest {
this.requestPost(UserTestUtils.URL_USER_DELETE, request, ERROR_REQUEST_MATCHER);
}
public void checkImportUserInDb(ExcelParseDTO<UserExcelRowDTO> userImportReportDTOByFile) throws Exception {
public List<UserDTO> checkImportUserInDb(ExcelParseDTO<UserExcelRowDTO> userImportReportDTOByFile) throws Exception {
List<UserDTO> returnList = new ArrayList<>();
for (UserExcelRowDTO item : userImportReportDTOByFile.getDataList()) {
Assertions.assertNotNull(this.getUserByEmail(item.getEmail()));
UserDTO userDTO = this.getUserByEmail(item.getEmail());
Assertions.assertNotNull(userDTO);
returnList.add(userDTO);
}
return returnList;
}
}

View File

@ -35,18 +35,20 @@ public class UserTestUtils {
public static final String URL_USER_UPDATE_ENABLE = "/system/user/update/enable";
public static final String URL_USER_IMPORT = "/system/user/import";
public static final String URL_USER_DELETE = "/system/user/delete";
public static final String URL_USER_RESET_PASSWORD = "/system/user/reset/password";
public static <T> T parseObjectFromMvcResult(MvcResult mvcResult, Class<T> parseClass) {
String returnData = "";
try {
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), parseClass);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
} catch (Exception ignore) {
}
return null;
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), parseClass);
}
public static UserBatchCreateDTO getUserCreateDTO(