1.用户修改邮箱逻辑
2.用户验证邮箱逻辑
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ replay_pid*
|
|||||||
/.idea/
|
/.idea/
|
||||||
/target/
|
/target/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
.idea/.cache/.Apifox_Helper/.toolWindow.db
generated
BIN
.idea/.cache/.Apifox_Helper/.toolWindow.db
generated
Binary file not shown.
@@ -375,8 +375,8 @@ public class UserController {
|
|||||||
return ResponseData.success(userService.addUserWithMail(model));
|
return ResponseData.success(userService.addUserWithMail(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/activate")
|
@GetMapping("/activateAccount")
|
||||||
public ResponseData<Object> activate(@RequestParam("token") String token){
|
public ResponseData<Object> activateAccount(@RequestParam("token") String token){
|
||||||
return ResponseData.success(userService.activateAccount(token));
|
return ResponseData.success(userService.activateAccount(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,4 +385,8 @@ public class UserController {
|
|||||||
return ResponseData.success(mailService.resendMail(userModelDTO));
|
return ResponseData.success(mailService.resendMail(userModelDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/verificationMail")
|
||||||
|
public ResponseData<Object> verificationMail(@RequestParam("token") String token){
|
||||||
|
return ResponseData.success(userService.verificationMail(token));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ public class UserModel {
|
|||||||
private Integer inviterId; // 邀请人id
|
private Integer inviterId; // 邀请人id
|
||||||
private String email;
|
private String email;
|
||||||
private String password;
|
private String password;
|
||||||
|
private Integer mailVerification;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ public interface UserService extends IService<UserModel> {
|
|||||||
UserModelVO addUserWithMail(UserModelDTO model);
|
UserModelVO addUserWithMail(UserModelDTO model);
|
||||||
|
|
||||||
Boolean activateAccount(String token);
|
Boolean activateAccount(String token);
|
||||||
|
|
||||||
|
Boolean verificationMail(String token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserModel> implements
|
|||||||
userModelDTO.setPassword(BcryptUtils.encryptPassword(userModelDTO.getNewPassword()));
|
userModelDTO.setPassword(BcryptUtils.encryptPassword(userModelDTO.getNewPassword()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (userModelDTO.getEmail() != null) {
|
||||||
|
mailService.sendVerificationMail(userModelDTO.getEmail(), userModelDTO.getId());
|
||||||
|
}
|
||||||
|
|
||||||
// 用户有密码的情况下重新设置密码
|
// 用户有密码的情况下重新设置密码
|
||||||
if (userInfo.getPassword() != null && userModelDTO.getOldPassword() != null) {
|
if (userInfo.getPassword() != null && userModelDTO.getOldPassword() != null) {
|
||||||
if (BcryptUtils.matchPassword(userModelDTO.getOldPassword(), userInfo.getPassword())) {
|
if (BcryptUtils.matchPassword(userModelDTO.getOldPassword(), userInfo.getPassword())) {
|
||||||
@@ -117,6 +121,7 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserModel> implements
|
|||||||
//设置积分为0
|
//设置积分为0
|
||||||
userModelDTO.setPoints(0);
|
userModelDTO.setPoints(0);
|
||||||
UserModel userModelEntity = BeanUtil.copyProperties(userModelDTO, UserModel.class);
|
UserModel userModelEntity = BeanUtil.copyProperties(userModelDTO, UserModel.class);
|
||||||
|
userModelEntity.setMailVerification(1);
|
||||||
if ( userDao.insert(userModelEntity) != 1){
|
if ( userDao.insert(userModelEntity) != 1){
|
||||||
throw new BusinessException(ErrorCode.ADD_FAILED,"用户注册失败");
|
throw new BusinessException(ErrorCode.ADD_FAILED,"用户注册失败");
|
||||||
}
|
}
|
||||||
@@ -141,10 +146,22 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserModel> implements
|
|||||||
throw new BusinessException(ErrorCode.USER_DOES_NOT_EXIST);
|
throw new BusinessException(ErrorCode.USER_DOES_NOT_EXIST);
|
||||||
}
|
}
|
||||||
userModel.setStatus(0);
|
userModel.setStatus(0);
|
||||||
|
userModel.setMailVerification(0);
|
||||||
if (userDao.updateById(userModel) == 1){
|
if (userDao.updateById(userModel) == 1){
|
||||||
return true;
|
return true;
|
||||||
}else {
|
}else {
|
||||||
throw new BusinessException(ErrorCode.UPDATE_FAILED,"激活失败");
|
throw new BusinessException(ErrorCode.UPDATE_FAILED,"激活失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean verificationMail(String token) {
|
||||||
|
Integer userId = SaTempUtil.parseToken(token, Integer.class);
|
||||||
|
UserModel userModel = userDao.selectById(userId);
|
||||||
|
userModel.setMailVerification(0);
|
||||||
|
if (userDao.updateById(userModel) == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw new BusinessException(ErrorCode.SYSTEM_ERROR,"邮箱验证失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,9 @@ public interface MailService {
|
|||||||
|
|
||||||
void sendMail(String emailAddress,Integer userId);
|
void sendMail(String emailAddress,Integer userId);
|
||||||
|
|
||||||
|
void sendVerificationMail(String emailAddress,Integer userId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Boolean resendMail(UserModelDTO userModelDTO);
|
Boolean resendMail(UserModelDTO userModelDTO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ public class MailServiceImpl implements MailService {
|
|||||||
@Value("${activateUrl}")
|
@Value("${activateUrl}")
|
||||||
private String activateUrl;
|
private String activateUrl;
|
||||||
|
|
||||||
|
@Value("${verificationMailUrl}")
|
||||||
|
private String verificationMailUrl;
|
||||||
|
|
||||||
|
|
||||||
private final Cache<String, Object> emailSendCache = Caffeine.newBuilder()
|
private final Cache<String, Object> emailSendCache = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||||
.build();
|
.build();
|
||||||
@@ -196,6 +200,170 @@ public class MailServiceImpl implements MailService {
|
|||||||
emailSendCache.put(emailAddress, userId);
|
emailSendCache.put(emailAddress, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendVerificationMail(String emailAddress, Integer userId) {
|
||||||
|
log.info("Sending email to {}", emailAddress);
|
||||||
|
String token = SaTempUtil.createToken(userId, 600);
|
||||||
|
if (emailSendCache.getIfPresent(emailAddress) != null) {
|
||||||
|
throw new BusinessException(ErrorCode.EMAIL_SEND_FREQUENT);
|
||||||
|
}
|
||||||
|
MailUtil.send(emailAddress, "验证你的邮箱", "<!DOCTYPE html>\n" +
|
||||||
|
"<html lang=\"en\">\n" +
|
||||||
|
"<head>\n" +
|
||||||
|
" <meta charset=\"UTF-8\">\n" +
|
||||||
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
|
||||||
|
" <title>Account Activation</title>\n" +
|
||||||
|
" <style>\n" +
|
||||||
|
" * {\n" +
|
||||||
|
" margin: 0;\n" +
|
||||||
|
" padding: 0;\n" +
|
||||||
|
" box-sizing: border-box;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" body {\n" +
|
||||||
|
" font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n" +
|
||||||
|
" background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n" +
|
||||||
|
" min-height: 100vh;\n" +
|
||||||
|
" display: flex;\n" +
|
||||||
|
" align-items: center;\n" +
|
||||||
|
" justify-content: center;\n" +
|
||||||
|
" padding: 20px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .container {\n" +
|
||||||
|
" background: white;\n" +
|
||||||
|
" border-radius: 12px;\n" +
|
||||||
|
" box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n" +
|
||||||
|
" padding: 40px;\n" +
|
||||||
|
" text-align: center;\n" +
|
||||||
|
" max-width: 400px;\n" +
|
||||||
|
" width: 100%;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .icon {\n" +
|
||||||
|
" width: 60px;\n" +
|
||||||
|
" height: 60px;\n" +
|
||||||
|
" background: #4CAF50;\n" +
|
||||||
|
" border-radius: 50%;\n" +
|
||||||
|
" display: flex;\n" +
|
||||||
|
" align-items: center;\n" +
|
||||||
|
" justify-content: center;\n" +
|
||||||
|
" margin: 0 auto 20px;\n" +
|
||||||
|
" color: white;\n" +
|
||||||
|
" font-size: 24px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" h1 {\n" +
|
||||||
|
" color: #333;\n" +
|
||||||
|
" font-size: 24px;\n" +
|
||||||
|
" margin-bottom: 10px;\n" +
|
||||||
|
" font-weight: 600;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .subtitle {\n" +
|
||||||
|
" color: #666;\n" +
|
||||||
|
" font-size: 16px;\n" +
|
||||||
|
" margin-bottom: 30px;\n" +
|
||||||
|
" line-height: 1.5;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .activate-button {\n" +
|
||||||
|
" display: inline-block;\n" +
|
||||||
|
" background: #4CAF50;\n" +
|
||||||
|
" border: none;\n" +
|
||||||
|
" border-radius: 8px;\n" +
|
||||||
|
" padding: 15px 30px;\n" +
|
||||||
|
" margin: 20px 0;\n" +
|
||||||
|
" font-size: 18px;\n" +
|
||||||
|
" font-weight: bold;\n" +
|
||||||
|
" color: white;\n" +
|
||||||
|
" text-decoration: none;\n" +
|
||||||
|
" cursor: pointer;\n" +
|
||||||
|
" transition: all 0.3s ease;\n" +
|
||||||
|
" box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n" +
|
||||||
|
" }\n" +
|
||||||
|
" \n" +
|
||||||
|
" .activate-button:hover {\n" +
|
||||||
|
" background: #45a049;\n" +
|
||||||
|
" transform: translateY(-2px);\n" +
|
||||||
|
" box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);\n" +
|
||||||
|
" }\n" +
|
||||||
|
" \n" +
|
||||||
|
" .activate-button:active {\n" +
|
||||||
|
" transform: translateY(0);\n" +
|
||||||
|
" box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .info {\n" +
|
||||||
|
" background: #e3f2fd;\n" +
|
||||||
|
" border-left: 4px solid #2196F3;\n" +
|
||||||
|
" padding: 15px;\n" +
|
||||||
|
" margin: 20px 0;\n" +
|
||||||
|
" text-align: left;\n" +
|
||||||
|
" border-radius: 4px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .info-title {\n" +
|
||||||
|
" font-weight: 600;\n" +
|
||||||
|
" color: #1976D2;\n" +
|
||||||
|
" margin-bottom: 5px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .info-text {\n" +
|
||||||
|
" color: #424242;\n" +
|
||||||
|
" font-size: 14px;\n" +
|
||||||
|
" line-height: 1.4;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" .footer {\n" +
|
||||||
|
" margin-top: 30px;\n" +
|
||||||
|
" padding-top: 20px;\n" +
|
||||||
|
" border-top: 1px solid #eee;\n" +
|
||||||
|
" color: #999;\n" +
|
||||||
|
" font-size: 12px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" @media (max-width: 480px) {\n" +
|
||||||
|
" .container {\n" +
|
||||||
|
" padding: 30px 20px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" \n" +
|
||||||
|
" .verification-code {\n" +
|
||||||
|
" font-size: 24px;\n" +
|
||||||
|
" letter-spacing: 2px;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
" </style>\n" +
|
||||||
|
"</head>\n" +
|
||||||
|
"<body>\n" +
|
||||||
|
" <div class=\"container\">\n" +
|
||||||
|
" <div class=\"icon\">✉</div>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <h1>Verification Mail</h1>\n" +
|
||||||
|
" <p class=\"subtitle\">Please click the button below to verification your mail</p>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <a href=\""+ verificationMailUrl+ token + "\" class=\"activate-button\">\n" +
|
||||||
|
" Verification\n" +
|
||||||
|
" </a>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <div class=\"info\">\n" +
|
||||||
|
" <div class=\"info-title\">Important Notice:</div>\n" +
|
||||||
|
" <div class=\"info-text\">\n" +
|
||||||
|
" • This activation link is valid for 10 minutes<br>\n" +
|
||||||
|
" • Please do not share this link with anyone<br>\n" +
|
||||||
|
" • If you didn't register an account, please ignore this message\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <div class=\"footer\">\n" +
|
||||||
|
" This is an automated message. Please do not reply to this email.\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
"</body>\n" +
|
||||||
|
"</html>\n", true);
|
||||||
|
emailSendCache.put(emailAddress, userId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean resendMail(UserModelDTO userModelDTO) {
|
public Boolean resendMail(UserModelDTO userModelDTO) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -42,4 +42,5 @@ sa-token:
|
|||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
|
||||||
activateUrl: http://192.168.1.174:8086/user/activate?token=
|
activateUrl: http://192.168.1.174:8086/user/activate?token=
|
||||||
|
verificationMailUrl: http://192.168.1.174:8086/user/verification?token=
|
||||||
Reference in New Issue
Block a user