perf: 优化用户体验,首次访问时弹出邮箱账号绑定用以初始化账号

This commit is contained in:
xiaojunnuo
2026-07-05 01:14:48 +08:00
parent 396670dc8f
commit 608cc2a81f
10 changed files with 319 additions and 144 deletions
@@ -1,10 +1,14 @@
import { BaseController, Constants, SysSettingsService } from "@certd/lib-server";
import { AccessGetter, AccessService, BaseController, Constants, SysSettingsService } from "@certd/lib-server";
import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core";
import { PasskeyService } from "../../../modules/login/service/passkey-service.js";
import { RoleService } from "../../../modules/sys/authority/service/role-service.js";
import { UserService } from "../../../modules/sys/authority/service/user-service.js";
import { NotificationService } from "../../../modules/pipeline/service/notification-service.js";
import { newAccess } from "@certd/pipeline";
import { http, logger, utils } from "@certd/basic";
import { ApiTags } from "@midwayjs/swagger";
import { CodeService } from "../../../modules/basic/service/code-service.js";
import { EmailService } from "../../../modules/basic/service/email-service.js";
/**
*/
@@ -27,6 +31,15 @@ export class MineController extends BaseController {
@Inject()
sysSettingsService: SysSettingsService;
@Inject()
accessService: AccessService;
@Inject()
notificationService: NotificationService;
@Inject()
emailService: EmailService;
@Post("/info", { description: Constants.per.authOnly, summary: "查询用户信息" })
public async info() {
const userId = this.getUserId();
@@ -41,6 +54,17 @@ export class MineController extends BaseController {
delete user.password;
//@ts-ignore
user.needInitPassword = needInitPassword;
const { projectId } = await this.getProjectUserIdRead();
const userProjectQuery = this.accessService.buildUserProjectQuery(userId, projectId);
const existingAccess = await this.accessService.findOne({
where: { type: "acmeAccount", subtype: "letsencrypt", ...userProjectQuery },
});
if (!existingAccess) {
//@ts-ignore
user.needInitAccount = true;
}
return this.ok(user);
}
@@ -122,4 +146,58 @@ export class MineController extends BaseController {
});
return this.ok({});
}
@Post("/accountInit", { description: Constants.per.authOnly, summary: "初始化Let's Encrypt ACME账号和邮件通知" })
public async accountInit(@Body("email") email?: string) {
const { projectId, userId } = await this.getProjectUserIdWrite();
let userEmail = email;
let user: any = null;
if (!userEmail) {
user = await this.userService.info(userId);
userEmail = user.email;
}
if (!userEmail) {
return this.ok({ needEmail: true });
}
if (email) {
if (!user) {
user = await this.userService.info(userId);
}
if (!user.email) {
await this.userService.updateEmail(userId, { email: userEmail });
}
}
await this.emailService.add(userId, userEmail);
await this.notificationService.getOrCreateDefault(userEmail, userId, projectId);
const getAccessById = this.accessService.getById.bind(this.accessService);
const accessGetter = new AccessGetter(userId, projectId, getAccessById);
const accessContext = {
http,
logger,
utils,
accessService: accessGetter,
define: undefined,
} as any;
const access = await newAccess("acmeAccount", { caType: "letsencrypt", email: userEmail }, accessGetter, accessContext);
const accountJson = await access.onGenerateAccount();
await this.accessService.add({
type: "acmeAccount",
name: "Let's Encrypt",
userId,
projectId,
setting: JSON.stringify({
caType: "letsencrypt",
email: userEmail,
account: accountJson,
}),
});
return this.ok({ success: true });
}
}
@@ -441,7 +441,8 @@ export class RuntimeDepsService {
private getDefineByPluginKey(pluginKey: string, owner?: RuntimeDependencyPluginDefine): RuntimeDependencyPluginDefine {
const parts = pluginKey.split(":");
let [pluginType, subtype, name] = parts;
const [pluginType, subtype, rawName] = parts;
let name = rawName;
if (parts.length === 2) {
name = subtype;
} else if (parts.length === 3) {