package com.qmth.distributed.print.api; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qmth.boot.api.annotation.Aac; import com.qmth.boot.api.annotation.BOOL; import com.qmth.boot.api.constant.ApiConstant; import com.qmth.boot.api.exception.ApiException; import com.qmth.boot.core.enums.Platform; import com.qmth.boot.tools.signature.SignatureType; import com.qmth.distributed.print.business.bean.auth.AuthBean; import com.qmth.distributed.print.business.bean.auth.ExpireTimeBean; import com.qmth.distributed.print.business.bean.params.LoginParam; import com.qmth.distributed.print.business.bean.result.EditResult; import com.qmth.distributed.print.business.bean.result.LoginResult; import com.qmth.distributed.print.business.config.DictionaryConfig; import com.qmth.distributed.print.business.entity.*; import com.qmth.distributed.print.business.enums.DownloadFileEnum; import com.qmth.distributed.print.business.enums.RoleTypeEnum; import com.qmth.distributed.print.business.enums.UploadFileEnum; import com.qmth.distributed.print.business.service.*; import com.qmth.distributed.print.business.util.AuthUtil; import com.qmth.distributed.print.business.util.RedisUtil; import com.qmth.distributed.print.business.util.ServletUtil; import com.qmth.distributed.print.business.util.security.Md5Utils; import com.qmth.distributed.print.common.SignatureEntityTest; import com.qmth.distributed.print.common.contant.SystemConstant; import com.qmth.distributed.print.common.enums.ExceptionResultEnum; import com.qmth.distributed.print.common.util.Result; import com.qmth.distributed.print.common.util.ResultUtil; import com.qmth.distributed.print.common.util.SessionUtil; import io.swagger.annotations.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.validation.Valid; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.stream.Collectors; /** * @Date: 2021/3/30. */ @Api(tags = "系统Controller") @RestController @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.common}") @Aac(strict = BOOL.TRUE, platform = Platform.WEB) public class SysController { private final static Logger log = LoggerFactory.getLogger(SysController.class); @Autowired private SysUserService sysUserService; @Autowired private BasicVerifyCodeService basicVerifyCodeService; @Autowired private DictionaryConfig dictionaryConfig; @Resource CacheService cacheService; @Resource TBSessionService tbSessionService; @Resource RedisUtil redisUtil; @Resource CommonService commonService; @Resource TBTaskService tbTaskService; @Resource BasicAttachmentService basicAttachmentService; @Autowired private SysConfigService sysConfigService; /** * 登录 * * @param login * @return */ @ApiOperation(value = "登录") @RequestMapping(value = "/login", method = RequestMethod.POST) @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = LoginResult.class)}) @Aac(auth = BOOL.FALSE) public Result login(@ApiParam(value = "用户信息", required = true) @Valid @RequestBody LoginParam login, BindingResult bindingResult) throws NoSuchAlgorithmException { if (bindingResult.hasErrors()) { return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage()); } BasicSchool basicSchool = null; if (!Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) { basicSchool = cacheService.schoolCache(login.getSchoolCode()); if (Objects.isNull(basicSchool)) { throw ExceptionResultEnum.SCHOOL_NO_DATA.exception(); } if (Objects.nonNull(basicSchool.getEnable()) && !basicSchool.getEnable()) { throw ExceptionResultEnum.SCHOOL_ENABLE.exception(); } } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().eq(SysUser::getLoginName, login.getLoginName()); if (!Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) { wrapper.lambda().eq(SysUser::getSchoolId, basicSchool.getId()); } List userList = sysUserService.list(wrapper); //用户不存在 if (Objects.isNull(userList) || userList.size() == 0) { throw ExceptionResultEnum.USER_NO_DATA.exception(); } if (Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) { userList.forEach(o -> { AuthBean authBean = commonService.getUserAuth(o.getId()); if (Objects.nonNull(authBean) && Objects.nonNull(authBean.getRoleList()) && authBean.getRoleList().size() > 0) { Set roleType = authBean.getRoleList().stream().map(s -> s.getType()).collect(Collectors.toSet()); if (!roleType.contains(RoleTypeEnum.ADMIN)) { throw ExceptionResultEnum.ERROR.exception("学校代码为admin只允许超级管理员登录"); } } }); } if (userList.size() > 1) { throw ExceptionResultEnum.ERROR.exception("查询的用户有多条"); } SysUser sysUser = userList.get(0); if (Objects.nonNull(sysUser.getSchoolId()) && sysUser.getSchoolId().longValue() != basicSchool.getId().longValue()) { throw ExceptionResultEnum.ERROR.exception("用户学校不匹配"); } //密码不正确 if (!Objects.equals(login.getPassword(), sysUser.getPassword())) { throw ExceptionResultEnum.PASSWORD_ERROR.exception(); } //停用 if (!sysUser.getEnable()) { throw ExceptionResultEnum.USER_ENABLE.exception(); } // 校验验证码 SysConfig value = sysConfigService.getByKey("sys.code.enable"); if (Objects.nonNull(value) && value.getConfigValue().equals("true")) { String code = login.getCode(); if (Objects.isNull(code)) { throw ExceptionResultEnum.ERROR.exception("验证码为空"); } if (!dictionaryConfig.smsDomain().getSmsNormalCode().equals(code)) { QueryWrapper codeWrapper = new QueryWrapper<>(); codeWrapper.lambda().eq(BasicVerifyCode::getMobileNumber, sysUser.getMobileNumber()).eq(BasicVerifyCode::getUserId, sysUser.getId()); BasicVerifyCode accessControl = basicVerifyCodeService.getOne(codeWrapper); if (accessControl == null || (accessControl != null && !accessControl.getVerifyCode().equals(code))) { throw ExceptionResultEnum.ERROR.exception("短信验证码错误,请仔细核对后再次输入"); } if (new Date(accessControl.getExpireTime()).before(new Date())) { throw ExceptionResultEnum.ERROR.exception("短信验证码已过期"); } } } Platform platform = ServletUtil.getRequestPlatform(); String deviceId = ServletUtil.getRequestDeviceId(); //添加用户鉴权缓存 AuthBean authBean = cacheService.userAuthCache(sysUser.getId()); if (Objects.isNull(authBean)) { throw ExceptionResultEnum.ROLE_ENABLE_AUTHORIZATION.exception(); } //生成token String token = SystemConstant.getUuid(); cacheService.userCache(sysUser.getId()); //添加用户会话缓存 Set roleType = authBean.getRoleList().stream().map(s -> s.getType()).collect(Collectors.toSet()); String sessionId = SessionUtil.digest(sysUser.getId(), Math.abs(roleType.toString().hashCode()), platform.name()); //TODO 测试用 String test = SignatureEntityTest.build(SignatureType.TOKEN, sessionId, token); ExpireTimeBean expireTime = AuthUtil.getExpireTime(platform); TBSession tbSession = new TBSession(sessionId, String.valueOf(sysUser.getId()), roleType.toString(), platform.name(), platform.name(), deviceId, ServletUtil.getRequest().getLocalAddr(), token, expireTime.getDate().getTime()); tbSessionService.saveOrUpdate(tbSession); redisUtil.setUserSession(sessionId, tbSession, expireTime.getExpireSeconds()); LoginResult loginResult = new LoginResult(sysUser, sessionId, test, roleType); loginResult.setSchoolInfo(Objects.nonNull(authBean.getSchool()) ? loginResult.new SchoolNativeBean(authBean.getSchool()) : null); loginResult.setOrgInfo(Objects.nonNull(authBean.getOrg()) ? loginResult.new OrgNativeBean(authBean.getOrg()) : null); return ResultUtil.ok(loginResult); } /** * 登出 * * @return */ @ApiOperation(value = "登出") @RequestMapping(value = "/logout", method = RequestMethod.POST) @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)}) public Result logout() { SysUser sysUser = (SysUser) ServletUtil.getRequestUser(); TBSession tbSession = (TBSession) ServletUtil.getRequestSession(); AuthBean authBean = cacheService.userAuthCache(sysUser.getId()); if (Objects.isNull(authBean)) { throw ExceptionResultEnum.NOT_LOGIN.exception(); } tbSessionService.removeById(tbSession.getId()); redisUtil.deleteUserSession(tbSession.getId()); cacheService.removeUserCache(sysUser.getId()); cacheService.removeUserAuthCache(sysUser.getId()); return ResultUtil.ok(new EditResult(sysUser.getId())); } /** * 发送验证码 * * @param loginParam * @return */ @ApiOperation(value = "发送验证码") @RequestMapping(value = "/getVerifyCode", method = RequestMethod.POST) public Object getverifyCode(@RequestBody LoginParam loginParam) { String loginName = loginParam.getLoginName(); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().eq(SysUser::getLoginName, loginName); SysUser user = sysUserService.getOne(wrapper); //用户不存在 if (Objects.isNull(user)) { throw ExceptionResultEnum.ERROR.exception("用户不存在"); } String password = Md5Utils.toMd5Hex(loginParam.getPassword()); if (password.equals(user.getPassword())) { throw ExceptionResultEnum.ERROR.exception("密码错误"); } String mobileNumber = user.getMobileNumber(); if (Objects.isNull(mobileNumber)) { throw ExceptionResultEnum.ERROR.exception("用户未绑定手机号码"); } basicVerifyCodeService.sendVeirfyCode(mobileNumber, user.getId()); return ResultUtil.ok(true); } @ApiOperation(value = "根据机构代码查询机构信息接口") @RequestMapping(value = "/school/query_by_school_code", method = RequestMethod.POST) @ApiResponses({@ApiResponse(code = 200, message = "学校信息", response = EditResult.class)}) @Aac(auth = BOOL.FALSE) public Result queryBySchoolCode(@ApiParam(value = "机构code", required = true) @RequestParam String code) { // HtmlToPdfUtil.convert("/Users/king/Downloads/测试附件/3120ee49668e4bf48fd8c161a2abb73b的副本.html", "/Users/king/Downloads/测试附件/new_test1.pdf", PageSizeEnum.A3); if (!Objects.equals(code.toUpperCase(), RoleTypeEnum.ADMIN.name())) { BasicSchool basicSchool = cacheService.schoolCache(code); if (Objects.isNull(basicSchool)) { throw ExceptionResultEnum.SCHOOL_NO_DATA.exception(); } return ResultUtil.ok(Collections.singletonMap(SystemConstant.LOGO, basicSchool.getLogo())); } else { return ResultUtil.ok(Collections.singletonMap(SystemConstant.LOGO, dictionaryConfig.sysDomain().getAdminLogoUrl())); } } @ApiOperation(value = "文件上传接口") @RequestMapping(value = "/file/upload", method = RequestMethod.POST) @Transactional @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)}) public Result fileUpload(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file, @ApiParam(value = "上传文件类型", required = true) @RequestParam UploadFileEnum type) { BasicAttachment basicAttachment = null; try { basicAttachment = basicAttachmentService.saveAttachment(file, ServletUtil.getRequestMd5(), type); if (Objects.isNull(basicAttachment)) { throw ExceptionResultEnum.ATTACHMENT_ERROR.exception(); } } catch (Exception e) { log.error("请求出错", e); if (Objects.nonNull(basicAttachment)) { basicAttachmentService.deleteAttachment(basicAttachment); } if (e instanceof ApiException) { ResultUtil.error((ApiException) e, e.getMessage()); } else { ResultUtil.error(e.getMessage()); } } return ResultUtil.ok(new EditResult(basicAttachment.getId(), commonService.filePreview(basicAttachment.getPath()), basicAttachment.getPages())); } @ApiOperation(value = "文件下载接口") @RequestMapping(value = "/file/download", method = RequestMethod.POST) @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)}) public Result fileDownload(@ApiParam(value = "任务id", required = true) @RequestParam String id, @ApiParam(value = "下载文件类型", required = true) @RequestParam DownloadFileEnum type) { TBTask tbTask = tbTaskService.getById(Long.parseLong(id)); if (Objects.isNull(tbTask)) { throw ExceptionResultEnum.TASK_NO_DATA.exception(); } String path = null; switch (type.ordinal()) { case 0: path = tbTask.getImportFilePath(); break; case 1: path = tbTask.getReportFilePath(); break; default: path = tbTask.getResultFilePath(); break; } if (Objects.isNull(path)) { throw ExceptionResultEnum.PATH_NO_DATA.exception(); } return ResultUtil.ok(new EditResult(commonService.filePreview(path))); } @ApiOperation(value = "文件预览接口") @RequestMapping(value = "/file/preview", method = RequestMethod.POST) @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)}) public Result filePreview(@ApiParam(value = "附件id", required = true) @RequestParam String id) { BasicAttachment basicAttachment = basicAttachmentService.getById(Long.parseLong(id)); return ResultUtil.ok(new EditResult(commonService.filePreview(basicAttachment.getPath()))); } }