|
@@ -0,0 +1,618 @@
|
|
|
|
+package com.tourism.webadmin.back.controller;
|
|
|
|
+
|
|
|
|
+import cn.dev33.satoken.annotation.SaIgnore;
|
|
|
|
+import cn.dev33.satoken.session.SaSession;
|
|
|
|
+import cn.dev33.satoken.stp.StpUtil;
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
|
+import cn.hutool.core.util.BooleanUtil;
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import com.tourism.common.core.annotation.DisableDataFilter;
|
|
|
|
+import com.tourism.common.core.annotation.MyRequestBody;
|
|
|
|
+import com.tourism.common.core.constant.ApplicationConstant;
|
|
|
|
+import com.tourism.common.core.constant.ErrorCodeEnum;
|
|
|
|
+import com.tourism.common.core.object.LoginUserInfo;
|
|
|
|
+import com.tourism.common.core.object.ResponseResult;
|
|
|
|
+import com.tourism.common.core.object.TokenData;
|
|
|
|
+import com.tourism.common.core.upload.BaseUpDownloader;
|
|
|
|
+import com.tourism.common.core.upload.UpDownloaderFactory;
|
|
|
|
+import com.tourism.common.core.upload.UploadStoreInfo;
|
|
|
|
+import com.tourism.common.core.util.*;
|
|
|
|
+import com.tourism.common.flow.online.service.FlowOnlineOperationService;
|
|
|
|
+import com.tourism.common.log.annotation.OperationLog;
|
|
|
|
+import com.tourism.common.log.model.constant.SysOperationLogType;
|
|
|
|
+import com.tourism.common.mobile.model.MobileEntry;
|
|
|
|
+import com.tourism.common.online.service.OnlineOperationService;
|
|
|
|
+import com.tourism.common.redis.cache.SessionCacheHelper;
|
|
|
|
+import com.tourism.common.report.service.ReportOperationService;
|
|
|
|
+import com.tourism.common.satoken.util.SaTokenUtil;
|
|
|
|
+import com.tourism.webadmin.back.service.SmsService;
|
|
|
|
+import com.tourism.webadmin.config.ApplicationConfig;
|
|
|
|
+import com.tourism.webadmin.upms.dto.SysUserWebDto;
|
|
|
|
+import com.tourism.webadmin.upms.model.*;
|
|
|
|
+import com.tourism.webadmin.upms.model.constant.SysMenuType;
|
|
|
|
+import com.tourism.webadmin.upms.model.constant.SysOnlineMenuPermType;
|
|
|
|
+import com.tourism.webadmin.upms.model.constant.SysUserStatus;
|
|
|
|
+import com.tourism.webadmin.upms.service.*;
|
|
|
|
+import io.swagger.v3.oas.annotations.tags.Tag;
|
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
|
+import lombok.Data;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.redisson.api.RSet;
|
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.security.crypto.password.PasswordEncoder;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+import org.springframework.util.ObjectUtils;
|
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
|
+
|
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
|
+import java.net.URLDecoder;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 登录接口控制器类。
|
|
|
|
+ *
|
|
|
|
+ * @author 吃饭睡觉
|
|
|
|
+ * @date 2024-09-06
|
|
|
|
+ */
|
|
|
|
+@Tag(name = "网页用户登录接口")
|
|
|
|
+@DisableDataFilter
|
|
|
|
+@Slf4j
|
|
|
|
+@RestController
|
|
|
|
+@RequestMapping("/admin/web/login")
|
|
|
|
+public class LoginToWebController {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private SysUserWebService sysUserWebService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private SysDataPermService sysDataPermService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private OnlineOperationService onlineOperationService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private FlowOnlineOperationService flowOnlineOperationService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private ReportOperationService reportOperationService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private ApplicationConfig appConfig;
|
|
|
|
+ @Autowired
|
|
|
|
+ private RedissonClient redissonClient;
|
|
|
|
+ @Autowired
|
|
|
|
+ private SessionCacheHelper cacheHelper;
|
|
|
|
+ @Autowired
|
|
|
|
+ private PasswordEncoder passwordEncoder;
|
|
|
|
+ @Autowired
|
|
|
|
+ private UpDownloaderFactory upDownloaderFactory;
|
|
|
|
+ @Autowired
|
|
|
|
+ private SaTokenUtil saTokenUtil;
|
|
|
|
+ @Autowired
|
|
|
|
+ private SmsService smsService;
|
|
|
|
+
|
|
|
|
+ private static final String IS_ADMIN = "isAdmin";
|
|
|
|
+ private static final String SHOW_NAME_FIELD = "showName";
|
|
|
|
+ private static final String SHOW_ORDER_FIELD = "showOrder";
|
|
|
|
+ private static final String HEAD_IMAGE_URL_FIELD = "headImageUrl";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 用户注册
|
|
|
|
+ * @return
|
|
|
|
+ * @throws UnsupportedEncodingException
|
|
|
|
+ */
|
|
|
|
+ @SaIgnore
|
|
|
|
+ @OperationLog(type = SysOperationLogType.Register, saveResponse = false)
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
+ @PostMapping("/doRegister")
|
|
|
|
+ public ResponseResult doRegister(@RequestBody SysUserWebDto sysUserWebDto) {
|
|
|
|
+
|
|
|
|
+ if (MyCommonUtil.existBlankArgument(sysUserWebDto.getLoginName(), sysUserWebDto.getPassword())) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 验证短信验证码
|
|
|
|
+ if (!smsService.validateSmsCode(sysUserWebDto.getSmsCode(),sysUserWebDto.getMobile())) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.SMSCODE_ERR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //存储用户信息
|
|
|
|
+ SysUserWeb sysUserWeb = new SysUserWeb();
|
|
|
|
+ BeanUtil.copyProperties(sysUserWebDto,sysUserWeb);
|
|
|
|
+ sysUserWebService.saveNew(sysUserWeb);
|
|
|
|
+
|
|
|
|
+ return ResponseResult.success();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private ResponseResult<SysUserWeb> verifyAndHandleLoginUser(
|
|
|
|
+ String loginName, String password) throws UnsupportedEncodingException {
|
|
|
|
+ String errorMessage;
|
|
|
|
+ SysUserWeb user = sysUserWebService.getSysUserByLoginName(loginName);
|
|
|
|
+ password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
|
|
|
|
+
|
|
|
|
+ // NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。
|
|
|
|
+ // 执行RsaUtil工具类中的main函数,可以生成新的公钥和私钥。
|
|
|
|
+ password = RsaUtil.decrypt(password, ApplicationConstant.PRIVATE_KEY);
|
|
|
|
+ if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
|
|
|
+ }
|
|
|
|
+ if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) {
|
|
|
|
+ errorMessage = "登录失败,用户账号被锁定!";
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage);
|
|
|
|
+ }
|
|
|
|
+ if (BooleanUtil.isTrue(appConfig.getExcludeLogin())) {
|
|
|
|
+ String deviceType = MyCommonUtil.getDeviceTypeWithString();
|
|
|
|
+ LoginUserInfo userInfo = BeanUtil.copyProperties(user, LoginUserInfo.class);
|
|
|
|
+ String loginId = SaTokenUtil.makeLoginIdByWeb(userInfo);
|
|
|
|
+ StpUtil.kickout(loginId, deviceType);
|
|
|
|
+ }
|
|
|
|
+ return ResponseResult.success(user);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 登录接口。
|
|
|
|
+ *
|
|
|
|
+ * @param loginName 登录名。
|
|
|
|
+ * @param password 密码。
|
|
|
|
+ * @return 应答结果对象,其中包括Token数据,以及菜单列表。
|
|
|
|
+ */
|
|
|
|
+ @SaIgnore
|
|
|
|
+ @OperationLog(type = SysOperationLogType.LOGIN_WEB, saveResponse = false)
|
|
|
|
+ @PostMapping("/doLogin")
|
|
|
|
+ public ResponseResult<JSONObject> doLogin(
|
|
|
|
+ @MyRequestBody String loginName,
|
|
|
|
+ @MyRequestBody String password) throws UnsupportedEncodingException {
|
|
|
|
+ if (MyCommonUtil.existBlankArgument(loginName, password)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+ }
|
|
|
|
+ ResponseResult<SysUserWeb> verifyResult = this.verifyAndHandleLoginUser(loginName, password);
|
|
|
|
+ if (!verifyResult.isSuccess()) {
|
|
|
|
+ return ResponseResult.errorFrom(verifyResult);
|
|
|
|
+ }
|
|
|
|
+ JSONObject jsonData = this.buildLoginDataAndLogin(verifyResult.getData());
|
|
|
|
+ return ResponseResult.success(jsonData);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 手机号登录接口。
|
|
|
|
+ * @return 应答结果对象,其中包括Token数据,以及菜单列表。
|
|
|
|
+ */
|
|
|
|
+ @SaIgnore
|
|
|
|
+ @OperationLog(type = SysOperationLogType.LOGIN_WEB, saveResponse = false)
|
|
|
|
+ @PostMapping("/doLoginByPhone")
|
|
|
|
+ public ResponseResult<JSONObject> doLoginByPhone(
|
|
|
|
+ @MyRequestBody String mobile,
|
|
|
|
+ @MyRequestBody String smsCode) throws UnsupportedEncodingException {
|
|
|
|
+ String errorMessage;
|
|
|
|
+ if (MyCommonUtil.existBlankArgument(mobile, smsCode)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+ }
|
|
|
|
+ //查询手机号是否存在
|
|
|
|
+ SysUserWeb sysUserByMobile = sysUserWebService.getSysUserByMobile(mobile);
|
|
|
|
+ if (ObjectUtils.isEmpty(sysUserByMobile)){
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.INVALID_MOBILE_CODE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 验证短信验证码
|
|
|
|
+ if (!smsService.validateSmsCode(smsCode,mobile)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.SMSCODE_ERR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sysUserByMobile.getUserStatus() == SysUserStatus.STATUS_LOCKED) {
|
|
|
|
+ errorMessage = "登录失败,用户账号被锁定!";
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage);
|
|
|
|
+ }
|
|
|
|
+ if (BooleanUtil.isTrue(appConfig.getExcludeLogin())) {
|
|
|
|
+ String deviceType = MyCommonUtil.getDeviceTypeWithString();
|
|
|
|
+ LoginUserInfo userInfo = BeanUtil.copyProperties(sysUserByMobile, LoginUserInfo.class);
|
|
|
|
+ String loginId = SaTokenUtil.makeLoginIdByWeb(userInfo);
|
|
|
|
+ StpUtil.kickout(loginId, deviceType);
|
|
|
|
+ }
|
|
|
|
+ JSONObject jsonData = this.buildLoginDataAndLogin(sysUserByMobile);
|
|
|
|
+ return ResponseResult.success(jsonData);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 登录移动端接口。
|
|
|
|
+ *
|
|
|
|
+ * @param loginName 登录名。
|
|
|
|
+ * @param password 密码。
|
|
|
|
+ * @return 应答结果对象,其中包括Token数据,以及菜单列表。
|
|
|
|
+ */
|
|
|
|
+// @Parameter(name = "loginName", example = "admin")
|
|
|
|
+// @Parameter(name = "password", example = "IP3ccke3GhH45iGHB5qP9p7iZw6xUyj28Ju10rnBiPKOI35sc%2BjI7%2FdsjOkHWMfUwGYGfz8ik31HC2Ruk%2Fhkd9f6RPULTHj7VpFdNdde2P9M4mQQnFBAiPM7VT9iW3RyCtPlJexQ3nAiA09OqG%2F0sIf1kcyveSrulxembARDbDo%3D")
|
|
|
|
+// @SaIgnore
|
|
|
|
+// @OperationLog(type = SysOperationLogType.LOGIN_MOBILE, saveResponse = false)
|
|
|
|
+// @PostMapping("/doMobileLogin")
|
|
|
|
+// public ResponseResult<JSONObject> doMobileLogin(
|
|
|
|
+// @MyRequestBody String loginName,
|
|
|
|
+// @MyRequestBody String password) throws UnsupportedEncodingException {
|
|
|
|
+// if (MyCommonUtil.existBlankArgument(loginName, password)) {
|
|
|
|
+// return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+// }
|
|
|
|
+// ResponseResult<SysUser> verifyResult = this.verifyAndHandleLoginUser(loginName, password);
|
|
|
|
+// if (!verifyResult.isSuccess()) {
|
|
|
|
+// return ResponseResult.errorFrom(verifyResult);
|
|
|
|
+// }
|
|
|
|
+// JSONObject jsonData = this.buildMobileLoginDataAndLogin(verifyResult.getData());
|
|
|
|
+// return ResponseResult.success(jsonData);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 登出操作。同时将Session相关的信息从缓存中删除。
|
|
|
|
+ *
|
|
|
|
+ * @return 应答结果对象。
|
|
|
|
+ */
|
|
|
|
+ @OperationLog(type = SysOperationLogType.LOGOUT)
|
|
|
|
+ @PostMapping("/doLogout")
|
|
|
|
+ public ResponseResult<Void> doLogout() {
|
|
|
|
+ String sessionId = TokenData.takeFromRequest().getSessionId();
|
|
|
|
+ redissonClient.getBucket(TokenData.takeFromRequest().getMySessionId()).deleteAsync();
|
|
|
|
+ redissonClient.getBucket(RedisKeyUtil.makeSessionPermCodeKey(sessionId)).deleteAsync();
|
|
|
|
+ redissonClient.getBucket(RedisKeyUtil.makeSessionPermIdKey(sessionId)).deleteAsync();
|
|
|
|
+ sysDataPermService.removeDataPermCache(sessionId);
|
|
|
|
+ cacheHelper.removeAllSessionCache(sessionId);
|
|
|
|
+ StpUtil.logout();
|
|
|
|
+ return ResponseResult.success();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 在登录之后,通过token再次获取登录信息。
|
|
|
|
+ * 用于在当前浏览器登录系统后,在新tab页中可以免密登录。
|
|
|
|
+ *
|
|
|
|
+ * @return 应答结果对象,其中包括JWT的Token数据,以及菜单列表。
|
|
|
|
+ */
|
|
|
|
+ @GetMapping("/getLoginInfo")
|
|
|
|
+ public ResponseResult<JSONObject> getLoginInfo() {
|
|
|
|
+ TokenData tokenData = TokenData.takeFromRequest();
|
|
|
|
+ JSONObject jsonData = new JSONObject();
|
|
|
|
+ jsonData.put(SHOW_NAME_FIELD, tokenData.getShowName());
|
|
|
|
+ jsonData.put(IS_ADMIN, tokenData.getIsAdmin());
|
|
|
|
+ if (StrUtil.isNotBlank(tokenData.getHeadImageUrl())) {
|
|
|
|
+ jsonData.put(HEAD_IMAGE_URL_FIELD, tokenData.getHeadImageUrl());
|
|
|
|
+ }
|
|
|
|
+ return ResponseResult.success(jsonData);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 用户修改自己的密码。
|
|
|
|
+ *
|
|
|
|
+ * @param oldPass 原有密码。
|
|
|
|
+ * @param newPass 新密码。
|
|
|
|
+ * @return 应答结果对象。
|
|
|
|
+ */
|
|
|
|
+ @PostMapping("/changePassword")
|
|
|
|
+ public ResponseResult<Void> changePassword(
|
|
|
|
+ @MyRequestBody String oldPass, @MyRequestBody String newPass) throws UnsupportedEncodingException {
|
|
|
|
+ //校验密码是否为空
|
|
|
|
+ if (MyCommonUtil.existBlankArgument(newPass, oldPass)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ TokenData tokenData = TokenData.takeFromRequest();
|
|
|
|
+ SysUserWeb user = sysUserWebService.getById(tokenData.getUserId());
|
|
|
|
+ oldPass = URLDecoder.decode(oldPass, StandardCharsets.UTF_8.name());
|
|
|
|
+ // NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。
|
|
|
|
+ // 执行RsaUtil工具类中的main函数,可以生成新的公钥和私钥。
|
|
|
|
+ oldPass = RsaUtil.decrypt(oldPass, ApplicationConstant.PRIVATE_KEY);
|
|
|
|
+ if (user == null || !passwordEncoder.matches(oldPass, user.getPassword())) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
|
|
|
+ }
|
|
|
|
+ newPass = URLDecoder.decode(newPass, StandardCharsets.UTF_8.name());
|
|
|
|
+ newPass = RsaUtil.decrypt(newPass, ApplicationConstant.PRIVATE_KEY);
|
|
|
|
+ if (!sysUserWebService.changePassword(tokenData.getUserId(), newPass)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
|
|
|
+ }
|
|
|
|
+ return ResponseResult.success();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 忘记密码。
|
|
|
|
+ * @return 应答结果对象。
|
|
|
|
+ */
|
|
|
|
+ @PostMapping("/findPassword")
|
|
|
|
+ public ResponseResult<String> findPassword(
|
|
|
|
+ @MyRequestBody String smsCode, @MyRequestBody String mobile) throws UnsupportedEncodingException {
|
|
|
|
+ //校验是否为空
|
|
|
|
+ if (MyCommonUtil.existBlankArgument(smsCode, mobile)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SysUserWeb sysUserByMobile = sysUserWebService.getSysUserByMobile(mobile);
|
|
|
|
+// if (ObjectUtils.isEmpty(sysUserByMobile)){
|
|
|
|
+// return ResponseResult.error(ErrorCodeEnum.INVALID_MOBILE_CODE);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ // 验证短信验证码
|
|
|
|
+ if (!smsService.validateSmsCode(smsCode,mobile)) {
|
|
|
|
+ return ResponseResult.error(ErrorCodeEnum.SMSCODE_ERR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ResponseResult.success(sysUserByMobile.getPassword());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 上传并修改用户头像。
|
|
|
|
+ *
|
|
|
|
+ * @param uploadFile 上传的头像文件。
|
|
|
|
+ */
|
|
|
|
+// @PostMapping("/changeHeadImage")
|
|
|
|
+// public void changeHeadImage(@RequestParam("uploadFile") MultipartFile uploadFile) throws IOException {
|
|
|
|
+// UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, HEAD_IMAGE_URL_FIELD);
|
|
|
|
+// BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
|
|
|
+// UploadResponseInfo responseInfo = upDownloader.doUpload(null,
|
|
|
|
+// appConfig.getUploadFileBaseDir(), SysUser.class.getSimpleName(), HEAD_IMAGE_URL_FIELD, true, uploadFile);
|
|
|
|
+// if (BooleanUtil.isTrue(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 {
|
|
|
|
+ UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, HEAD_IMAGE_URL_FIELD);
|
|
|
|
+ BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
|
|
|
+ upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
|
|
|
|
+ SysUser.class.getSimpleName(), HEAD_IMAGE_URL_FIELD, filename, true, response);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// private ResponseResult<SysUser> verifyAndHandleLoginUser(
|
|
|
|
+// String loginName, String password) throws UnsupportedEncodingException {
|
|
|
|
+// String errorMessage;
|
|
|
|
+// SysUser user = sysUserService.getSysUserByLoginName(loginName);
|
|
|
|
+// password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
|
|
|
|
+// // NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。
|
|
|
|
+// // 执行RsaUtil工具类中的main函数,可以生成新的公钥和私钥。
|
|
|
|
+// password = RsaUtil.decrypt(password, ApplicationConstant.PRIVATE_KEY);
|
|
|
|
+// if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
|
|
|
|
+// return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
|
|
|
+// }
|
|
|
|
+// if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) {
|
|
|
|
+// errorMessage = "登录失败,用户账号被锁定!";
|
|
|
|
+// return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage);
|
|
|
|
+// }
|
|
|
|
+// if (BooleanUtil.isTrue(appConfig.getExcludeLogin())) {
|
|
|
|
+// String deviceType = MyCommonUtil.getDeviceTypeWithString();
|
|
|
|
+// LoginUserInfo userInfo = BeanUtil.copyProperties(user, LoginUserInfo.class);
|
|
|
|
+// String loginId = SaTokenUtil.makeLoginId(userInfo);
|
|
|
|
+// StpUtil.kickout(loginId, deviceType);
|
|
|
|
+// }
|
|
|
|
+// return ResponseResult.success(user);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ private JSONObject buildLoginDataAndLogin(SysUserWeb user) {
|
|
|
|
+ TokenData tokenData = this.loginAndCreateToken(user);
|
|
|
|
+ // 这里手动将TokenData存入request,便于OperationLogAspect统一处理操作日志。
|
|
|
|
+ TokenData.addToRequest(tokenData);
|
|
|
|
+ JSONObject jsonData = this.createResponseData(user);
|
|
|
|
+ Collection<SysMenu> allMenuList;
|
|
|
|
+ return jsonData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private JSONObject buildMobileLoginDataAndLogin(SysUserWeb user) {
|
|
|
|
+ TokenData tokenData = this.loginAndCreateToken(user);
|
|
|
|
+ // 这里手动将TokenData存入request,便于OperationLogAspect统一处理操作日志。
|
|
|
|
+ TokenData.addToRequest(tokenData);
|
|
|
|
+ JSONObject jsonData = this.createResponseData(user);
|
|
|
|
+ List<MobileEntry> mobileEntryList;
|
|
|
|
+
|
|
|
|
+ return jsonData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private TokenData loginAndCreateToken(SysUserWeb user) {
|
|
|
|
+ String deviceType = MyCommonUtil.getDeviceTypeWithString();
|
|
|
|
+ LoginUserInfo userInfo = BeanUtil.copyProperties(user, LoginUserInfo.class);
|
|
|
|
+ String loginId = SaTokenUtil.makeLoginIdByWeb(userInfo);
|
|
|
|
+ StpUtil.login(loginId, deviceType);
|
|
|
|
+ SaSession session = StpUtil.getTokenSession();
|
|
|
|
+ TokenData tokenData = this.buildTokenData(user, session.getId(), StpUtil.getLoginDevice());
|
|
|
|
+ String mySessionId = RedisKeyUtil.getSessionIdPrefix(tokenData, user.getLoginName()) + MyCommonUtil.generateUuid();
|
|
|
|
+ tokenData.setMySessionId(mySessionId);
|
|
|
|
+ tokenData.setToken(session.getToken());
|
|
|
|
+ redissonClient.getBucket(mySessionId)
|
|
|
|
+ .set(JSON.toJSONString(tokenData), appConfig.getSessionExpiredSeconds(), TimeUnit.SECONDS);
|
|
|
|
+ session.set(TokenData.REQUEST_ATTRIBUTE_NAME, tokenData);
|
|
|
|
+ return tokenData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private JSONObject createResponseData(SysUserWeb user) {
|
|
|
|
+ JSONObject jsonData = new JSONObject();
|
|
|
|
+ jsonData.put(TokenData.REQUEST_ATTRIBUTE_NAME, StpUtil.getTokenValue());
|
|
|
|
+ jsonData.put(SHOW_NAME_FIELD, user.getShowName());
|
|
|
|
+ if (StrUtil.isNotBlank(user.getHeadImageUrl())) {
|
|
|
|
+ jsonData.put(HEAD_IMAGE_URL_FIELD, user.getHeadImageUrl());
|
|
|
|
+ }
|
|
|
|
+ return jsonData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void appendResponseMenuAndPermCodeData(
|
|
|
|
+ JSONObject responseData, Collection<SysMenu> allMenuList, Collection<String> menuCodeList) {
|
|
|
|
+ allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getExtraObject() != null && StrUtil.isNotBlank(m.getExtraObject().getMenuCode()))
|
|
|
|
+ .forEach(m -> CollUtil.addAll(menuCodeList, m.getExtraObject().getMenuCode()));
|
|
|
|
+ List<SysMenu> menuList = allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getMenuType() <= SysMenuType.TYPE_MENU).collect(Collectors.toList());
|
|
|
|
+ responseData.put("menuList", menuList);
|
|
|
|
+ responseData.put("permCodeList", menuCodeList);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private TokenData buildTokenData(SysUserWeb user, String sessionId, String deviceType) {
|
|
|
|
+ TokenData tokenData = new TokenData();
|
|
|
|
+ tokenData.setSessionId(sessionId);
|
|
|
|
+ tokenData.setUserId(user.getUserId());
|
|
|
|
+ tokenData.setLoginName(user.getLoginName());
|
|
|
|
+ tokenData.setShowName(user.getShowName());
|
|
|
|
+ tokenData.setLoginIp(IpUtil.getRemoteIpAddress(ContextUtil.getHttpRequest()));
|
|
|
|
+ tokenData.setLoginTime(new Date());
|
|
|
|
+ tokenData.setDeviceType(deviceType);
|
|
|
|
+ tokenData.setHeadImageUrl(user.getHeadImageUrl());
|
|
|
|
+ return tokenData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void putUserSysPermCache(String sessionId, Collection<String> permUrlSet) {
|
|
|
|
+ if (CollUtil.isEmpty(permUrlSet)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String sessionPermKey = RedisKeyUtil.makeSessionPermIdKey(sessionId);
|
|
|
|
+ RSet<String> redisPermSet = redissonClient.getSet(sessionPermKey);
|
|
|
|
+ redisPermSet.addAll(permUrlSet);
|
|
|
|
+ redisPermSet.expire(appConfig.getSessionExpiredSeconds(), TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void putUserSysPermCodeCache(String sessionId, Collection<String> permCodeSet) {
|
|
|
|
+ if (CollUtil.isEmpty(permCodeSet)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String sessionPermCodeKey = RedisKeyUtil.makeSessionPermCodeKey(sessionId);
|
|
|
|
+ RSet<String> redisPermSet = redissonClient.getSet(sessionPermCodeKey);
|
|
|
|
+ redisPermSet.addAll(permCodeSet);
|
|
|
|
+ redisPermSet.expire(appConfig.getSessionExpiredSeconds(), TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private OnlinePermData getOnlineMenuPermData(Collection<SysMenu> allMenuList) {
|
|
|
|
+ List<SysMenu> onlineMenuList = allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getOnlineFormId() != null && m.getMenuType().equals(SysMenuType.TYPE_BUTTON))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ if (CollUtil.isEmpty(onlineMenuList)) {
|
|
|
|
+ return new OnlinePermData();
|
|
|
|
+ }
|
|
|
|
+ Set<Long> formIds = allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getOnlineFormId() != null
|
|
|
|
+ && m.getOnlineFlowEntryId() == null
|
|
|
|
+ && m.getMenuType().equals(SysMenuType.TYPE_MENU))
|
|
|
|
+ .map(SysMenu::getOnlineFormId)
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
+ Set<Long> viewFormIds = onlineMenuList.stream()
|
|
|
|
+ .filter(m -> m.getOnlineMenuPermType() == SysOnlineMenuPermType.TYPE_VIEW)
|
|
|
|
+ .map(SysMenu::getOnlineFormId)
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
+ Set<Long> editFormIds = onlineMenuList.stream()
|
|
|
|
+ .filter(m -> m.getOnlineMenuPermType() == SysOnlineMenuPermType.TYPE_EDIT)
|
|
|
|
+ .map(SysMenu::getOnlineFormId)
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
+ Map<String, Object> permDataMap =
|
|
|
|
+ onlineOperationService.calculatePermData(formIds, viewFormIds, editFormIds);
|
|
|
|
+ OnlinePermData permData = BeanUtil.mapToBean(permDataMap, OnlinePermData.class, false, null);
|
|
|
|
+ permData.permUrlSet.addAll(permData.onlineWhitelistUrls);
|
|
|
|
+ return permData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private OnlinePermData getFlowOnlineMenuPermData(Collection<SysMenu> allMenuList) {
|
|
|
|
+ List<SysMenu> flowOnlineMenuList = allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getOnlineFlowEntryId() != null).collect(Collectors.toList());
|
|
|
|
+ Set<Long> entryIds = flowOnlineMenuList.stream()
|
|
|
|
+ .map(SysMenu::getOnlineFlowEntryId).collect(Collectors.toSet());
|
|
|
|
+ List<Map<String, Object>> flowPermDataList = flowOnlineOperationService.calculatePermData(entryIds);
|
|
|
|
+ List<OnlineFlowPermData> flowOnlinePermDataList =
|
|
|
|
+ MyModelUtil.mapToBeanList(flowPermDataList, OnlineFlowPermData.class);
|
|
|
|
+ OnlinePermData permData = new OnlinePermData();
|
|
|
|
+ flowOnlinePermDataList.forEach(perm -> {
|
|
|
|
+ permData.permCodeSet.addAll(perm.getPermCodeList());
|
|
|
|
+ permData.permUrlSet.addAll(perm.getPermList());
|
|
|
|
+ });
|
|
|
|
+ return permData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Set<String> getReportMenuPermData(Collection<SysMenu> allMenuList) {
|
|
|
|
+ Set<String> permSet = new HashSet<>();
|
|
|
|
+ List<SysMenu> reportMenuList = allMenuList.stream()
|
|
|
|
+ .filter(m -> m.getReportPageId() != null).collect(Collectors.toList());
|
|
|
|
+ if (CollUtil.isEmpty(reportMenuList)) {
|
|
|
|
+ return permSet;
|
|
|
|
+ }
|
|
|
|
+ Set<Long> pageIds = reportMenuList.stream().map(SysMenu::getReportPageId).collect(Collectors.toSet());
|
|
|
|
+ Map<Long, Set<String>> reportPermDataMap = reportOperationService.calculatePermData(pageIds);
|
|
|
|
+ for (Long pageId : pageIds) {
|
|
|
|
+ CollUtil.addAll(permSet, reportPermDataMap.get(pageId));
|
|
|
|
+ }
|
|
|
|
+ return permSet;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Set<String> getOnlineMobileEntryPermData(Collection<MobileEntry> mobileEntryList) {
|
|
|
|
+ List<MobileEntry> onlineMobileEntryList = mobileEntryList.stream()
|
|
|
|
+ .filter(m -> m.getExtraObject() != null
|
|
|
|
+ && m.getExtraObject().getOnlineFormId() != null
|
|
|
|
+ && m.getExtraObject().getOnlineFlowEntryId() == null)
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ if (CollUtil.isEmpty(onlineMobileEntryList)) {
|
|
|
|
+ return CollUtil.newHashSet();
|
|
|
|
+ }
|
|
|
|
+ Set<Long> onlineFormIds = onlineMobileEntryList.stream()
|
|
|
|
+ .map(m -> m.getExtraObject().getOnlineFormId()).collect(Collectors.toSet());
|
|
|
|
+ Map<String, Object> permDataMap =
|
|
|
|
+ onlineOperationService.calculatePermData(onlineFormIds, onlineFormIds, onlineFormIds);
|
|
|
|
+ OnlinePermData permData = BeanUtil.mapToBean(permDataMap, OnlinePermData.class, false, null);
|
|
|
|
+ permData.permUrlSet.addAll(permData.onlineWhitelistUrls);
|
|
|
|
+ return permData.permUrlSet;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Set<String> getFlowOnlineMobileEntryPermData(Collection<MobileEntry> mobileEntryList) {
|
|
|
|
+ List<MobileEntry> flowOnlineMobileEntryList = mobileEntryList.stream()
|
|
|
|
+ .filter(m -> m.getExtraData() != null && m.getExtraObject().getOnlineFlowEntryId() != null)
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ Set<Long> entryIds = flowOnlineMobileEntryList.stream()
|
|
|
|
+ .map(m -> m.getExtraObject().getOnlineFlowEntryId()).collect(Collectors.toSet());
|
|
|
|
+ List<Map<String, Object>> flowPermDataList = flowOnlineOperationService.calculatePermData(entryIds);
|
|
|
|
+ List<OnlineFlowPermData> flowOnlinePermDataList =
|
|
|
|
+ MyModelUtil.mapToBeanList(flowPermDataList, OnlineFlowPermData.class);
|
|
|
|
+ Set<String> permSet = new HashSet<>();
|
|
|
|
+ flowOnlinePermDataList.forEach(perm -> permSet.addAll(perm.getPermList()));
|
|
|
|
+ return permSet;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Set<String> getReportMobileEntryPermData(Collection<MobileEntry> mobileEntryList) {
|
|
|
|
+ Set<String> permSet = new HashSet<>();
|
|
|
|
+ List<MobileEntry> reportMobileEntryList = mobileEntryList.stream()
|
|
|
|
+ .filter(m -> m.getExtraObject() != null && m.getExtraObject().getReportPageId() != null)
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ if (CollUtil.isEmpty(reportMobileEntryList)) {
|
|
|
|
+ return permSet;
|
|
|
|
+ }
|
|
|
|
+ Set<Long> pageIds = reportMobileEntryList.stream()
|
|
|
|
+ .map(m -> m.getExtraObject().getReportPageId()).collect(Collectors.toSet());
|
|
|
|
+ Map<Long, Set<String>> reportPermDataMap = reportOperationService.calculatePermData(pageIds);
|
|
|
|
+ for (Long pageId : pageIds) {
|
|
|
|
+ CollUtil.addAll(permSet, reportPermDataMap.get(pageId));
|
|
|
|
+ }
|
|
|
|
+ return permSet;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static class OnlinePermData {
|
|
|
|
+ public final Set<String> permCodeSet = new HashSet<>();
|
|
|
|
+ public final Set<String> permUrlSet = new HashSet<>();
|
|
|
|
+ public final List<String> onlineWhitelistUrls = new LinkedList<>();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Data
|
|
|
|
+ static class OnlineFlowPermData {
|
|
|
|
+ private List<String> permCodeList;
|
|
|
|
+ private List<String> permList;
|
|
|
|
+ }
|
|
|
|
+}
|