commit:同步2.2版本
@@ -164,6 +164,16 @@ public interface SysDeptClient extends BaseClient<SysDeptDto, SysDeptVo, Long> {
|
||||
@PostMapping("/sysDept/aggregateBy")
|
||||
ResponseResult<List<Map<String, Object>>> aggregateBy(@RequestBody MyAggregationParam aggregationParam);
|
||||
|
||||
/**
|
||||
* 根据过滤字段和过滤集合,返回不存在的数据。
|
||||
*
|
||||
* @param queryParam 查询参数。
|
||||
* @return filterSet中,在从表中不存在的数据集合。
|
||||
*/
|
||||
@Override
|
||||
@PostMapping("/sysDept/notExist")
|
||||
ResponseResult<List<?>> notExist(@RequestBody MyQueryParam queryParam);
|
||||
|
||||
@Component("UpmsSysDeptClientFallbackFactory")
|
||||
@Slf4j
|
||||
class SysDeptClientFallbackFactory
|
||||
|
||||
@@ -166,6 +166,16 @@ public interface SysUserClient extends BaseClient<SysUserDto, SysUserVo, Long> {
|
||||
@PostMapping("/sysUser/aggregateBy")
|
||||
ResponseResult<List<Map<String, Object>>> aggregateBy(@RequestBody MyAggregationParam aggregationParam);
|
||||
|
||||
/**
|
||||
* 根据过滤字段和过滤集合,返回不存在的数据。
|
||||
*
|
||||
* @param queryParam 查询参数。
|
||||
* @return filterSet中,在从表中不存在的数据集合。
|
||||
*/
|
||||
@Override
|
||||
@PostMapping("/sysUser/notExist")
|
||||
ResponseResult<List<?>> notExist(@RequestBody MyQueryParam queryParam);
|
||||
|
||||
/**
|
||||
* 获取指定角色Id集合的用户数据集合。
|
||||
* @param roleIds 角色Id集合。
|
||||
|
||||
@@ -14,6 +14,22 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.anji-plus</groupId>
|
||||
<artifactId>spring-boot-starter-captcha</artifactId>
|
||||
<version>${ajcaptcha.version}</version>
|
||||
</dependency>
|
||||
<!-- aj-captcha 依赖data-redis作为缓存 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- 业务组件依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.orangeforms</groupId>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.orangeforms.upmsservice.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.anji.captcha.model.common.ResponseModel;
|
||||
import com.anji.captcha.model.vo.CaptchaVO;
|
||||
import com.anji.captcha.service.CaptchaService;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
@@ -11,11 +17,13 @@ import com.orangeforms.common.core.constant.ErrorCodeEnum;
|
||||
import com.orangeforms.common.core.constant.ApplicationConstant;
|
||||
import com.orangeforms.common.core.object.*;
|
||||
import com.orangeforms.common.core.util.*;
|
||||
import com.orangeforms.common.core.upload.*;
|
||||
import com.orangeforms.common.redis.cache.SessionCacheHelper;
|
||||
import com.orangeforms.common.log.annotation.OperationLog;
|
||||
import com.orangeforms.common.log.model.constant.SysOperationLogType;
|
||||
import com.orangeforms.upmsapi.constant.SysUserStatus;
|
||||
import com.orangeforms.upmsapi.constant.SysUserType;
|
||||
import com.orangeforms.upmsservice.config.ApplicationConfig;
|
||||
import com.orangeforms.upmsservice.model.*;
|
||||
import com.orangeforms.upmsservice.service.*;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
@@ -24,7 +32,9 @@ import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
@@ -63,27 +73,53 @@ public class LoginController {
|
||||
private SessionCacheHelper cacheHelper;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Autowired
|
||||
private ApplicationConfig appConfig;
|
||||
@Autowired
|
||||
private CaptchaService captchaService;
|
||||
@Autowired
|
||||
private UpDownloaderFactory upDownloaderFactory;
|
||||
|
||||
/**
|
||||
* 登录接口。
|
||||
*
|
||||
* @param loginName 登录名。
|
||||
* @param password 密码。
|
||||
* @param loginName 登录名。
|
||||
* @param password 密码。
|
||||
* @param captchaVerification 验证码。
|
||||
* @return 应答结果对象,其中包括JWT的Token数据,以及菜单列表。
|
||||
*/
|
||||
@ApiImplicitParams({
|
||||
// 这里包含密码密文,仅用于方便开发期间的接口测试,集成测试和发布阶段,需要将当前注解去掉。
|
||||
// 如果您重新生成了公钥和私钥,请替换password的缺省值。
|
||||
@ApiImplicitParam(name = "loginName", defaultValue = "admin"),
|
||||
@ApiImplicitParam(name = "password", defaultValue = "IP3ccke3GhH45iGHB5qP9p7iZw6xUyj28Ju10rnBiPKOI35sc%2BjI7%2FdsjOkHWMfUwGYGfz8ik31HC2Ruk%2Fhkd9f6RPULTHj7VpFdNdde2P9M4mQQnFBAiPM7VT9iW3RyCtPlJexQ3nAiA09OqG%2F0sIf1kcyveSrulxembARDbDo%3D")
|
||||
@ApiImplicitParam(name = "password", defaultValue = "IP3ccke3GhH45iGHB5qP9p7iZw6xUyj28Ju10rnBiPKOI35sc%2BjI7%2FdsjOkHWMfUwGYGfz8ik31HC2Ruk%2Fhkd9f6RPULTHj7VpFdNdde2P9M4mQQnFBAiPM7VT9iW3RyCtPlJexQ3nAiA09OqG%2F0sIf1kcyveSrulxembARDbDo%3D"),
|
||||
@ApiImplicitParam(name = "captchaVerification", defaultValue = "为了方便测试,这里可以修改一下代码,hardcode一个每次都ok的验证码")
|
||||
})
|
||||
@OperationLog(type = SysOperationLogType.LOGIN, saveResponse = false)
|
||||
@PostMapping("/doLogin")
|
||||
public ResponseResult<JSONObject> doLogin(
|
||||
@MyRequestBody String loginName, @MyRequestBody String password) throws Exception {
|
||||
if (MyCommonUtil.existBlankArgument(loginName, password)) {
|
||||
@MyRequestBody String loginName,
|
||||
@MyRequestBody String password,
|
||||
@MyRequestBody String captchaVerification) throws Exception {
|
||||
if (MyCommonUtil.existBlankArgument(loginName, password, captchaVerification)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
String errorMessage;
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(captchaVerification);
|
||||
ResponseModel response = captchaService.verification(captchaVO);
|
||||
if (!response.isSuccess()) {
|
||||
//验证码校验失败,返回信息告诉前端
|
||||
//repCode 0000 无异常,代表成功
|
||||
//repCode 9999 服务器内部异常
|
||||
//repCode 0011 参数不能为空
|
||||
//repCode 6110 验证码已失效,请重新获取
|
||||
//repCode 6111 验证失败
|
||||
//repCode 6112 获取验证码失败,请联系管理员
|
||||
errorMessage = String.format("数据验证失败,验证码错误,错误码 [%s] 错误信息 [%s]",
|
||||
response.getRepCode(), response.getRepMsg());
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
SysUser user = sysUserService.getSysUserByLoginName(loginName);
|
||||
if (user == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
||||
@@ -95,7 +131,6 @@ public class LoginController {
|
||||
if (!passwordEncoder.matches(password, user.getPassword())) {
|
||||
return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
||||
}
|
||||
String errorMessage;
|
||||
if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) {
|
||||
errorMessage = "登录失败,用户账号被锁定!";
|
||||
return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage);
|
||||
@@ -136,6 +171,9 @@ public class LoginController {
|
||||
JSONObject jsonData = new JSONObject();
|
||||
jsonData.put("showName", tokenData.getShowName());
|
||||
jsonData.put("isAdmin", tokenData.getIsAdmin());
|
||||
if (StrUtil.isNotBlank(tokenData.getHeadImageUrl())) {
|
||||
jsonData.put("headImageUrl", tokenData.getHeadImageUrl());
|
||||
}
|
||||
Collection<SysMenu> menuList;
|
||||
Collection<String> permCodeList;
|
||||
if (tokenData.getIsAdmin()) {
|
||||
@@ -180,9 +218,71 @@ public class LoginController {
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传并修改用户头像。
|
||||
*
|
||||
* @param uploadFile 上传的头像文件。
|
||||
*/
|
||||
@PostMapping("/changeHeadImage")
|
||||
public void changeHeadImage(
|
||||
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
|
||||
String fieldName = "headImageUrl";
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
UploadResponseInfo responseInfo = upDownloader.doUpload(null,
|
||||
appConfig.getUploadFileBaseDir(), SysUser.class.getSimpleName(), fieldName, true, uploadFile);
|
||||
if (responseInfo.getUploadFailed()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
|
||||
return;
|
||||
}
|
||||
responseInfo.setDownloadUri("/admin/upms/login/downloadHeadImage");
|
||||
String newHeadImage = JSONArray.toJSONString(CollUtil.newArrayList(responseInfo));
|
||||
if (!sysUserService.changeHeadImage(TokenData.takeFromRequest().getUserId(), newHeadImage)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST));
|
||||
return;
|
||||
}
|
||||
ResponseResult.output(ResponseResult.success(responseInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载用户头像。
|
||||
*
|
||||
* @param filename 文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
|
||||
* @param response Http 应答对象。
|
||||
*/
|
||||
@GetMapping("/downloadHeadImage")
|
||||
public void downloadHeadImage(String filename, HttpServletResponse response) {
|
||||
try {
|
||||
SysUser user = sysUserService.getById(TokenData.takeFromRequest().getUserId());
|
||||
if (user == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(user.getHeadImageUrl())) {
|
||||
ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
if (!BaseUpDownloader.containFile(user.getHeadImageUrl(), filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
String fieldName = "headImageUrl";
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
|
||||
SysUser.class.getSimpleName(), fieldName, filename, true, response);
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject buildLoginData(SysUser user) {
|
||||
int deviceType = MyCommonUtil.getDeviceType();
|
||||
boolean isAdmin = user.getUserType() == SysUserType.TYPE_ADMIN;
|
||||
String headImageUrl = user.getHeadImageUrl();
|
||||
TokenData tokenData = new TokenData();
|
||||
String sessionId = user.getLoginName() + "_" + deviceType + "_" + MyCommonUtil.generateUuid();
|
||||
tokenData.setUserId(user.getUserId());
|
||||
@@ -194,6 +294,9 @@ public class LoginController {
|
||||
tokenData.setLoginIp(IpUtil.getRemoteIpAddress(ContextUtil.getHttpRequest()));
|
||||
tokenData.setLoginTime(new Date());
|
||||
tokenData.setDeviceType(deviceType);
|
||||
if (StrUtil.isNotBlank(headImageUrl)) {
|
||||
tokenData.setHeadImageUrl(headImageUrl);
|
||||
}
|
||||
List<SysUserRole> userRoleList = sysRoleService.getSysUserRoleListByUserId(user.getUserId());
|
||||
if (CollectionUtils.isNotEmpty(userRoleList)) {
|
||||
Set<Long> userRoleIdSet = userRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());
|
||||
@@ -205,6 +308,9 @@ public class LoginController {
|
||||
jsonData.put(TokenData.REQUEST_ATTRIBUTE_NAME, tokenData);
|
||||
jsonData.put("showName", user.getShowName());
|
||||
jsonData.put("isAdmin", isAdmin);
|
||||
if (StrUtil.isNotBlank(headImageUrl)) {
|
||||
jsonData.put("headImageUrl", headImageUrl);
|
||||
}
|
||||
Collection<SysMenu> menuList;
|
||||
Collection<String> permCodeList;
|
||||
if (isAdmin) {
|
||||
|
||||
@@ -119,27 +119,7 @@ public class SysDeptController extends BaseController<SysDept, SysDeptVo, Long>
|
||||
if (MyCommonUtil.existBlankArgument(deptId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
SysDept originalSysDept = sysDeptService.getById(deptId);
|
||||
if (originalSysDept == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildren(deptId)) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象存在子对象],请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildrenUser(deptId)) {
|
||||
errorMessage = "数据验证失败,请先移除部门用户数据后,再删除当前部门!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (!sysDeptService.remove(deptId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,4 +370,43 @@ public class SysDeptController extends BaseController<SysDept, SysDeptVo, Long>
|
||||
public ResponseResult<List<Map<String, Object>>> aggregateBy(@RequestBody MyAggregationParam aggregationParam) {
|
||||
return super.baseAggregateBy(aggregationParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据过滤字段和过滤集合,返回不存在的数据。主要用于微服务间远程过程调用。
|
||||
*
|
||||
* @param queryParam 查询参数。
|
||||
* @return 不存在的数据集合。
|
||||
*/
|
||||
@ApiOperation(hidden = true, value = "notExist")
|
||||
@PostMapping("/notExist")
|
||||
public ResponseResult<List<?>> notExist(@RequestBody MyQueryParam queryParam) {
|
||||
List<?> notExistIdSet = service().notExist(
|
||||
queryParam.getInFilterField(), queryParam.getInFilterValues(), true);
|
||||
return ResponseResult.success(notExistIdSet);
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long deptId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
SysDept originalSysDept = sysDeptService.getById(deptId);
|
||||
if (originalSysDept == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildren(deptId)) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象存在子对象],请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildrenUser(deptId)) {
|
||||
errorMessage = "数据验证失败,请先移除部门用户数据后,再删除当前部门!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (!sysDeptService.remove(deptId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.orangeforms.upmsservice.controller;
|
||||
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.github.pagehelper.page.PageMethod;
|
||||
import com.orangeforms.upmsservice.model.*;
|
||||
@@ -13,15 +14,22 @@ import com.orangeforms.common.core.constant.*;
|
||||
import com.orangeforms.common.core.base.controller.BaseController;
|
||||
import com.orangeforms.common.core.base.service.IBaseService;
|
||||
import com.orangeforms.common.core.annotation.MyRequestBody;
|
||||
import com.orangeforms.common.core.upload.BaseUpDownloader;
|
||||
import com.orangeforms.common.core.upload.UpDownloaderFactory;
|
||||
import com.orangeforms.common.core.upload.UploadResponseInfo;
|
||||
import com.orangeforms.common.core.upload.UploadStoreInfo;
|
||||
import com.orangeforms.common.log.annotation.OperationLog;
|
||||
import com.orangeforms.common.log.model.constant.SysOperationLogType;
|
||||
import com.orangeforms.common.redis.cache.SessionCacheHelper;
|
||||
import com.orangeforms.upmsservice.config.ApplicationConfig;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import io.swagger.annotations.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -40,6 +48,10 @@ public class SysUserController extends BaseController<SysUser, SysUserVo, Long>
|
||||
private SysUserService sysUserService;
|
||||
@Autowired
|
||||
private ApplicationConfig appConfig;
|
||||
@Autowired
|
||||
private SessionCacheHelper cacheHelper;
|
||||
@Autowired
|
||||
private UpDownloaderFactory upDownloaderFactory;
|
||||
|
||||
@Override
|
||||
protected IBaseService<SysUser, Long> service() {
|
||||
@@ -149,18 +161,7 @@ public class SysUserController extends BaseController<SysUser, SysUserVo, Long>
|
||||
if (MyCommonUtil.existBlankArgument(userId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
SysUser originalSysUser = sysUserService.getById(userId);
|
||||
if (originalSysUser == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!sysUserService.remove(userId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,6 +206,101 @@ public class SysUserController extends BaseController<SysUser, SysUserVo, Long>
|
||||
return ResponseResult.success(sysUserVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 附件文件下载。
|
||||
* 这里将图片和其他类型的附件文件放到不同的父目录下,主要为了便于今后图片文件的迁移。
|
||||
*
|
||||
* @param userId 附件所在记录的主键Id。
|
||||
* @param fieldName 附件所属的字段名。
|
||||
* @param filename 文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
|
||||
* @param asImage 下载文件是否为图片。
|
||||
* @param response Http 应答对象。
|
||||
*/
|
||||
@OperationLog(type = SysOperationLogType.DOWNLOAD, saveResponse = false)
|
||||
@GetMapping("/download")
|
||||
public void download(
|
||||
@RequestParam(required = false) Long userId,
|
||||
@RequestParam String fieldName,
|
||||
@RequestParam String filename,
|
||||
@RequestParam Boolean asImage,
|
||||
HttpServletResponse response) {
|
||||
if (MyCommonUtil.existBlankArgument(fieldName, filename, asImage)) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
// 使用try来捕获异常,是为了保证一旦出现异常可以返回500的错误状态,便于调试。
|
||||
// 否则有可能给前端返回的是200的错误码。
|
||||
try {
|
||||
// 如果请求参数中没有包含主键Id,就判断该文件是否为当前session上传的。
|
||||
if (userId == null) {
|
||||
if (!cacheHelper.existSessionUploadFile(filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
SysUser sysUser = sysUserService.getById(userId);
|
||||
if (sysUser == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
String fieldJsonData = (String) ReflectUtil.getFieldValue(sysUser, fieldName);
|
||||
if (fieldJsonData == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
if (!BaseUpDownloader.containFile(fieldJsonData, filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
if (!storeInfo.isSupportUpload()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_IMPLEMENTED,
|
||||
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
|
||||
return;
|
||||
}
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
|
||||
SysUser.class.getSimpleName(), fieldName, filename, asImage, response);
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传操作。
|
||||
*
|
||||
* @param fieldName 上传文件名。
|
||||
* @param asImage 是否作为图片上传。如果是图片,今后下载的时候无需权限验证。否则就是附件上传,下载时需要权限验证。
|
||||
* @param uploadFile 上传文件对象。
|
||||
*/
|
||||
@OperationLog(type = SysOperationLogType.UPLOAD, saveResponse = false)
|
||||
@PostMapping("/upload")
|
||||
public void upload(
|
||||
@RequestParam String fieldName,
|
||||
@RequestParam Boolean asImage,
|
||||
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
// 这里就会判断参数中指定的字段,是否支持上传操作。
|
||||
if (!storeInfo.isSupportUpload()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
|
||||
return;
|
||||
}
|
||||
// 根据字段注解中的存储类型,通过工厂方法获取匹配的上传下载实现类,从而解耦。
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
UploadResponseInfo responseInfo = upDownloader.doUpload(appConfig.getServiceContextPath(),
|
||||
appConfig.getUploadFileBaseDir(), SysUser.class.getSimpleName(), fieldName, asImage, uploadFile);
|
||||
if (responseInfo.getUploadFailed()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
|
||||
return;
|
||||
}
|
||||
cacheHelper.putSessionUploadFile(responseInfo.getFilename());
|
||||
ResponseResult.output(ResponseResult.success(responseInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户的权限资源地址列表。同时返回详细的分配路径。
|
||||
*
|
||||
@@ -416,6 +512,20 @@ public class SysUserController extends BaseController<SysUser, SysUserVo, Long>
|
||||
return super.baseAggregateBy(aggregationParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据过滤字段和过滤集合,返回不存在的数据。主要用于微服务间远程过程调用。
|
||||
*
|
||||
* @param queryParam 查询参数。
|
||||
* @return 不存在的数据集合。
|
||||
*/
|
||||
@ApiOperation(hidden = true, value = "notExist")
|
||||
@PostMapping("/notExist")
|
||||
public ResponseResult<List<?>> notExist(@RequestBody MyQueryParam queryParam) {
|
||||
List<?> notExistIdSet = service().notExist(
|
||||
queryParam.getInFilterField(), queryParam.getInFilterValues(), true);
|
||||
return ResponseResult.success(notExistIdSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定角色Id集合的用户数据集合。
|
||||
* @param roleIds 角色Id集合。
|
||||
@@ -453,4 +563,20 @@ public class SysUserController extends BaseController<SysUser, SysUserVo, Long>
|
||||
}
|
||||
return ResponseResult.success(resultList);
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long userId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
SysUser originalSysUser = sysUserService.getById(userId);
|
||||
if (originalSysUser == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!sysUserService.remove(userId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.orangeforms.upmsapi.vo.SysUserVo;
|
||||
import com.orangeforms.upmsapi.constant.SysUserType;
|
||||
import com.orangeforms.upmsapi.constant.SysUserStatus;
|
||||
import com.orangeforms.common.core.upload.UploadStoreTypeEnum;
|
||||
import com.orangeforms.common.core.annotation.*;
|
||||
import com.orangeforms.common.core.base.model.BaseModel;
|
||||
import com.orangeforms.common.core.base.mapper.BaseModelMapper;
|
||||
@@ -64,6 +65,7 @@ public class SysUser extends BaseModel {
|
||||
/**
|
||||
* 用户头像的Url。
|
||||
*/
|
||||
@UploadFlagColumn(storeType = UploadStoreTypeEnum.LOCAL_SYSTEM)
|
||||
@TableField(value = "head_image_url")
|
||||
private String headImageUrl;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orangeforms.upmsservice.service;
|
||||
|
||||
import com.orangeforms.common.core.base.service.IBaseService;
|
||||
import com.orangeforms.common.core.object.CallResult;
|
||||
import com.orangeforms.upmsservice.model.SysPerm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -44,13 +44,22 @@ public interface SysUserService extends IBaseService<SysUser, Long> {
|
||||
boolean update(SysUser user, SysUser originalUser, Set<Long> roleIdSet, Set<Long> dataPermIdSet);
|
||||
|
||||
/**
|
||||
* 重置用户密码。
|
||||
* 修改用户密码。
|
||||
* @param userId 用户主键Id。
|
||||
* @param newPass 新密码。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean changePassword(Long userId, String newPass);
|
||||
|
||||
/**
|
||||
* 修改用户头像。
|
||||
*
|
||||
* @param userId 用户主键Id。
|
||||
* @param newHeadImage 新的头像信息。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean changeHeadImage(Long userId, String newHeadImage);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.orangeforms.upmsservice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.upmsservice.service.*;
|
||||
import com.orangeforms.upmsservice.dao.*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.orangeforms.upmsservice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.upmsservice.service.*;
|
||||
import com.orangeforms.upmsservice.dao.*;
|
||||
import com.orangeforms.upmsservice.model.*;
|
||||
@@ -158,7 +158,7 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码。
|
||||
* 修改用户密码。
|
||||
* @param userId 用户主键Id。
|
||||
* @param newPass 新密码。
|
||||
* @return 成功返回true,否则false。
|
||||
@@ -172,6 +172,15 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
|
||||
return sysUserMapper.updateById(updatedUser) == 1;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean changeHeadImage(Long userId, String newHeadImage) {
|
||||
SysUser updatedUser = new SysUser();
|
||||
updatedUser.setUserId(userId);
|
||||
updatedUser.setHeadImageUrl(newHeadImage);
|
||||
return sysUserMapper.updateById(updatedUser) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.orangeforms.upmsservice.util;
|
||||
|
||||
import com.anji.captcha.service.CaptchaCacheService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis,参考service/spring-boot代码示例。
|
||||
* 如果应用是单点的,也没有使用redis,那默认使用内存。
|
||||
* 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
|
||||
*
|
||||
* ☆☆☆ SPI: 在resources目录新建META-INF.services文件夹(两层),参考当前服务resources。
|
||||
* @author lide1202@hotmail.com
|
||||
* @date 2020-05-12
|
||||
*/
|
||||
public class CaptchaCacheServiceRedisImpl implements CaptchaCacheService {
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return "redis";
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Override
|
||||
public void set(String key, String value, long expiresInSeconds) {
|
||||
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String key) {
|
||||
return stringRedisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String key) {
|
||||
stringRedisTemplate.delete(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return stringRedisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long increment(String key, long val) {
|
||||
return stringRedisTemplate.opsForValue().increment(key,val);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.orangeforms.upmsservice.util.CaptchaCacheServiceRedisImpl
|
||||
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 39 KiB |