mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 12:48:59 +08:00
feat: 系统服务集成OSS、SMS,新增用户注册和用户个人中心信息等接口
This commit is contained in:
parent
7916b82dff
commit
8aa45c1d8a
@ -18,13 +18,6 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 单元测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud & Alibaba -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
@ -59,6 +52,7 @@
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sentinel规则持久化至Nacos配置 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
@ -69,12 +63,11 @@
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -102,14 +95,9 @@
|
||||
<artifactId>common-rabbitmq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.youlai</groupId>
|
||||
<artifactId>common-file</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.youlai</groupId>
|
||||
<artifactId>common-resourceserver</artifactId>
|
||||
<artifactId>common-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -117,6 +105,13 @@
|
||||
<artifactId>common-apidoc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 单元测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 阿里云短信配置
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2021/10/13
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "sms.aliyun")
|
||||
@Data
|
||||
public class AliyunSmsProperties {
|
||||
|
||||
/**
|
||||
* 阿里云账户的Access Key ID,用于API请求认证
|
||||
*/
|
||||
private String accessKeyId;
|
||||
|
||||
/**
|
||||
*阿里云账户的Access Key Secret,用于API请求认证
|
||||
*/
|
||||
private String accessKeySecret;
|
||||
|
||||
/**
|
||||
* 阿里云短信服务API的域名 eg: dysmsapi.aliyuncs.com
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 阿里云服务的区域ID,如cn-shanghai
|
||||
*/
|
||||
private String regionId;
|
||||
|
||||
/**
|
||||
* 短信签名,必须是已经在阿里云短信服务中注册并通过审核的
|
||||
*/
|
||||
private String signName;
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
private Map<String, String> templateCodes;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.youlai.common.file.controller;
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.youlai.common.file.model.FileInfo;
|
||||
import com.youlai.common.file.service.OssService;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.system.model.vo.FileInfoVO;
|
||||
import com.youlai.system.service.OssService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -20,10 +20,10 @@ public class FileController {
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary= "文件上传")
|
||||
public Result<FileInfo> uploadFile(
|
||||
public Result<FileInfoVO> uploadFile(
|
||||
@Parameter(name = "表单文件对象") @RequestParam(value = "file") MultipartFile file
|
||||
) {
|
||||
FileInfo fileInfo = ossService.uploadFile(file);
|
||||
FileInfoVO fileInfo = ossService.uploadFile(file);
|
||||
return Result.success(fileInfo);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.youlai.common.constant.ExcelConstants;
|
||||
import com.youlai.common.result.PageResult;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.web.annotation.PreventDuplicateResubmit;
|
||||
@ -12,11 +11,9 @@ import com.youlai.system.dto.UserAuthInfo;
|
||||
import com.youlai.system.listener.excel.UserImportListener;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.form.UserForm;
|
||||
import com.youlai.system.model.form.UserRegisterForm;
|
||||
import com.youlai.system.model.query.UserPageQuery;
|
||||
import com.youlai.system.model.vo.UserExportVO;
|
||||
import com.youlai.system.model.vo.UserImportVO;
|
||||
import com.youlai.system.model.vo.UserInfoVO;
|
||||
import com.youlai.system.model.vo.UserPageVO;
|
||||
import com.youlai.system.model.vo.*;
|
||||
import com.youlai.system.service.SysUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -124,7 +121,7 @@ public class SysUserController {
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "根据用户名获取认证信息", hidden = true)
|
||||
@Operation(summary = "获取用户认证信息", hidden = true)
|
||||
@GetMapping("/{username}/authInfo")
|
||||
public Result<UserAuthInfo> getUserAuthInfo(
|
||||
@Parameter(description = "用户名") @PathVariable String username
|
||||
@ -140,14 +137,13 @@ public class SysUserController {
|
||||
return Result.success(userInfoVO);
|
||||
}
|
||||
|
||||
@Operation(summary = "用户注销")
|
||||
@Operation(summary = "注销登出")
|
||||
@DeleteMapping("/logout")
|
||||
public Result logout() {
|
||||
boolean result = userService.logout();
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "用户导入模板下载")
|
||||
@GetMapping("/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
@ -155,7 +151,7 @@ public class SysUserController {
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
|
||||
|
||||
String fileClassPath = ExcelConstants.EXCEL_TEMPLATE_DIR + File.separator + fileName;
|
||||
String fileClassPath = "excel-templates" + File.separator + fileName;
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileClassPath);
|
||||
|
||||
ServletOutputStream outputStream = response.getOutputStream();
|
||||
@ -165,7 +161,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
@Operation(summary = "导入用户")
|
||||
@PostMapping("/_import")
|
||||
@PostMapping("/import")
|
||||
public Result importUsers(@Parameter(description = "部门ID") Long deptId, MultipartFile file) throws IOException {
|
||||
UserImportListener listener = new UserImportListener(deptId);
|
||||
EasyExcel.read(file.getInputStream(), UserImportVO.class, listener).sheet().doRead();
|
||||
@ -174,7 +170,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
@Operation(summary = "导出用户")
|
||||
@GetMapping("/_export")
|
||||
@GetMapping("/export")
|
||||
public void exportUsers(UserPageQuery queryParams, HttpServletResponse response) throws IOException {
|
||||
String fileName = "用户列表.xlsx";
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
@ -184,4 +180,39 @@ public class SysUserController {
|
||||
EasyExcel.write(response.getOutputStream(), UserExportVO.class).sheet("用户列表")
|
||||
.doWrite(exportUserList);
|
||||
}
|
||||
|
||||
@Operation(summary = "注册用户")
|
||||
@PostMapping("/register")
|
||||
public Result registerUser(
|
||||
@RequestBody @Valid UserRegisterForm userRegisterForm
|
||||
) {
|
||||
boolean result = userService.registerUser(userRegisterForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "发送注册短信验证码")
|
||||
@PostMapping("/register/sms_code")
|
||||
public Result sendRegisterSmsCode(
|
||||
@Parameter(description = "手机号") @RequestParam String mobile
|
||||
) {
|
||||
boolean result = userService.sendRegisterSmsCode(mobile);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "发送登录短信验证码")
|
||||
@PostMapping("/login/sms_code")
|
||||
public Result sendLoginSmsCode(
|
||||
@Parameter(description = "手机号") @RequestParam String mobile
|
||||
) {
|
||||
boolean result = userService.sendLoginSmsCode(mobile);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户个人中心信息")
|
||||
@GetMapping("/profile")
|
||||
public Result getUserProfile() {
|
||||
UserProfileVO userProfile = userService.getUserProfile();
|
||||
return Result.success(userProfile);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ package com.youlai.system.converter;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.model.bo.UserBO;
|
||||
import com.youlai.system.model.bo.UserFormBO;
|
||||
import com.youlai.system.model.bo.UserProfileBO;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.form.UserForm;
|
||||
import com.youlai.system.model.vo.UserImportVO;
|
||||
import com.youlai.system.model.vo.UserInfoVO;
|
||||
import com.youlai.system.model.vo.UserPageVO;
|
||||
import com.youlai.system.model.vo.UserProfileVO;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
@ -43,4 +45,8 @@ public interface UserConverter {
|
||||
|
||||
SysUser importVo2Entity(UserImportVO vo);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "genderLabel", expression = "java(com.youlai.common.base.IBaseEnum.getLabelByValue(bo.getGender(), com.youlai.common.enums.GenderEnum.class))")
|
||||
})
|
||||
UserProfileVO userProfileBo2Vo(UserProfileBO bo);
|
||||
}
|
||||
|
@ -19,12 +19,4 @@ import java.util.Set;
|
||||
public interface SysMenuMapper extends BaseMapper<SysMenu> {
|
||||
|
||||
List<RouteBO> listRoutes();
|
||||
|
||||
/**
|
||||
* 获取角色权限集合
|
||||
*
|
||||
* @param roles
|
||||
* @return
|
||||
*/
|
||||
Set<String> listRolePerms(Set<String> roles);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.youlai.common.mybatis.annotation.DataPermission;
|
||||
import com.youlai.system.dto.UserAuthInfo;
|
||||
import com.youlai.system.model.bo.UserBO;
|
||||
import com.youlai.system.model.bo.UserFormBO;
|
||||
import com.youlai.system.model.bo.UserProfileBO;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.query.UserPageQuery;
|
||||
import com.youlai.system.model.vo.UserExportVO;
|
||||
@ -25,9 +26,9 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
/**
|
||||
* 获取用户分页列表
|
||||
*
|
||||
* @param page
|
||||
* @param page 分页参数
|
||||
* @param queryParams 查询参数
|
||||
* @return
|
||||
* @return {@link List<UserBO>}
|
||||
*/
|
||||
@DataPermission(deptAlias = "u")
|
||||
Page<UserBO> getUserPage(Page<UserBO> page, UserPageQuery queryParams);
|
||||
@ -36,24 +37,32 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
* 获取用户表单详情
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
* @return {@link UserFormBO}
|
||||
*/
|
||||
UserFormBO getUserDetail(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户名获取认证信息
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
* @param username 用户名
|
||||
* @return {@link UserAuthInfo}
|
||||
*/
|
||||
UserAuthInfo getUserAuthInfo(String username);
|
||||
|
||||
/**
|
||||
* 获取导出用户列表
|
||||
*
|
||||
* @param queryParams
|
||||
* @return
|
||||
* @param queryParams 查询参数
|
||||
* @return {@link List<UserExportVO>}
|
||||
*/
|
||||
@DataPermission(deptAlias = "u")
|
||||
List<UserExportVO> listExportUsers(UserPageQuery queryParams);
|
||||
|
||||
/**
|
||||
* 获取用户个人中心信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return {@link UserProfileBO}
|
||||
*/
|
||||
UserProfileBO getUserProfile(Long userId);
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
package com.youlai.system.model.bo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户个人中心对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 3.1.0
|
||||
*/
|
||||
@Data
|
||||
public class UserProfileBO {
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 登录账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 头像地址
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 用户角色名称集合
|
||||
*/
|
||||
private Set<String> roleNames;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
private Integer gender;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package com.youlai.system.model.dto;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户导入对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/4/10
|
||||
*/
|
||||
@Data
|
||||
public class UserImportDTO {
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private String roleIds;
|
||||
|
||||
|
||||
private MultipartFile file;
|
||||
|
||||
/**
|
||||
* 导入的用户列表
|
||||
*/
|
||||
private List<UserItem> userList;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class UserItem {
|
||||
|
||||
@ExcelProperty(value = "用户名")
|
||||
private String username;
|
||||
|
||||
@ExcelProperty(value = "用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ExcelProperty(value = "性别")
|
||||
private String gender;
|
||||
|
||||
@ExcelProperty(value = "手机号码")
|
||||
private String mobile;
|
||||
|
||||
@ExcelProperty(value = "邮箱")
|
||||
private String email;
|
||||
}
|
||||
|
||||
}
|
@ -52,7 +52,7 @@ public class SysUser extends BaseEntity {
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 用户状态((1:正常;0:禁用))
|
||||
* 用户状态(1:正常;0:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.youlai.system.model.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户注册表单
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 3.1.0
|
||||
*/
|
||||
@Schema(description = "用户注册表单")
|
||||
@Data
|
||||
public class UserRegisterForm {
|
||||
|
||||
@Schema(description="登录账号")
|
||||
@NotBlank(message = "登录账号不能为空")
|
||||
private String username;
|
||||
|
||||
@Schema(description="手机号码")
|
||||
@Pattern(regexp = "^$|^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "手机号码格式不正确")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description="密码")
|
||||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
@Schema(description="验证码")
|
||||
@NotBlank(message = "验证码不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.youlai.system.model.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 个人中心用户视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/1/14
|
||||
*/
|
||||
@Schema(description ="个人中心用户视图对象")
|
||||
@Data
|
||||
public class UserProfileVO {
|
||||
|
||||
@Schema(description="用户ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description="登录账号")
|
||||
private String username;
|
||||
|
||||
@Schema(description="用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description="手机号码")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description="头像地址")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description="用户角色名称集合")
|
||||
private Set<String> roleNames;
|
||||
|
||||
@Schema(description="部门名称")
|
||||
private String deptName;
|
||||
|
||||
@Schema(description="邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description="性别")
|
||||
private String genderLabel;
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.youlai.common.file.service;
|
||||
package com.youlai.system.service;
|
||||
|
||||
import com.youlai.common.file.model.FileInfo;
|
||||
import com.youlai.system.model.vo.FileInfoVO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
@ -16,7 +16,7 @@ public interface OssService {
|
||||
* @param file 表单文件对象
|
||||
* @return 文件信息
|
||||
*/
|
||||
FileInfo uploadFile(MultipartFile file);
|
||||
FileInfoVO uploadFile(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 删除文件
|
@ -0,0 +1,24 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
|
||||
/**
|
||||
* 短信服务接口层
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public interface SmsService {
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param mobile 手机号 13388886666
|
||||
* @param templateCode 短信模板 SMS_194640010
|
||||
* @param templateParam 模板参数 "[{"code":"123456"}]"
|
||||
*
|
||||
* @return boolean 是否发送成功
|
||||
*/
|
||||
boolean sendSms(String mobile, String templateCode, String templateParam);
|
||||
|
||||
|
||||
}
|
@ -58,14 +58,6 @@ public interface SysMenuService extends IService<SysMenu> {
|
||||
*/
|
||||
boolean updateMenuVisible(Long menuId, Integer visible);
|
||||
|
||||
/**
|
||||
* 获取角色权限集合
|
||||
*
|
||||
* @param roles
|
||||
* @return
|
||||
*/
|
||||
Set<String> listRolePerms(Set<String> roles);
|
||||
|
||||
/**
|
||||
* 获取菜单表单数据
|
||||
*
|
||||
|
@ -6,14 +6,20 @@ import com.youlai.system.model.entity.SysUserRole;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户角色关联业务接口
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public interface SysUserRoleService extends IService<SysUserRole> {
|
||||
|
||||
/**
|
||||
* 保存用户角色
|
||||
*
|
||||
* @param userId
|
||||
* @param roleIds
|
||||
* @return
|
||||
* @param userId 用户ID
|
||||
* @param roleIds 角色ID集合
|
||||
* @return boolean 是否保存成功
|
||||
*/
|
||||
boolean saveUserRoles(Long userId, List<Long> roleIds);
|
||||
|
||||
|
@ -6,10 +6,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.dto.UserAuthInfo;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.form.UserForm;
|
||||
import com.youlai.system.model.form.UserRegisterForm;
|
||||
import com.youlai.system.model.query.UserPageQuery;
|
||||
import com.youlai.system.model.vo.UserExportVO;
|
||||
import com.youlai.system.model.vo.UserInfoVO;
|
||||
import com.youlai.system.model.vo.UserPageVO;
|
||||
import com.youlai.system.model.vo.UserProfileVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -24,7 +26,7 @@ public interface SysUserService extends IService<SysUser> {
|
||||
/**
|
||||
* 用户分页列表
|
||||
*
|
||||
* @return
|
||||
* @return {@link IPage<UserPageVO>}
|
||||
*/
|
||||
IPage<UserPageVO> getUserPage(UserPageQuery queryParams);
|
||||
|
||||
@ -32,8 +34,8 @@ public interface SysUserService extends IService<SysUser> {
|
||||
/**
|
||||
* 获取用户表单数据
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
* @param userId 用户ID
|
||||
* @return {@link UserForm}
|
||||
*/
|
||||
UserForm getUserFormData(Long userId);
|
||||
|
||||
@ -42,7 +44,7 @@ public interface SysUserService extends IService<SysUser> {
|
||||
* 新增用户
|
||||
*
|
||||
* @param userForm 用户表单对象
|
||||
* @return
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean saveUser(UserForm userForm);
|
||||
|
||||
@ -51,7 +53,7 @@ public interface SysUserService extends IService<SysUser> {
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param userForm 用户表单对象
|
||||
* @return
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean updateUser(Long userId, UserForm userForm);
|
||||
|
||||
@ -60,7 +62,7 @@ public interface SysUserService extends IService<SysUser> {
|
||||
* 删除用户
|
||||
*
|
||||
* @param idsStr 用户ID,多个以英文逗号(,)分割
|
||||
* @return
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean deleteUsers(String idsStr);
|
||||
|
||||
@ -70,7 +72,7 @@ public interface SysUserService extends IService<SysUser> {
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param password 用户密码
|
||||
* @return
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean updatePassword(Long userId, String password);
|
||||
|
||||
@ -87,8 +89,8 @@ public interface SysUserService extends IService<SysUser> {
|
||||
/**
|
||||
* 获取导出用户列表
|
||||
*
|
||||
* @param queryParams
|
||||
* @return
|
||||
* @param queryParams 查询参数
|
||||
* @return {@link List<UserExportVO>}
|
||||
*/
|
||||
List<UserExportVO> listExportUsers(UserPageQuery queryParams);
|
||||
|
||||
@ -96,14 +98,47 @@ public interface SysUserService extends IService<SysUser> {
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
*
|
||||
* @return
|
||||
* @return {@link UserInfoVO}
|
||||
*/
|
||||
UserInfoVO getCurrentUserInfo();
|
||||
|
||||
/**
|
||||
* 注销登出
|
||||
*
|
||||
* @return
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean logout();
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
*
|
||||
* @param userRegisterForm 用户注册表单对象
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
boolean registerUser(UserRegisterForm userRegisterForm);
|
||||
|
||||
|
||||
/**
|
||||
* 发送注册短信验证码
|
||||
*
|
||||
* @param mobile 手机号
|
||||
* @return {@link Boolean} 是否发送成功
|
||||
*/
|
||||
boolean sendRegisterSmsCode(String mobile);
|
||||
|
||||
/**
|
||||
* 发送登录短信验证码
|
||||
*
|
||||
* @param mobile 手机号
|
||||
* @return {@link Boolean} 是否发送成功
|
||||
*/
|
||||
boolean sendLoginSmsCode(String mobile);
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户个人中心信息
|
||||
*
|
||||
* @return {@link UserProfileVO}
|
||||
*/
|
||||
UserProfileVO getUserProfile();
|
||||
}
|
||||
|
@ -256,17 +256,6 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色权限集合
|
||||
*
|
||||
* @param roles 角色编码集合
|
||||
* @return 权限标识集合
|
||||
*/
|
||||
@Override
|
||||
public Set<String> listRolePerms(Set<String> roles) {
|
||||
return this.baseMapper.listRolePerms(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单表单数据
|
||||
*
|
||||
|
@ -2,7 +2,7 @@ package com.youlai.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.constant.SecurityConstants;
|
||||
import com.youlai.common.constant.RedisConstants;
|
||||
import com.youlai.system.mapper.SysRoleMenuMapper;
|
||||
import com.youlai.system.model.bo.RolePermsBO;
|
||||
import com.youlai.system.model.entity.SysRoleMenu;
|
||||
@ -39,14 +39,14 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
@Override
|
||||
public void refreshRolePermsCache() {
|
||||
// 清理权限缓存
|
||||
redisTemplate.opsForHash().delete(SecurityConstants.ROLE_PERMS_PREFIX, "*");
|
||||
redisTemplate.opsForHash().delete(RedisConstants.ROLE_PERMS_PREFIX, "*");
|
||||
|
||||
List<RolePermsBO> list = this.baseMapper.getRolePermsList(null);
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
list.forEach(item -> {
|
||||
String roleCode = item.getRoleCode();
|
||||
Set<String> perms = item.getPerms();
|
||||
redisTemplate.opsForHash().put(SecurityConstants.ROLE_PERMS_PREFIX, roleCode, perms);
|
||||
redisTemplate.opsForHash().put(RedisConstants.ROLE_PERMS_PREFIX, roleCode, perms);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
@Override
|
||||
public void refreshRolePermsCache(String roleCode) {
|
||||
// 清理权限缓存
|
||||
redisTemplate.opsForHash().delete(SecurityConstants.ROLE_PERMS_PREFIX, roleCode);
|
||||
redisTemplate.opsForHash().delete(RedisConstants.ROLE_PERMS_PREFIX, roleCode);
|
||||
|
||||
List<RolePermsBO> list = this.baseMapper.getRolePermsList(roleCode);
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
@ -67,7 +67,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
}
|
||||
|
||||
Set<String> perms = rolePerms.getPerms();
|
||||
redisTemplate.opsForHash().put(SecurityConstants.ROLE_PERMS_PREFIX, roleCode, perms);
|
||||
redisTemplate.opsForHash().put(RedisConstants.ROLE_PERMS_PREFIX, roleCode, perms);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
@Override
|
||||
public void refreshRolePermsCache(String oldRoleCode, String newRoleCode) {
|
||||
// 清理旧角色权限缓存
|
||||
redisTemplate.opsForHash().delete(SecurityConstants.ROLE_PERMS_PREFIX, oldRoleCode);
|
||||
redisTemplate.opsForHash().delete(RedisConstants.ROLE_PERMS_PREFIX, oldRoleCode);
|
||||
|
||||
// 添加新角色权限缓存
|
||||
List<RolePermsBO> list =this.baseMapper.getRolePermsList(newRoleCode);
|
||||
@ -88,7 +88,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
}
|
||||
|
||||
Set<String> perms = rolePerms.getPerms();
|
||||
redisTemplate.opsForHash().put(SecurityConstants.ROLE_PERMS_PREFIX, newRoleCode, perms);
|
||||
redisTemplate.opsForHash().put(RedisConstants.ROLE_PERMS_PREFIX, newRoleCode, perms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.constant.SystemConstants;
|
||||
@ -14,7 +13,6 @@ import com.youlai.system.converter.RoleConverter;
|
||||
import com.youlai.system.mapper.SysRoleMapper;
|
||||
import com.youlai.system.model.entity.SysRole;
|
||||
import com.youlai.system.model.entity.SysRoleMenu;
|
||||
import com.youlai.system.model.entity.SysUserRole;
|
||||
import com.youlai.system.model.form.RoleForm;
|
||||
import com.youlai.system.model.query.RolePageQuery;
|
||||
import com.youlai.common.web.model.Option;
|
||||
|
@ -2,40 +2,46 @@ package com.youlai.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.constant.SecurityConstants;
|
||||
import com.youlai.common.constant.GlobalConstants;
|
||||
import com.youlai.common.constant.RedisConstants;
|
||||
import com.youlai.common.constant.SystemConstants;
|
||||
import com.youlai.common.security.service.PermissionService;
|
||||
import com.youlai.common.security.util.SecurityUtils;
|
||||
import com.youlai.system.config.AliyunSmsProperties;
|
||||
import com.youlai.system.converter.UserConverter;
|
||||
import com.youlai.system.dto.UserAuthInfo;
|
||||
import com.youlai.system.mapper.SysUserMapper;
|
||||
import com.youlai.system.model.bo.UserBO;
|
||||
import com.youlai.system.model.bo.UserFormBO;
|
||||
import com.youlai.system.model.bo.UserProfileBO;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.form.UserForm;
|
||||
import com.youlai.system.model.form.UserRegisterForm;
|
||||
import com.youlai.system.model.query.UserPageQuery;
|
||||
import com.youlai.system.model.vo.UserExportVO;
|
||||
import com.youlai.system.model.vo.UserInfoVO;
|
||||
import com.youlai.system.model.vo.UserPageVO;
|
||||
import com.youlai.system.service.SysMenuService;
|
||||
import com.youlai.system.model.vo.UserProfileVO;
|
||||
import com.youlai.system.service.SmsService;
|
||||
import com.youlai.system.service.SysRoleService;
|
||||
import com.youlai.system.service.SysUserRoleService;
|
||||
import com.youlai.system.service.SysUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -47,6 +53,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
@ -57,12 +64,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
|
||||
private final UserConverter userConverter;
|
||||
|
||||
private final RedisTemplate<String,Object> redisTemplate;
|
||||
|
||||
private final SysMenuService menuService;
|
||||
|
||||
private final PermissionService permissionService;
|
||||
|
||||
private final SmsService smsService;
|
||||
|
||||
private final AliyunSmsProperties aliyunSmsProperties;
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 获取用户分页列表
|
||||
*
|
||||
@ -81,9 +90,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
Page<UserBO> userBoPage = this.baseMapper.getUserPage(page, queryParams);
|
||||
|
||||
// 实体转换
|
||||
Page<UserPageVO> userVoPage = userConverter.bo2Vo(userBoPage);
|
||||
|
||||
return userVoPage;
|
||||
return userConverter.bo2Vo(userBoPage);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,8 +103,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
public UserForm getUserFormData(Long userId) {
|
||||
UserFormBO userFormBO = this.baseMapper.getUserDetail(userId);
|
||||
// 实体转换po->form
|
||||
UserForm userForm = userConverter.bo2Form(userFormBO);
|
||||
return userForm;
|
||||
return userConverter.bo2Form(userFormBO);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,7 +142,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param userForm 用户表单对象
|
||||
* @return
|
||||
* @return true|false 是否更新成功
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
@ -167,12 +173,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
* 删除用户
|
||||
*
|
||||
* @param idsStr 用户ID,多个以英文逗号(,)分割
|
||||
* @return 删除结果 true/false
|
||||
* @return true/false 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteUsers(String idsStr) {
|
||||
Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
|
||||
// 逻辑删除
|
||||
List<Long> ids = Arrays.stream(idsStr.split(","))
|
||||
.map(Long::parseLong).
|
||||
collect(Collectors.toList());
|
||||
@ -207,10 +211,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
if (userAuthInfo != null) {
|
||||
Set<String> roles = userAuthInfo.getRoles();
|
||||
if (CollectionUtil.isNotEmpty(roles)) {
|
||||
// 根据角色编码集合获取权限标识集合
|
||||
Set<String> perms = menuService.listRolePerms(roles);
|
||||
userAuthInfo.setPerms(perms);
|
||||
|
||||
// 获取最大范围的数据权限(目前设定DataScope越小,拥有的数据权限范围越大,所以获取得到角色列表中最小的DataScope)
|
||||
Integer dataScope = roleService.getMaxDataRangeDataScope(roles);
|
||||
userAuthInfo.setDataScope(dataScope);
|
||||
@ -228,8 +228,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
*/
|
||||
@Override
|
||||
public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
|
||||
List<UserExportVO> list = this.baseMapper.listExportUsers(queryParams);
|
||||
return list;
|
||||
return this.baseMapper.listExportUsers(queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,11 +250,11 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
// entity->VO
|
||||
UserInfoVO userInfoVO = userConverter.entity2UserInfoVo(user);
|
||||
|
||||
// 用户角色集合
|
||||
// 获取用户角色集合
|
||||
Set<String> roles = SecurityUtils.getRoles();
|
||||
userInfoVO.setRoles(roles);
|
||||
|
||||
// 用户权限集合
|
||||
// 获取用户权限集合
|
||||
if (CollectionUtil.isNotEmpty(roles)) {
|
||||
Set<String> perms = permissionService.getRolePermsFormCache(roles);
|
||||
userInfoVO.setPerms(perms);
|
||||
@ -272,19 +271,133 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@Override
|
||||
public boolean logout() {
|
||||
String jti = SecurityUtils.getJti();
|
||||
Optional<Long> expireTimeOpt = Optional.ofNullable(SecurityUtils.getExp()); // 使用Optional处理可能的null值
|
||||
|
||||
Long expireTime = SecurityUtils.getExp(); // token 过期时间戳(秒)
|
||||
long currentTimeInSeconds = System.currentTimeMillis() / 1000; // 当前时间(单位:秒)
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000;// 当前时间(单位:秒)
|
||||
if (expireTime != null) {
|
||||
if (expireTime > currentTime) {
|
||||
// token未过期,添加至缓存作为黑名单限制访问,缓存时间为token过期剩余时间
|
||||
redisTemplate.opsForValue().set(SecurityConstants.TOKEN_BLACKLIST_PREFIX + jti, null, (expireTime - currentTime), TimeUnit.SECONDS);
|
||||
expireTimeOpt.ifPresent(expireTime -> {
|
||||
if (expireTime > currentTimeInSeconds) {
|
||||
// token未过期,添加至缓存作为黑名单,缓存时间为token剩余的有效时间
|
||||
long remainingTimeInSeconds = expireTime - currentTimeInSeconds;
|
||||
redisTemplate.opsForValue().set(RedisConstants.TOKEN_BLACKLIST_PREFIX + jti, "", remainingTimeInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
} else {
|
||||
});
|
||||
|
||||
if (!expireTimeOpt.isPresent()) {
|
||||
// token 永不过期则永久加入黑名单
|
||||
redisTemplate.opsForValue().set(SecurityConstants.TOKEN_BLACKLIST_PREFIX + jti, null);
|
||||
redisTemplate.opsForValue().set(RedisConstants.TOKEN_BLACKLIST_PREFIX + jti, "");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
*
|
||||
* @param userRegisterForm 用户注册表单对象
|
||||
* @return true|false 是否注册成功
|
||||
*/
|
||||
@Override
|
||||
public boolean registerUser(UserRegisterForm userRegisterForm) {
|
||||
|
||||
String mobile = userRegisterForm.getMobile();
|
||||
String code = userRegisterForm.getCode();
|
||||
// 校验验证码
|
||||
String cacheCode = (String) redisTemplate.opsForValue().get(RedisConstants.REGISTER_SMS_CODE_PREFIX + mobile);
|
||||
if (!StrUtil.equals(code, cacheCode)) {
|
||||
log.warn("验证码不匹配或不存在: {}", mobile);
|
||||
return false; // 验证码不匹配或不存在时返回false
|
||||
}
|
||||
// 校验通过,删除验证码
|
||||
redisTemplate.delete(RedisConstants.REGISTER_SMS_CODE_PREFIX + mobile);
|
||||
|
||||
// 校验手机号是否已注册
|
||||
long count = this.count(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(SysUser::getMobile, mobile)
|
||||
.or()
|
||||
.eq(SysUser::getUsername, mobile)
|
||||
);
|
||||
Assert.isTrue(count == 0, "手机号已注册");
|
||||
|
||||
SysUser entity = new SysUser();
|
||||
entity.setUsername(mobile);
|
||||
entity.setMobile(mobile);
|
||||
entity.setStatus(GlobalConstants.STATUS_YES);
|
||||
|
||||
// 设置默认加密密码
|
||||
String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
|
||||
entity.setPassword(defaultEncryptPwd);
|
||||
|
||||
// 新增用户,并直接返回结果
|
||||
return this.save(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送注册短信验证码
|
||||
*
|
||||
* @param mobile 手机号
|
||||
* @return true|false 是否发送成功
|
||||
*/
|
||||
@Override
|
||||
public boolean sendRegisterSmsCode(String mobile) {
|
||||
// 获取短信模板代码
|
||||
String templateCode = aliyunSmsProperties.getTemplateCodes().get("register");
|
||||
|
||||
// 生成随机4位数验证码
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
|
||||
// 短信模板: 您的验证码:${code},该验证码5分钟内有效,请勿泄漏于他人。
|
||||
// 其中 ${code} 是模板参数,使用时需要替换为实际值。
|
||||
String templateParams = JSONUtil.toJsonStr(Collections.singletonMap("code", code));
|
||||
|
||||
boolean result = smsService.sendSms(mobile, templateCode, templateParams);
|
||||
if (result) {
|
||||
// 将验证码存入redis,有效期5分钟
|
||||
redisTemplate.opsForValue().set(RedisConstants.REGISTER_SMS_CODE_PREFIX + mobile, code, 5, TimeUnit.MINUTES);
|
||||
|
||||
// TODO 考虑记录每次发送短信的详情,如发送时间、手机号和短信内容等,以便后续审核或分析短信发送效果。
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送登录短信验证码
|
||||
*
|
||||
* @param mobile 手机号
|
||||
* @return true|false 是否发送成功
|
||||
*/
|
||||
@Override
|
||||
public boolean sendLoginSmsCode(String mobile) {
|
||||
// 获取短信模板代码
|
||||
String templateCode = aliyunSmsProperties.getTemplateCodes().get("login");
|
||||
|
||||
// 生成随机4位数验证码
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
|
||||
// 短信模板: 您的验证码:${code},该验证码5分钟内有效,请勿泄漏于他人。
|
||||
// 其中 ${code} 是模板参数,使用时需要替换为实际值。
|
||||
String templateParams = JSONUtil.toJsonStr(Collections.singletonMap("code", code));
|
||||
|
||||
boolean result = smsService.sendSms(mobile, templateCode, templateParams);
|
||||
if (result) {
|
||||
// 将验证码存入redis,有效期5分钟
|
||||
redisTemplate.opsForValue().set(RedisConstants.REGISTER_SMS_CODE_PREFIX + mobile, code, 5, TimeUnit.MINUTES);
|
||||
|
||||
// TODO 考虑记录每次发送短信的详情,如发送时间、手机号和短信内容等,以便后续审核或分析短信发送效果。
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户个人中心信息
|
||||
*
|
||||
* @return {@link UserProfileVO}
|
||||
*/
|
||||
@Override
|
||||
public UserProfileVO getUserProfile() {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
// 获取用户个人中心信息
|
||||
UserProfileBO userProfileBO = this.baseMapper.getUserProfile(userId);
|
||||
return userConverter.userProfileBo2Vo(userProfileBO);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.youlai.common.file.service.impl;
|
||||
package com.youlai.system.service.impl.oss;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
@ -8,27 +8,27 @@ import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import com.youlai.common.file.model.FileInfo;
|
||||
import com.youlai.common.file.service.OssService;
|
||||
import com.youlai.system.model.vo.FileInfoVO;
|
||||
import com.youlai.system.service.OssService;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Aliyun 对象存储服务类
|
||||
* 阿里云OSS服务
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Component
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "oss.type", havingValue = "aliyun")
|
||||
@ConfigurationProperties(prefix = "oss.aliyun")
|
||||
@RequiredArgsConstructor
|
||||
@ -60,7 +60,7 @@ public class AliyunOssService implements OssService {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public FileInfo uploadFile(MultipartFile file) {
|
||||
public FileInfoVO uploadFile(MultipartFile file) {
|
||||
|
||||
// 生成文件名(日期文件夹)
|
||||
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
|
||||
@ -81,7 +81,7 @@ public class AliyunOssService implements OssService {
|
||||
}
|
||||
// 获取文件访问路径
|
||||
String fileUrl = "https://" + bucketName + "." + endpoint + "/" + fileName;
|
||||
FileInfo fileInfo = new FileInfo();
|
||||
FileInfoVO fileInfo = new FileInfoVO();
|
||||
fileInfo.setName(fileName);
|
||||
fileInfo.setUrl(fileUrl);
|
||||
return fileInfo;
|
@ -1,12 +1,12 @@
|
||||
package com.youlai.common.file.service.impl;
|
||||
package com.youlai.system.service.impl.oss;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.common.file.model.FileInfo;
|
||||
import com.youlai.common.file.service.OssService;
|
||||
import com.youlai.system.model.vo.FileInfoVO;
|
||||
import com.youlai.system.service.OssService;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.*;
|
||||
import io.minio.http.Method;
|
||||
@ -17,6 +17,7 @@ import lombok.SneakyThrows;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -29,7 +30,7 @@ import java.time.LocalDateTime;
|
||||
* @author haoxr
|
||||
* @since 2023/6/2
|
||||
*/
|
||||
@Component
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "oss.type", havingValue = "minio")
|
||||
@ConfigurationProperties(prefix = "oss.minio")
|
||||
@RequiredArgsConstructor
|
||||
@ -76,7 +77,7 @@ public class MinioOssService implements OssService {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public FileInfo uploadFile(MultipartFile file) {
|
||||
public FileInfoVO uploadFile(MultipartFile file) {
|
||||
|
||||
// 生成文件名(日期文件夹)
|
||||
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
|
||||
@ -107,7 +108,7 @@ public class MinioOssService implements OssService {
|
||||
fileUrl = customDomain + '/' + bucketName + "/" + fileName;
|
||||
}
|
||||
|
||||
FileInfo fileInfo = new FileInfo();
|
||||
FileInfoVO fileInfo = new FileInfoVO();
|
||||
fileInfo.setName(fileName);
|
||||
fileInfo.setUrl(fileUrl);
|
||||
return fileInfo;
|
@ -1,7 +1,5 @@
|
||||
package com.youlai.common.sms.service;
|
||||
package com.youlai.system.service.impl.sms;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.aliyuncs.CommonRequest;
|
||||
import com.aliyuncs.CommonResponse;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
@ -10,39 +8,35 @@ import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.exceptions.ServerException;
|
||||
import com.aliyuncs.http.MethodType;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.youlai.common.constant.SecurityConstants;
|
||||
import com.youlai.common.sms.config.AliyunSmsProperties;
|
||||
import com.youlai.system.config.AliyunSmsProperties;
|
||||
import com.youlai.system.service.SmsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 阿里云短信业务类
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
|
||||
* @since 2021/10/13 23:04
|
||||
* @author haoxr
|
||||
* @since 3.1.0
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliyunSmsService {
|
||||
public class AliyunSmsService implements SmsService {
|
||||
|
||||
private final AliyunSmsProperties aliyunSmsProperties;
|
||||
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param phoneNumber 手机号
|
||||
* @return
|
||||
* @param mobile 手机号 13388886666
|
||||
* @param templateCode 短信模板 SMS_194640010
|
||||
* @param templateParam 模板参数 "[{"code":"123456"}]"
|
||||
*
|
||||
* @return boolean 是否发送成功
|
||||
*/
|
||||
public boolean sendSmsCode(String phoneNumber) {
|
||||
String code = RandomUtil.randomNumbers(6); // 随机生成6位的验证码
|
||||
stringRedisTemplate.opsForValue().set(SecurityConstants.SMS_CODE_PREFIX + phoneNumber, code, 600, TimeUnit.SECONDS);
|
||||
@Override
|
||||
public boolean sendSms(String mobile,String templateCode,String templateParam) {
|
||||
|
||||
DefaultProfile profile = DefaultProfile.getProfile(aliyunSmsProperties.getRegionId(),
|
||||
aliyunSmsProperties.getAccessKeyId(), aliyunSmsProperties.getAccessKeySecret());
|
||||
@ -52,26 +46,22 @@ public class AliyunSmsService {
|
||||
CommonRequest request = new CommonRequest();
|
||||
// 指定请求方式
|
||||
request.setSysMethod(MethodType.POST);
|
||||
// 短信api的请求地址 固定
|
||||
// 短信api的请求地址(固定)
|
||||
request.setSysDomain(aliyunSmsProperties.getDomain());
|
||||
// 签名算法版本 固定
|
||||
// 签名算法版(固定)
|
||||
request.setSysVersion("2017-05-25");
|
||||
// 请求 API 的名称
|
||||
// 请求 API 的名称(固定)
|
||||
request.setSysAction("SendSms");
|
||||
// 指定地域名称
|
||||
request.putQueryParameter("RegionId", aliyunSmsProperties.getRegionId());
|
||||
// 要给哪个手机号发送短信 指定手机号
|
||||
request.putQueryParameter("PhoneNumbers", phoneNumber);
|
||||
request.putQueryParameter("PhoneNumbers", mobile);
|
||||
// 您的申请签名
|
||||
request.putQueryParameter("SignName", aliyunSmsProperties.getSignName());
|
||||
// 您申请的模板 code
|
||||
request.putQueryParameter("TemplateCode", aliyunSmsProperties.getTemplateCode());
|
||||
request.putQueryParameter("TemplateCode", templateCode);
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
// 这里的key就是短信模板中的 ${xxxx}
|
||||
params.put("code", code);
|
||||
|
||||
request.putQueryParameter("TemplateParam", JSONUtil.toJsonStr(params));
|
||||
request.putQueryParameter("TemplateParam", templateParam);
|
||||
|
||||
try {
|
||||
CommonResponse response = client.getCommonResponse(request);
|
||||
@ -82,7 +72,6 @@ public class AliyunSmsService {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
@ -46,27 +46,4 @@
|
||||
ORDER BY t1.sort asc
|
||||
</select>
|
||||
|
||||
<!-- 获取角色拥有的权限集合 -->
|
||||
<select id="listRolePerms" resultType="java.lang.String">
|
||||
SELECT
|
||||
DISTINCT t1.perm
|
||||
FROM
|
||||
sys_menu t1
|
||||
INNER JOIN sys_role_menu t2
|
||||
INNER JOIN sys_role t3
|
||||
WHERE
|
||||
t1.type = '${@com.youlai.common.enums.MenuTypeEnum@BUTTON.getValue()}'
|
||||
AND t1.perm IS NOT NULL
|
||||
<choose>
|
||||
<when test="roles!=null and roles.size()>0">
|
||||
AND t3.CODE IN
|
||||
<foreach collection="roles" item="role" separator="," open="(" close=")">
|
||||
#{role}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
AND t1.id = -1
|
||||
</otherwise>
|
||||
</choose>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -33,7 +33,7 @@
|
||||
INNER JOIN sys_role t2 ON t1.role_id = t2.id AND t2.deleted = 0 AND t2.`status` = 1
|
||||
INNER JOIN sys_menu t3 ON t1.menu_id = t3.id
|
||||
WHERE
|
||||
type = '${@com.youlai.system.common.enums.MenuTypeEnum@BUTTON.getValue()}'
|
||||
type = '${@com.youlai.system.enums.MenuTypeEnum@BUTTON.getValue()}'
|
||||
<if test="roleCode!=null and roleCode.trim() neq ''">
|
||||
AND t2.`code` = #{roleCode}
|
||||
</if>
|
||||
|
@ -23,7 +23,7 @@
|
||||
LEFT JOIN sys_user_role sur ON u.id = sur.user_id
|
||||
LEFT JOIN sys_role r ON sur.role_id = r.id
|
||||
<where>
|
||||
u.deleted = 0 AND u.username != 'root'
|
||||
u.deleted = 0 AND u.username != ${@com.youlai.common.constant.SystemConstants@ROOT_ROLE_CODE}
|
||||
<if test='queryParams.keywords!=null and queryParams.keywords.trim() neq ""'>
|
||||
AND (
|
||||
u.username LIKE CONCAT('%',#{queryParams.keywords},'%')
|
||||
@ -51,7 +51,7 @@
|
||||
<result property="avatar" column="avatar" jdbcType="VARCHAR"/>
|
||||
<result property="email" column="email" jdbcType="VARCHAR"/>
|
||||
<result property="status" column="status" jdbcType="BOOLEAN"/>
|
||||
<result property="deptId" column="dept_id" jdbcType="BIGINT"></result>
|
||||
<result property="deptId" column="dept_id" jdbcType="BIGINT"/>
|
||||
<collection
|
||||
property="roleIds"
|
||||
column="id"
|
||||
@ -62,16 +62,18 @@
|
||||
|
||||
<!-- 根据用户ID获取用户详情 -->
|
||||
<select id="getUserDetail" resultMap="UserFormMap">
|
||||
SELECT id,
|
||||
username,
|
||||
nickname,
|
||||
mobile,
|
||||
gender,
|
||||
avatar,
|
||||
email,
|
||||
STATUS,
|
||||
dept_id
|
||||
FROM sys_user
|
||||
SELECT
|
||||
id,
|
||||
username,
|
||||
nickname,
|
||||
mobile,
|
||||
gender,
|
||||
avatar,
|
||||
email,
|
||||
STATUS,
|
||||
dept_id
|
||||
FROM
|
||||
sys_user
|
||||
WHERE id = #{userId}
|
||||
AND deleted = 0
|
||||
</select>
|
||||
@ -82,9 +84,9 @@
|
||||
<result property="username" column="username" jdbcType="VARCHAR"/>
|
||||
<result property="password" column="password" jdbcType="VARCHAR"/>
|
||||
<result property="status" column="status" jdbcType="BOOLEAN"/>
|
||||
<result property="deptId" column="dept_id" jdbcType="BIGINT"></result>
|
||||
<result property="deptId" column="dept_id" jdbcType="BIGINT"/>
|
||||
<collection property="roles" ofType="string" javaType="java.util.Set">
|
||||
<result column="code"></result>
|
||||
<result column="code"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
@ -103,7 +105,8 @@
|
||||
LEFT JOIN sys_user_role t2 ON t2.user_id = t1.id
|
||||
LEFT JOIN sys_role t3 ON t3.id = t2.role_id
|
||||
WHERE
|
||||
t1.username = #{username} AND t1.deleted=0
|
||||
t1.username = #{username}
|
||||
AND t1.deleted=0
|
||||
</select>
|
||||
|
||||
<!-- 获取用户导出列表 -->
|
||||
@ -139,4 +142,27 @@
|
||||
GROUP BY u.id
|
||||
</select>
|
||||
|
||||
<!-- 获取用户个人中心信息 -->
|
||||
<select id="getUserProfile" resultType="com.youlai.system.model.bo.UserProfileBO">
|
||||
SELECT
|
||||
u.id,
|
||||
u.username,
|
||||
u.nickname,
|
||||
u.mobile,
|
||||
u.gender,
|
||||
u.avatar,
|
||||
u.STATUS,
|
||||
d.NAME AS dept_name,
|
||||
GROUP_CONCAT( r.NAME ) AS roleNames,
|
||||
u.create_time
|
||||
FROM
|
||||
sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.id
|
||||
LEFT JOIN sys_user_role sur ON u.id = sur.user_id
|
||||
LEFT JOIN sys_role r ON sur.role_id = r.id
|
||||
WHERE
|
||||
u.id = #{userId}
|
||||
AND u.deleted = 0
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
Loading…
Reference in New Issue
Block a user