Compare commits
1 Commits
add-qiniu-
...
add-email-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3b34074ce6 |
@@ -154,4 +154,14 @@ public class AuthController {
|
||||
return success(authService.socialLogin(reqVO));
|
||||
}
|
||||
|
||||
// ========== 邮箱注册相关 ==========
|
||||
|
||||
@PostMapping("/register")
|
||||
@PermitAll
|
||||
@Operation(summary = "使用邮箱和密码注册")
|
||||
public CommonResult<Boolean> register(@RequestBody @Valid AuthRegisterReqVO reqVO) {
|
||||
userService.registerUser(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Schema(description = "管理后台 - 用户注册 Request VO")
|
||||
@Data
|
||||
public class AuthRegisterReqVO {
|
||||
|
||||
@Schema(description = "用户邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "test@example.com")
|
||||
@NotBlank(message = "用户邮箱不能为空")
|
||||
@Email(message = "邮箱格式不正确")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Size(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
}
|
@@ -52,13 +52,4 @@ public class SmsCallbackController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/qiniu")
|
||||
@PermitAll
|
||||
@Operation(summary = "七牛云短信的回调", description = "参见 https://www.qiniu.com/products/sms 文档")
|
||||
public CommonResult<Boolean> receiveQiniuSmsStatus(HttpServletRequest request) throws Throwable {
|
||||
String text = ServletUtils.getBody(request);
|
||||
smsSendService.receiveSmsStatus(SmsChannelEnum.QINIU.getCode(), text);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -77,4 +77,16 @@ public class UserSaveReqVO {
|
||||
|| (ObjectUtil.isAllNotEmpty(password)); // 新增时,必须都传递 password
|
||||
}
|
||||
|
||||
// ========== 新增字段 ==========
|
||||
|
||||
@Schema(description = "用户邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "test@example.com")
|
||||
@NotBlank(message = "用户邮箱不能为空")
|
||||
@Email(message = "邮箱格式不正确")
|
||||
private String registrationEmail;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Size(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String registrationPassword;
|
||||
|
||||
}
|
||||
|
@@ -1,134 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
|
||||
import com.qiniu.sms.SmsManager;
|
||||
import com.qiniu.util.Auth;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||
|
||||
/**
|
||||
* 七牛云短信客户端的实现类
|
||||
*/
|
||||
@Slf4j
|
||||
public class QiniuSmsClient extends AbstractSmsClient {
|
||||
|
||||
/**
|
||||
* 七牛云短信管理器
|
||||
*/
|
||||
private volatile SmsManager smsManager;
|
||||
|
||||
public QiniuSmsClient(SmsChannelProperties properties) {
|
||||
super(properties);
|
||||
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
|
||||
Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
Auth auth = Auth.create(properties.getApiKey(), properties.getApiSecret());
|
||||
smsManager = new SmsManager(auth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId,
|
||||
List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
// 构建请求
|
||||
String[] mobiles = {mobile};
|
||||
String templateId = apiTemplateId;
|
||||
String templateParam = JsonUtils.toJsonString(MapUtils.convertMap(templateParams));
|
||||
// 执行请求
|
||||
com.qiniu.sms.model.SmsResponse response = smsManager.sendMessage(templateId, mobiles, templateParam);
|
||||
return new SmsSendRespDTO().setSuccess(response.isSuccessful()).setSerialNo(response.getJobId())
|
||||
.setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
|
||||
List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
|
||||
return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess())
|
||||
.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg())
|
||||
.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime())
|
||||
.setSerialNo(status.getJobId()).setLogId(Long.valueOf(status.getOutId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable {
|
||||
// 七牛云不支持查询短信模板,直接返回 null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信接收状态
|
||||
*/
|
||||
@Data
|
||||
public static class SmsReceiveStatus {
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@JsonProperty("phone_number")
|
||||
private String phoneNumber;
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@JsonProperty("send_time")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime sendTime;
|
||||
/**
|
||||
* 状态报告时间
|
||||
*/
|
||||
@JsonProperty("report_time")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime reportTime;
|
||||
/**
|
||||
* 是否接收成功
|
||||
*/
|
||||
private Boolean success;
|
||||
/**
|
||||
* 状态报告说明
|
||||
*/
|
||||
@JsonProperty("err_msg")
|
||||
private String errMsg;
|
||||
/**
|
||||
* 状态报告编码
|
||||
*/
|
||||
@JsonProperty("err_code")
|
||||
private String errCode;
|
||||
/**
|
||||
* 发送序列号
|
||||
*/
|
||||
@JsonProperty("job_id")
|
||||
private String jobId;
|
||||
/**
|
||||
* 用户序列号
|
||||
*/
|
||||
@JsonProperty("out_id")
|
||||
private String outId;
|
||||
/**
|
||||
* 短信长度
|
||||
*/
|
||||
@JsonProperty("sms_size")
|
||||
private Integer smsSize;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -79,7 +79,6 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
|
||||
case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties);
|
||||
case TENCENT: return new TencentSmsClient(properties);
|
||||
case HUAWEI: return new HuaweiSmsClient(properties);
|
||||
case QINIU: return new QiniuSmsClient(properties);
|
||||
}
|
||||
// 创建失败,错误日志 + 抛出异常
|
||||
log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties);
|
||||
|
@@ -18,7 +18,6 @@ public enum SmsChannelEnum {
|
||||
ALIYUN("ALIYUN", "阿里云"),
|
||||
TENCENT("TENCENT", "腾讯云"),
|
||||
HUAWEI("HUAWEI", "华为云"),
|
||||
QINIU("QINIU", "七牛云"),
|
||||
;
|
||||
|
||||
/**
|
||||
|
@@ -201,4 +201,12 @@ public interface AdminUserService {
|
||||
*/
|
||||
boolean isPasswordMatch(String rawPassword, String encodedPassword);
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
*
|
||||
* @param registerReqVO 注册信息
|
||||
* @return 用户编号
|
||||
*/
|
||||
Long registerUser(@Valid AuthRegisterReqVO registerReqVO);
|
||||
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
|
||||
@@ -21,12 +22,14 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqV
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
||||
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||
import cn.iocoder.yudao.module.system.service.permission.RoleService;
|
||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.mzt.logapi.context.LogRecordContext;
|
||||
@@ -84,6 +87,9 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Resource
|
||||
private ConfigApi configApi;
|
||||
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
|
||||
@@ -492,6 +498,28 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long registerUser(AuthRegisterReqVO registerReqVO) {
|
||||
// 1. 校验邮箱是否已被使用
|
||||
validateEmailUnique(null, registerReqVO.getEmail());
|
||||
|
||||
// 2. 创建用户
|
||||
AdminUserDO user = new AdminUserDO();
|
||||
user.setEmail(registerReqVO.getEmail());
|
||||
user.setPassword(encodePassword(registerReqVO.getPassword()));
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认启用
|
||||
userMapper.insert(user);
|
||||
|
||||
// 3. 赋予 'normal' 角色
|
||||
RoleDO normalRole = roleService.getRoleByCode("normal");
|
||||
if (normalRole != null) {
|
||||
permissionService.assignRoleToUser(user.getId(), normalRole.getId());
|
||||
}
|
||||
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对密码进行加密
|
||||
*
|
||||
|
@@ -1,5 +0,0 @@
|
||||
sms:
|
||||
qiniu:
|
||||
apiKey: your_qiniu_api_key
|
||||
apiSecret: your_qiniu_api_secret
|
||||
signature: your_qiniu_signature
|
Reference in New Issue
Block a user