diff --git a/packages/ui/certd-client/src/views/framework/forgot-password/index.vue b/packages/ui/certd-client/src/views/framework/forgot-password/index.vue
index 9e94db2a..1acee359 100644
--- a/packages/ui/certd-client/src/views/framework/forgot-password/index.vue
+++ b/packages/ui/certd-client/src/views/framework/forgot-password/index.vue
@@ -21,7 +21,13 @@
-
+
@@ -33,7 +39,14 @@
-
+
@@ -60,7 +73,7 @@
找回密码
@@ -83,7 +96,10 @@ const rules = {
input: [{ required: true }],
validateCode: [{ required: true }],
imgCode: [{ required: true }, { min: 4, max: 4, message: "请输入4位图片验证码" }],
- password: [{ required: true, trigger: "change", message: "请输入密码" }],
+ password: [
+ { required: true, trigger: "change", message: "请输入密码" },
+ { len: 6, message: "至少输入6位密码" },
+ ],
confirmPassword: [
{ required: true, trigger: "change", message: "请确认密码" },
{
diff --git a/packages/ui/certd-client/src/views/framework/login/sms-code.vue b/packages/ui/certd-client/src/views/framework/login/sms-code.vue
index b9f6e1ac..efbf6ab3 100644
--- a/packages/ui/certd-client/src/views/framework/login/sms-code.vue
+++ b/packages/ui/certd-client/src/views/framework/login/sms-code.vue
@@ -23,6 +23,7 @@ const props = defineProps<{
phoneCode?: string;
imgCode?: string;
randomStr?: string;
+ verificationType?: string;
}>();
const emit = defineEmits(["update:value", "change"]);
@@ -58,6 +59,7 @@ async function sendSmsCode() {
mobile: props.mobile,
imgCode: props.imgCode,
randomStr: props.randomStr,
+ verificationType: props.verificationType,
});
} finally {
loading.value = false;
diff --git a/packages/ui/certd-client/src/views/framework/register/email-code.vue b/packages/ui/certd-client/src/views/framework/register/email-code.vue
index 51e6cd15..6ee92e1f 100644
--- a/packages/ui/certd-client/src/views/framework/register/email-code.vue
+++ b/packages/ui/certd-client/src/views/framework/register/email-code.vue
@@ -22,6 +22,7 @@ const props = defineProps<{
email?: string;
imgCode?: string;
randomStr?: string;
+ verificationType?: string;
}>();
const emit = defineEmits(["update:value", "change"]);
@@ -53,6 +54,7 @@ async function sendSmsCode() {
email: props.email,
imgCode: props.imgCode,
randomStr: props.randomStr,
+ verificationType: props.verificationType,
});
} finally {
loading.value = false;
diff --git a/packages/ui/certd-server/src/controller/basic/code-controller.ts b/packages/ui/certd-server/src/controller/basic/code-controller.ts
index 09a90009..fb0eedc2 100644
--- a/packages/ui/certd-server/src/controller/basic/code-controller.ts
+++ b/packages/ui/certd-server/src/controller/basic/code-controller.ts
@@ -27,6 +27,9 @@ export class EmailCodeReq {
@Rule(RuleType.string().required().max(4))
imgCode: string;
+
+ @Rule(RuleType.string())
+ verificationType: string;
}
/**
@@ -55,8 +58,20 @@ export class BasicController extends BaseController {
@Body(ALL)
body: EmailCodeReq
) {
+ const opts = {
+ verificationType: body.verificationType,
+ title: undefined,
+ content: undefined,
+ duration: undefined,
+ };
+ if(body?.verificationType === 'forgotPassword') {
+ opts.title = '找回密码';
+ opts.content = '验证码:${code}。您正在找回密码,请输入验证码并完成操作。如非本人操作请忽略';
+ opts.duration = 3;
+ }
+
await this.codeService.checkCaptcha(body.randomStr, body.imgCode);
- await this.codeService.sendEmailCode(body.email, body.randomStr);
+ await this.codeService.sendEmailCode(body.email, body.randomStr, opts);
// 设置缓存内容
return this.ok(null);
}
diff --git a/packages/ui/certd-server/src/controller/user/login/forgot-password-controller.ts b/packages/ui/certd-server/src/controller/user/login/forgot-password-controller.ts
index 62ff9a46..382bdcb2 100644
--- a/packages/ui/certd-server/src/controller/user/login/forgot-password-controller.ts
+++ b/packages/ui/certd-server/src/controller/user/login/forgot-password-controller.ts
@@ -2,12 +2,15 @@ import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { BaseController, CommonException, Constants, SysSettingsService } from "@certd/lib-server";
import { CodeService } from '../../../modules/basic/service/code-service.js';
import { UserService } from '../../../modules/sys/authority/service/user-service.js';
+import { LoginService } from "../../../modules/login/service/login-service.js";
/**
*/
@Provide()
@Controller('/api')
export class LoginController extends BaseController {
+ @Inject()
+ loginService: LoginService;
@Inject()
userService: UserService;
@Inject()
@@ -23,6 +26,7 @@ export class LoginController extends BaseController {
) {
if(body.type === 'email') {
this.codeService.checkEmailCode({
+ verificationType: 'forgotPassword',
email: body.input,
randomStr: body.randomStr,
validateCode: body.validateCode,
@@ -30,6 +34,7 @@ export class LoginController extends BaseController {
});
} else if(body.type === 'mobile') {
await this.codeService.checkSmsCode({
+ verificationType: 'forgotPassword',
mobile: body.input,
randomStr: body.randomStr,
phoneCode: body.phoneCode,
@@ -39,7 +44,8 @@ export class LoginController extends BaseController {
} else {
throw new CommonException('暂不支持的找回类型,请联系管理员找回');
}
- await this.userService.forgotPassword(body);
+ const username = await this.userService.forgotPassword(body);
+ username && this.loginService.clearCacheOnSuccess(username)
return this.ok();
}
}
diff --git a/packages/ui/certd-server/src/modules/basic/service/code-service.ts b/packages/ui/certd-server/src/modules/basic/service/code-service.ts
index a7f5122a..62d108ca 100644
--- a/packages/ui/certd-server/src/modules/basic/service/code-service.ts
+++ b/packages/ui/certd-server/src/modules/basic/service/code-service.ts
@@ -57,7 +57,15 @@ export class CodeService {
}
/**
*/
- async sendSmsCode(phoneCode = '86', mobile: string, randomStr: string) {
+ async sendSmsCode(
+ phoneCode = '86',
+ mobile: string,
+ randomStr: string,
+ opts?: {
+ duration?: number,
+ verificationType?: string
+ },
+ ) {
if (!mobile) {
throw new Error('手机号不能为空');
}
@@ -65,6 +73,8 @@ export class CodeService {
throw new Error('randomStr不能为空');
}
+ const duration = Math.max(Math.floor(Math.min(opts?.duration || 5, 15)), 1);
+
const sysSettings = await this.sysSettingsService.getPrivateSettings();
if (!sysSettings.sms?.config?.accessId) {
throw new Error('当前站点还未配置短信');
@@ -84,16 +94,29 @@ export class CodeService {
phoneCode,
});
- const key = this.buildSmsCodeKey(phoneCode, mobile, randomStr);
+ const key = this.buildSmsCodeKey(phoneCode, mobile, randomStr, opts?.verificationType);
cache.set(key, smsCode, {
- ttl: 5 * 60 * 1000, //5分钟
+ ttl: duration * 60 * 1000, //5分钟
});
return smsCode;
}
/**
+ *
+ * @param email 收件邮箱
+ * @param randomStr
+ * @param opts title标题 content内容模版 duration有效时间单位分钟 verificationType验证类型
*/
- async sendEmailCode(email: string, randomStr: string) {
+ async sendEmailCode(
+ email: string,
+ randomStr: string,
+ opts?: {
+ title?: string,
+ content?: string,
+ duration?: number,
+ verificationType?: string
+ },
+ ) {
if (!email) {
throw new Error('Email不能为空');
}
@@ -110,15 +133,20 @@ export class CodeService {
}
const code = randomNumber(4);
+ const duration = Math.max(Math.floor(Math.min(opts?.duration || 5, 15)), 1);
+
+ const title = `【${siteTitle}】${!!opts?.title ? opts.title : '验证码'}`;
+ const content = !!opts.content ? this.compile(opts.content)({code, duration}) : `您的验证码是${code},请勿泄露`;
+
await this.emailService.send({
- subject: `【${siteTitle}】验证码`,
- content: `您的验证码是${code},请勿泄露`,
+ subject: title,
+ content: content,
receivers: [email],
});
- const key = this.buildEmailCodeKey(email, randomStr);
+ const key = this.buildEmailCodeKey(email, randomStr, opts?.verificationType);
cache.set(key, code, {
- ttl: 5 * 60 * 1000, //5分钟
+ ttl: duration * 60 * 1000, //5分钟
});
return code;
}
@@ -126,20 +154,20 @@ export class CodeService {
/**
* checkSms
*/
- async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; throwError: boolean }) {
- const key = this.buildSmsCodeKey(opts.phoneCode, opts.mobile, opts.randomStr);
+ async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; verificationType?: string; throwError: boolean }) {
+ const key = this.buildSmsCodeKey(opts.phoneCode, opts.mobile, opts.randomStr, opts.verificationType);
if (isDev()) {
return true;
}
return this.checkValidateCode(key, opts.smsCode, opts.throwError);
}
- buildSmsCodeKey(phoneCode: string, mobile: string, randomStr: string) {
- return `sms:${phoneCode}${mobile}:${randomStr}`;
+ buildSmsCodeKey(phoneCode: string, mobile: string, randomStr: string, verificationType?: string) {
+ return ['sms', verificationType, phoneCode, mobile, randomStr].filter(item => !!item).join(':');
}
- buildEmailCodeKey(email: string, randomStr: string) {
- return `email:${email}:${randomStr}`;
+ buildEmailCodeKey(email: string, randomStr: string, verificationType?: string) {
+ return ['email', verificationType, email, randomStr].filter(item => !!item).join(':');
}
checkValidateCode(key: string, userCode: string, throwError = true) {
//验证图片验证码
@@ -154,8 +182,18 @@ export class CodeService {
return true;
}
- checkEmailCode(opts: { randomStr: string; validateCode: string; email: string; throwError: boolean }) {
- const key = this.buildEmailCodeKey(opts.email, opts.randomStr);
+ checkEmailCode(opts: { randomStr: string; validateCode: string; email: string; verificationType?: string; throwError: boolean }) {
+ const key = this.buildEmailCodeKey(opts.email, opts.randomStr, opts.verificationType);
return this.checkValidateCode(key, opts.validateCode, opts.throwError);
}
+
+ compile(templateString: string) {
+ return new Function(
+ "data",
+ ` with(data || {}) {
+ return \`${templateString}\`;
+ }
+ `
+ );
+ }
}
diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts
index 94359243..3298d477 100644
--- a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts
+++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts
@@ -250,6 +250,7 @@ export class UserService extends BaseService {
// return;
}
await this.resetPassword(user.id, data.password)
+ return user.username;
}
async changePassword(userId: any, form: any) {