mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-19 01:48:47 +08:00
邮箱添加
This commit is contained in:
parent
6235b44459
commit
0a06e8a5cf
@ -5,6 +5,7 @@ import cn.hutool.captcha.AbstractCaptcha;
|
|||||||
import cn.hutool.captcha.generator.CodeGenerator;
|
import cn.hutool.captcha.generator.CodeGenerator;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -81,7 +82,7 @@ public class CaptchaController {
|
|||||||
*/
|
*/
|
||||||
@RateLimiter(key = "#email", time = 60, count = 1)
|
@RateLimiter(key = "#email", time = 60, count = 1)
|
||||||
@GetMapping("/resource/email/code")
|
@GetMapping("/resource/email/code")
|
||||||
public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
|
public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") @Email String email) {
|
||||||
if (!mailProperties.getEnabled()) {
|
if (!mailProperties.getEnabled()) {
|
||||||
return R.fail("当前系统没有开启邮箱功能!");
|
return R.fail("当前系统没有开启邮箱功能!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,38 +6,48 @@ import cn.hutool.core.bean.BeanUtil;
|
|||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.constant.Constants;
|
||||||
|
import org.dromara.common.core.constant.GlobalConstants;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.domain.model.LoginUser;
|
import org.dromara.common.core.domain.model.LoginUser;
|
||||||
|
import org.dromara.common.core.domain.model.RegisterBody;
|
||||||
|
import org.dromara.common.core.enums.UserType;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
|
import org.dromara.common.core.exception.user.CaptchaException;
|
||||||
|
import org.dromara.common.core.exception.user.CaptchaExpireException;
|
||||||
|
import org.dromara.common.core.exception.user.UserException;
|
||||||
|
import org.dromara.common.core.utils.MessageUtils;
|
||||||
|
import org.dromara.common.core.utils.ServletUtils;
|
||||||
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.dromara.common.core.utils.file.MimeTypeUtils;
|
import org.dromara.common.core.utils.file.MimeTypeUtils;
|
||||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
import org.dromara.common.log.annotation.Log;
|
import org.dromara.common.log.annotation.Log;
|
||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.log.event.LogininforEvent;
|
||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.redis.utils.RedisUtils;
|
||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
import org.dromara.common.tenant.helper.TenantHelper;
|
import org.dromara.common.tenant.helper.TenantHelper;
|
||||||
|
import org.dromara.common.web.config.properties.CaptchaProperties;
|
||||||
import org.dromara.common.web.core.BaseController;
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.system.domain.SysUser;
|
||||||
import org.dromara.system.domain.bo.SysUserBo;
|
import org.dromara.system.domain.bo.SysUserBo;
|
||||||
import org.dromara.system.domain.bo.SysUserPasswordBo;
|
import org.dromara.system.domain.bo.SysUserPasswordBo;
|
||||||
import org.dromara.system.domain.bo.SysUserProfileBo;
|
import org.dromara.system.domain.bo.SysUserProfileBo;
|
||||||
import org.dromara.system.domain.vo.*;
|
import org.dromara.system.domain.vo.*;
|
||||||
|
import org.dromara.system.mapper.SysUserMapper;
|
||||||
import org.dromara.system.service.*;
|
import org.dromara.system.service.*;
|
||||||
import org.dromara.web.domain.bo.EqAppHomeBo;
|
import org.dromara.web.domain.bo.*;
|
||||||
import org.dromara.web.domain.bo.EqAreaBo;
|
|
||||||
import org.dromara.web.domain.bo.EqEquipmentBo;
|
|
||||||
import org.dromara.web.domain.bo.EqShareBo;
|
|
||||||
import org.dromara.web.domain.vo.EqAreaVo;
|
import org.dromara.web.domain.vo.EqAreaVo;
|
||||||
import org.dromara.web.domain.vo.EqEquipmentVo;
|
import org.dromara.web.domain.vo.EqEquipmentVo;
|
||||||
import org.dromara.web.domain.vo.EqShareVo;
|
import org.dromara.web.domain.vo.EqShareVo;
|
||||||
import org.dromara.web.domain.vo.EqUserConfigVo;
|
import org.dromara.web.domain.vo.EqUserConfigVo;
|
||||||
import org.dromara.web.service.IEqAreaService;
|
import org.dromara.web.service.*;
|
||||||
import org.dromara.web.service.IEqEquipmentService;
|
|
||||||
import org.dromara.web.service.IEqShareService;
|
|
||||||
import org.dromara.web.service.IEqUserConfigService;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -46,6 +56,8 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* app用户相关
|
* app用户相关
|
||||||
@ -235,5 +247,114 @@ public class EqUserController extends BaseController {
|
|||||||
private final IEqShareService eqShareService;
|
private final IEqShareService eqShareService;
|
||||||
|
|
||||||
|
|
||||||
|
private final SysUserMapper userMapper;
|
||||||
|
private final CaptchaProperties captchaProperties;
|
||||||
|
private final SysRegisterService registerService;
|
||||||
|
private final ISysConfigService configService;
|
||||||
|
private final IEqUserConfigService iEqUserConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱注册
|
||||||
|
*/
|
||||||
|
//@ApiEncrypt
|
||||||
|
@PostMapping("/emailRegister")
|
||||||
|
public R<Void> register(@Validated @RequestBody RegisterBody user) {
|
||||||
|
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
||||||
|
return R.fail("当前系统没有开启注册功能!");
|
||||||
|
}
|
||||||
|
emailRegister(user);
|
||||||
|
SysUserVo sysUserVo = userService.selectUserByUserName(user.getUsername());
|
||||||
|
EqUserConfigBo bo = new EqUserConfigBo();
|
||||||
|
bo.setUserId(sysUserVo.getUserId());
|
||||||
|
bo.setLanguageType("zh_CN");
|
||||||
|
bo.setTimezoneType("1");//默认 UTC+08:00
|
||||||
|
bo.setZoneId("UTC+08:00");
|
||||||
|
bo.setTimeFormat("YYYY-MM-DD");
|
||||||
|
bo.setCreateBy(sysUserVo.getUserId());
|
||||||
|
bo.setUpdateBy(sysUserVo.getUserId());
|
||||||
|
iEqUserConfigService.insertByBo(bo);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void emailRegister(RegisterBody registerBody) {
|
||||||
|
String tenantId = registerBody.getTenantId();
|
||||||
|
String username = registerBody.getUsername();
|
||||||
|
String password = registerBody.getPassword();
|
||||||
|
// 校验用户类型是否存在
|
||||||
|
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
|
||||||
|
|
||||||
|
if (!validEmail(username)) throw new UserException("user.email.not.valid");
|
||||||
|
|
||||||
|
validateEmailCode(tenantId, username, registerBody.getCode());
|
||||||
|
|
||||||
|
SysUserBo sysUser = new SysUserBo();
|
||||||
|
sysUser.setUserName(username);
|
||||||
|
sysUser.setNickName(username);
|
||||||
|
sysUser.setPassword(BCrypt.hashpw(password));
|
||||||
|
sysUser.setUserType(userType);
|
||||||
|
|
||||||
|
boolean exist = TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
|
||||||
|
.eq(SysUser::getUserName, sysUser.getUserName()));
|
||||||
|
});
|
||||||
|
if (exist) {
|
||||||
|
throw new UserException("user.register.save.error", username);
|
||||||
|
}
|
||||||
|
boolean regFlag = userService.registerUser(sysUser, tenantId);
|
||||||
|
if (!regFlag) {
|
||||||
|
throw new UserException("user.register.error");
|
||||||
|
}
|
||||||
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验邮箱验证码
|
||||||
|
*/
|
||||||
|
private boolean validateEmailCode(String tenantId, String email, String emailCode) {
|
||||||
|
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email);
|
||||||
|
|
||||||
|
if (emailCode == null) {
|
||||||
|
recordLogininfor(tenantId, email, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == null || !code.equalsIgnoreCase(emailCode)) {
|
||||||
|
recordLogininfor(tenantId, email, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
|
||||||
|
throw new CaptchaException();
|
||||||
|
}
|
||||||
|
return code.equals(emailCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void recordLogininfor(String tenantId, String username, String status, String message) {
|
||||||
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setTenantId(tenantId);
|
||||||
|
logininforEvent.setUsername(username);
|
||||||
|
logininforEvent.setStatus(status);
|
||||||
|
logininforEvent.setMessage(message);
|
||||||
|
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||||
|
SpringUtils.context().publishEvent(logininforEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//邮箱格式的验证
|
||||||
|
public static boolean validEmail(String userEmail) {
|
||||||
|
Pattern p = Pattern.compile("[a-zA-Z0-9]+@[A-Za-z0-9]+\\.[a-z0-9]");
|
||||||
|
Matcher m = p.matcher(userEmail);
|
||||||
|
if(m.find()){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,7 @@ spring.data:
|
|||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 2
|
database: 2
|
||||||
# redis 密码必须配置
|
# redis 密码必须配置
|
||||||
password: ruoyi123
|
# password: ruoyi123
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
# 是否开启ssl
|
# 是否开启ssl
|
||||||
@ -127,18 +127,40 @@ redisson:
|
|||||||
subscriptionConnectionPoolSize: 50
|
subscriptionConnectionPoolSize: 50
|
||||||
|
|
||||||
--- # mail 邮件发送
|
--- # mail 邮件发送
|
||||||
|
#mail:
|
||||||
|
# enabled: true
|
||||||
|
# host: smtp.qq.com
|
||||||
|
# port: 465
|
||||||
|
# # 是否需要用户名密码验证
|
||||||
|
# auth: true
|
||||||
|
# # 发送方,遵循RFC-822标准
|
||||||
|
# from: 1278921369@qq.com
|
||||||
|
# # 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||||
|
# user: 1278921369@qq.com
|
||||||
|
# # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
|
||||||
|
# pass: wynqzknymvnkhjea
|
||||||
|
# # 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||||
|
# starttlsEnable: true
|
||||||
|
# # 使用SSL安全连接
|
||||||
|
# sslEnable: true
|
||||||
|
# # SMTP超时时长,单位毫秒,缺省值不超时
|
||||||
|
# timeout: 0
|
||||||
|
# # Socket连接超时值,单位毫秒,缺省值不超时
|
||||||
|
# connectionTimeout: 0
|
||||||
|
|
||||||
|
|
||||||
mail:
|
mail:
|
||||||
enabled: false
|
enabled: true
|
||||||
host: smtp.163.com
|
host: smtp.qiye.aliyun.com
|
||||||
port: 465
|
port: 465
|
||||||
# 是否需要用户名密码验证
|
# 是否需要用户名密码验证
|
||||||
auth: true
|
auth: true
|
||||||
# 发送方,遵循RFC-822标准
|
# 发送方,遵循RFC-822标准
|
||||||
from: xxx@163.com
|
from: aioc-service@mocdoor.com
|
||||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||||
user: xxx@163.com
|
user: aioc-service@mocdoor.com
|
||||||
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
|
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
|
||||||
pass: xxxxxxxxxx
|
pass: PsoFT63GWn4Jdi8C
|
||||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||||
starttlsEnable: true
|
starttlsEnable: true
|
||||||
# 使用SSL安全连接
|
# 使用SSL安全连接
|
||||||
|
|||||||
@ -124,7 +124,9 @@ security:
|
|||||||
# actuator 监控配置
|
# actuator 监控配置
|
||||||
- /actuator
|
- /actuator
|
||||||
- /actuator/**
|
- /actuator/**
|
||||||
|
## app
|
||||||
- /app/text/**
|
- /app/text/**
|
||||||
|
- /app/user/**
|
||||||
|
|
||||||
# 多租户配置
|
# 多租户配置
|
||||||
tenant:
|
tenant:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user