完成邮件重置操作

This commit is contained in:
柏码の讲师 2023-12-13 18:53:16 +08:00
parent 65763f5c24
commit 77b5b2ef7f
7 changed files with 115 additions and 3 deletions

View File

@ -38,7 +38,7 @@ public class AuthorizeController {
@GetMapping("/ask-code")
@Operation(summary = "请求邮件验证码")
public RestBean<Void> askVerifyCode(@RequestParam @Email String email,
@RequestParam @Pattern(regexp = "(reset)") String type,
@RequestParam @Pattern(regexp = "(reset|modify)") String type,
HttpServletRequest request){
return this.messageHandle(() ->
accountService.registerEmailVerifyCode(type, String.valueOf(email), request.getRemoteAddr()));

View File

@ -3,6 +3,7 @@ package com.example.controller;
import com.example.entity.RestBean;
import com.example.entity.vo.request.ChangePasswordVO;
import com.example.entity.vo.request.CreateSubAccountVO;
import com.example.entity.vo.request.ModifyEmailVO;
import com.example.entity.vo.response.SubAccountVO;
import com.example.service.AccountService;
import com.example.utils.Const;
@ -26,6 +27,17 @@ public class UserController {
RestBean.success() : RestBean.failure(401, "原密码输入错误!");
}
@PostMapping("/modify-email")
public RestBean<Void> modifyEmail(@RequestAttribute(Const.ATTR_USER_ID) int id,
@RequestBody @Valid ModifyEmailVO vo) {
String result = service.modifyEmail(id, vo);
if(result == null) {
return RestBean.success();
} else {
return RestBean.failure(401, result);
}
}
@PostMapping("/sub/create")
public RestBean<Void> createSubAccount(@RequestBody @Valid CreateSubAccountVO vo) {
service.createSubAccount(vo);

View File

@ -0,0 +1,13 @@
package com.example.entity.vo.request;
import jakarta.validation.constraints.Email;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
@Data
public class ModifyEmailVO {
@Email
String email;
@Length(max = 6, min = 6)
String code;
}

View File

@ -36,6 +36,10 @@ public class MailQueueListener {
createMessage("您的密码重置邮件",
"你好,您正在执行重置密码操作,验证码: "+code+"有效时间3分钟如非本人操作请无视。",
email);
case "modify" ->
createMessage("您的邮件修改验证邮件",
"您好,您正在绑定新的电子邮件地址,验证码: "+code+"有效时间3分钟如非本人操作请无视",
email);
default -> null;
};
if(message == null) return;

View File

@ -5,6 +5,7 @@ import com.example.entity.dto.Account;
import com.example.entity.vo.request.ConfirmResetVO;
import com.example.entity.vo.request.CreateSubAccountVO;
import com.example.entity.vo.request.EmailResetVO;
import com.example.entity.vo.request.ModifyEmailVO;
import com.example.entity.vo.response.SubAccountVO;
import org.springframework.security.core.userdetails.UserDetailsService;
@ -19,4 +20,5 @@ public interface AccountService extends IService<Account>, UserDetailsService {
void createSubAccount(CreateSubAccountVO vo);
void deleteSubAccount(int uid);
List<SubAccountVO> listSubAccount();
String modifyEmail(int id, ModifyEmailVO vo);
}

View File

@ -7,6 +7,7 @@ import com.example.entity.dto.Account;
import com.example.entity.vo.request.ConfirmResetVO;
import com.example.entity.vo.request.CreateSubAccountVO;
import com.example.entity.vo.request.EmailResetVO;
import com.example.entity.vo.request.ModifyEmailVO;
import com.example.entity.vo.response.SubAccountVO;
import com.example.mapper.AccountMapper;
import com.example.service.AccountService;
@ -161,6 +162,21 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
}).toList();
}
@Override
public String modifyEmail(int id, ModifyEmailVO vo) {
String code = getEmailVerifyCode(vo.getEmail());
if (code == null) return "请先获取验证码";
if(!code.equals(vo.getCode())) return "验证码错误,请重新输入";
this.deleteEmailVerifyCode(vo.getEmail());
Account account = this.findAccountByNameOrEmail(vo.getEmail());
if(account != null && account.getId() != id) return "该邮箱账号已经被其他账号绑定,无法完成操作";
this.update()
.set("email", vo.getEmail())
.eq("id", id)
.update();
return null;
}
/**
* 移除Redis中存储的邮件验证码
* @param email 电邮

View File

@ -1,6 +1,6 @@
<script setup>
import {reactive, ref} from "vue";
import {Lock, Plus, Switch} from "@element-plus/icons-vue";
import {Delete, Lock, Plus, Refresh, Switch} from "@element-plus/icons-vue";
import {get, logout, post} from "@/net";
import {ElMessage} from "element-plus";
import router from "@/router";
@ -29,6 +29,43 @@ const validatePassword = (rule, value, callback) => {
}
}
const emailForm = reactive({
email: store.user.email,
code: ''
})
const coldTime = ref(0)
const isEmailValid = ref(true)
const onEmailValidate = (prop, isValid) => {
if(prop === 'email')
isEmailValid.value = isValid
}
const validateEmail = () => {
coldTime.value = 60
let handle;
get(`/api/auth/ask-code?email=${emailForm.email}&type=modify`, () => {
ElMessage.success(`验证码已发送到邮箱: ${emailForm.email},请注意查收`)
handle = setInterval(() => {
coldTime.value--
if(coldTime.value === 0) {
clearInterval(handle)
}
}, 1000)
}, (message) => {
ElMessage.warning(message)
coldTime.value = 0
})
}
function modifyEmail() {
post('/api/user/modify-email', emailForm, () => {
ElMessage.success('邮件修改成功')
logout(() => router.push('/'))
})
}
const rules = {
password: [
{ required: true, message: '请输入原来的密码', trigger: 'blur' },
@ -40,6 +77,10 @@ const rules = {
new_password_repeat: [
{ required: true, message: '请重复输入新的密码', trigger: 'blur' },
{ validator: validatePassword, trigger: ['blur', 'change'] },
],
email: [
{ required: true, message: '请输入邮件地址', trigger: 'blur' },
{type: 'email', message: '请输入合法的电子邮件地址', trigger: ['blur', 'change']}
]
}
@ -103,7 +144,31 @@ function deleteAccount(id) {
</el-form>
</div>
<div class="info-card" style="margin-top: 10px">
<div class="title"><i class="fa-regular fa-envelope"></i> 电子邮件设置</div>
<el-divider style="margin: 10px 0"/>
<el-form :model="emailForm" label-position="top" :rules="rules"
ref="emailFormRef" @validate="onEmailValidate" style="margin: 0 10px 10px 10px">
<el-form-item label="电子邮件" prop="email">
<el-input v-model="emailForm.email"/>
</el-form-item>
<el-form-item>
<el-row style="width: 100%" :gutter="10">
<el-col :span="18">
<el-input placeholder="请获取验证码" v-model="emailForm.code"/>
</el-col>
<el-col :span="6">
<el-button type="success" @click="validateEmail" style="width: 100%;"
:disabled="!isEmailValid || coldTime > 0">
{{coldTime > 0 ? '请稍后 ' + coldTime + ' 秒' : '获取验证码'}}
</el-button>
</el-col>
</el-row>
</el-form-item>
<div>
<el-button @click="modifyEmail" :disabled="!emailForm.email"
:icon="Refresh" type="success">保存电子邮件</el-button>
</div>
</el-form>
</div>
</div>
<div class="info-card" style="flex: 50%">