From ff083ce6848a8bee3c8248e4b881086ae1517c28 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 11 Dec 2024 11:30:32 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E9=80=9A=E7=9F=A5=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/pipeline/src/core/executor.ts | 64 +++++++----------- .../core/pipeline/src/notification/api.ts | 9 +++ .../pipeline/src/notification/decorator.ts | 9 +-- .../src/plugin/cert-plugin/base.ts | 37 +++-------- .../notification-selector/index.vue | 1 + .../src/controller/basic/email-controller.ts | 5 +- .../controller/pipeline/handle-controller.ts | 12 ---- .../src/modules/basic/service/code-service.ts | 13 +++- .../modules/basic/service/email-service.ts | 2 +- .../pipeline/service/notification-getter.ts | 6 +- .../pipeline/service/notification-service.ts | 65 ++++++++++++++++++- 11 files changed, 122 insertions(+), 101 deletions(-) diff --git a/packages/core/pipeline/src/core/executor.ts b/packages/core/pipeline/src/core/executor.ts index d67d9ecec..9d12d5b31 100644 --- a/packages/core/pipeline/src/core/executor.ts +++ b/packages/core/pipeline/src/core/executor.ts @@ -10,7 +10,8 @@ import { Decorator } from "../decorator/index.js"; import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js"; import { FileStore } from "./file-store.js"; import { cloneDeep, forEach, merge } from "lodash-es"; -import { INotificationService, NotificationBody, NotificationContext, notificationRegistry } from "../notification/index.js"; +import { INotificationService } from "../notification/index.js"; + export type SysInfo = { //系统标题 title?: string; @@ -373,18 +374,17 @@ export class Executor { let subject = ""; let content = ""; const errorMessage = error?.message; - const sysTitle = this.options.sysInfo?.title || "Certd"; if (when === "start") { - subject = `【${sysTitle}】开始执行,${this.pipeline.title}【${this.pipeline.id}】`; + subject = `开始执行,${this.pipeline.title}【${this.pipeline.id}】`; content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`; } else if (when === "success") { - subject = `【${sysTitle}】执行成功,${this.pipeline.title}【${this.pipeline.id}】`; + subject = `执行成功,${this.pipeline.title}【${this.pipeline.id}】`; content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`; } else if (when === "turnToSuccess") { - subject = `【${sysTitle}】执行成功(失败转成功),${this.pipeline.title}【${this.pipeline.id}】`; + subject = `执行成功(失败转成功),${this.pipeline.title}【${this.pipeline.id}】`; content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`; } else if (when === "error") { - subject = `【${sysTitle}】执行失败,${this.pipeline.title}【${this.pipeline.id}】`; + subject = `执行失败,${this.pipeline.title}【${this.pipeline.id}】`; content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}\n错误详情:${error.message}`; } else { return; @@ -407,43 +407,23 @@ export class Executor { } } else { try { - //构建notification插件,发送通知 - let notifyConfig: any; - if (notification.notificationId === 0) { - notifyConfig = await this.options.notificationService.getDefault(); - } else { - notifyConfig = await this.options.notificationService.getById(notification.notificationId); - } - if (notifyConfig == null) { - throw new Error(`通知配置不存在`); - } - - const notificationPlugin = notificationRegistry.get(notifyConfig.type); - const notificationCls: any = notificationPlugin.target; - const notificationSender = new notificationCls(); - const notificationCtx: NotificationContext = { - http: utils.http, - logger, - utils, - emailService: this.options.emailService, - }; - //设置参数 - merge(notificationSender, notifyConfig.setting); - notificationSender.setCtx(notificationCtx); - await notificationSender.onInstance(); - const body: NotificationBody = { - title: subject, - content, - userId: this.pipeline.userId, - pipeline: this.pipeline, - result: this.lastRuntime.pipeline.status, - pipelineId: this.pipeline.id, - historyId: this.runtime.id, - errorMessage, - url, - }; //发送通知 - await notificationSender.send(body); + await this.options.notificationService.send({ + id: notification.notificationId, + useDefault: true, + useEmail: false, + body: { + title: subject, + content, + userId: this.pipeline.userId, + pipeline: this.pipeline, + result: this.lastRuntime.pipeline.status, + pipelineId: this.pipeline.id, + historyId: this.runtime.id, + errorMessage, + url, + }, + }); } catch (e) { logger.error("send notification error", e); } diff --git a/packages/core/pipeline/src/notification/api.ts b/packages/core/pipeline/src/notification/api.ts index 79044e6ea..035f951b3 100644 --- a/packages/core/pipeline/src/notification/api.ts +++ b/packages/core/pipeline/src/notification/api.ts @@ -48,9 +48,18 @@ export type NotificationInstanceConfig = { }; }; +export type NotificationSendReq = { + id?: number; + useDefault?: boolean; + useEmail?: boolean; + emailAddress?: string; + logger?: ILogger; + body: NotificationBody; +}; export interface INotificationService { getById(id: number): Promise; getDefault(): Promise; + send(req: NotificationSendReq): Promise; } export interface INotification { diff --git a/packages/core/pipeline/src/notification/decorator.ts b/packages/core/pipeline/src/notification/decorator.ts index 721dcd5c8..b5b9efd27 100644 --- a/packages/core/pipeline/src/notification/decorator.ts +++ b/packages/core/pipeline/src/notification/decorator.ts @@ -1,9 +1,9 @@ // src/decorator/memoryCache.decorator.ts import { Decorator } from "../decorator/index.js"; import * as _ from "lodash-es"; +import { merge } from "lodash-es"; import { notificationRegistry } from "./registry.js"; import { BaseNotification, NotificationBody, NotificationContext, NotificationDefine, NotificationInputDefine, NotificationInstanceConfig } from "./api.js"; -import { isPlus } from "@certd/plus-core"; // 提供一个唯一 key export const NOTIFICATION_CLASS_KEY = "pipeline:notification"; @@ -47,9 +47,7 @@ export async function newNotification(type: string, input: any, ctx: Notificatio // @ts-ignore const plugin = new register.target(); - for (const key in input) { - plugin[key] = input[key]; - } + merge(plugin, input); if (!ctx) { throw new Error("ctx is required"); } @@ -61,8 +59,5 @@ export async function newNotification(type: string, input: any, ctx: Notificatio export async function sendNotification(opts: { config: NotificationInstanceConfig; ctx: NotificationContext; body: NotificationBody }) { const notification: BaseNotification = await newNotification(opts.config.type, opts.config.setting, opts.ctx); - if (notification.define.needPlus && !isPlus()) { - opts.body.content = `${opts.body.content}\n\n注意:此通知渠道已调整为专业版功能,后续版本将不再支持发送,请尽快修改或升级为专业版`; - } await notification.doSend(opts.body); } diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts index 670dda23b..d704860ac 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts @@ -1,4 +1,4 @@ -import { AbstractTaskPlugin, IContext, NotificationBody, sendNotification, Step, TaskInput, TaskOutput } from "@certd/pipeline"; +import { AbstractTaskPlugin, IContext, NotificationBody, Step, TaskInput, TaskOutput } from "@certd/pipeline"; import dayjs from "dayjs"; import type { CertInfo } from "./acme.js"; import { CertReader } from "./cert-reader.js"; @@ -295,7 +295,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin { * 检查是否过期,默认提前35天 * @param expires * @param maxDays - * @returns {boolean} */ isWillExpire(expires: number, maxDays = 20) { if (expires == null) { @@ -312,39 +311,19 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin { this.logger.info("发送证书申请成功通知"); const url = await this.ctx.urlService.getPipelineDetailUrl(this.pipeline.id, this.ctx.runtime.id); const body: NotificationBody = { - title: `【Certd】证书申请成功【${this.pipeline.title}】`, + title: `证书申请成功【${this.pipeline.title}】`, content: `域名:${this.domains.join(",")}`, url: url, }; try { - const defNotification = await this.ctx.notificationService.getDefault(); - if (defNotification) { - this.logger.info(`通知渠道:${defNotification.name}`); - const notificationCtx = { - http: this.ctx.http, - logger: this.logger, - utils: this.ctx.utils, - emailService: this.ctx.emailService, - }; - await sendNotification({ - config: defNotification, - ctx: notificationCtx, - body, - }); - return; - } - this.logger.warn("未配置默认通知,将发送邮件通知"); - await this.sendSuccessEmail(body); + await this.ctx.notificationService.send({ + useDefault: true, + useEmail: true, + emailAddress: this.email, + body, + }); } catch (e) { this.logger.error("证书申请成功通知发送失败", e); } } - async sendSuccessEmail(body: NotificationBody) { - this.logger.info("发送邮件通知:" + this.email); - await this.ctx.emailService.send({ - receivers: [this.email], - subject: body.title, - content: body.content, - }); - } } diff --git a/packages/ui/certd-client/src/views/certd/notification/notification-selector/index.vue b/packages/ui/certd-client/src/views/certd/notification/notification-selector/index.vue index 2d6ca8396..e851b86a8 100644 --- a/packages/ui/certd-client/src/views/certd/notification/notification-selector/index.vue +++ b/packages/ui/certd-client/src/views/certd/notification/notification-selector/index.vue @@ -126,6 +126,7 @@ function clear() { } async function emitValue(value: any) { + target.value = optionsDictRef.dataMap[value]; if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) { message.error("对不起,您不能修改他人流水线的通知"); return; diff --git a/packages/ui/certd-server/src/controller/basic/email-controller.ts b/packages/ui/certd-server/src/controller/basic/email-controller.ts index 1d9de9f3e..684c0456f 100644 --- a/packages/ui/certd-server/src/controller/basic/email-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/email-controller.ts @@ -12,10 +12,7 @@ export class EmailController extends BaseController { emailService: EmailService; @Post('/test', { summary: Constants.per.authOnly }) - public async test( - @Body('receiver') - receiver - ) { + public async test(@Body('receiver') receiver) { const userId = super.getUserId(); await this.emailService.test(userId, receiver); return this.ok({}); diff --git a/packages/ui/certd-server/src/controller/pipeline/handle-controller.ts b/packages/ui/certd-server/src/controller/pipeline/handle-controller.ts index 30d2c9814..288a8fd69 100644 --- a/packages/ui/certd-server/src/controller/pipeline/handle-controller.ts +++ b/packages/ui/certd-server/src/controller/pipeline/handle-controller.ts @@ -56,18 +56,6 @@ export class HandleController extends BaseController { @Post('/notification', { summary: Constants.per.authOnly }) async notificationRequest(@Body(ALL) body: NotificationRequestHandleReq) { const input = body.input.body; - // if (body.input.id > 0) { - // const oldEntity = await this.notificationService.info(body.input.id); - // if (oldEntity) { - // if (oldEntity.userId !== this.getUserId()) { - // throw new Error('notification not found'); - // } - // const param: any = { - // type: body.typeName, - // setting: JSON.stringify(body.input.access), - // }; - // } - // } const notification = await newNotification(body.typeName, input, { http, 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 ef6f9f6df..c589cbb44 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 @@ -1,12 +1,13 @@ import { Inject, Provide } from '@midwayjs/core'; import { cache, isDev, randomNumber } from '@certd/basic'; -import { SysSettingsService } from '@certd/lib-server'; +import { SysSettingsService, SysSiteInfo } from '@certd/lib-server'; import { SmsServiceFactory } from '../sms/factory.js'; import { ISmsService } from '../sms/api.js'; import { CodeErrorException } from '@certd/lib-server/dist/basic/exception/code-error-exception.js'; import { EmailService } from './email-service.js'; import { AccessService } from '../../pipeline/service/access-service.js'; import { AccessSysGetter } from '../../pipeline/service/access-sys-getter.js'; +import { isComm } from '@certd/plus-core'; // {data: '', text: 'abcd'} /** @@ -99,9 +100,17 @@ export class CodeService { throw new Error('randomStr不能为空'); } + let siteTitle = 'Certd'; + if (isComm()) { + const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); + if (siteInfo) { + siteTitle = siteInfo.title || siteTitle; + } + } + const code = randomNumber(4); await this.emailService.send({ - subject: '【Certd】验证码', + subject: `【${siteTitle}】验证码`, content: `您的验证码是${code},请勿泄露`, receivers: [email], }); diff --git a/packages/ui/certd-server/src/modules/basic/service/email-service.ts b/packages/ui/certd-server/src/modules/basic/service/email-service.ts index b6fe0979b..31190cec0 100644 --- a/packages/ui/certd-server/src/modules/basic/service/email-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/email-service.ts @@ -91,7 +91,7 @@ export class EmailService implements IEmailService { const mailOptions = { from: `${sysTitle} <${emailConfig.sender}>`, to: email.receivers.join(', '), // list of receivers - subject: email.subject, + subject: `【${sysTitle}】${email.subject}`, text: email.content, }; await transporter.sendMail(mailOptions); diff --git a/packages/ui/certd-server/src/modules/pipeline/service/notification-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/notification-getter.ts index 34baa8cad..609d536cd 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/notification-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/notification-getter.ts @@ -1,4 +1,4 @@ -import { INotificationService } from '@certd/pipeline'; +import { INotificationService, NotificationSendReq } from '@certd/pipeline'; import { NotificationService } from './notification-service.js'; export class NotificationGetter implements INotificationService { @@ -17,4 +17,8 @@ export class NotificationGetter implements INotificationService { async getById(id: any) { return await this.notificationService.getById(id, this.userId); } + + async send(req: NotificationSendReq): Promise { + return await this.notificationService.send(req, this.userId); + } } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts index f59049131..e0b722ccb 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts @@ -1,9 +1,12 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { BaseService, ValidateException } from '@certd/lib-server'; +import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; +import { BaseService, SysSettingsService, SysSiteInfo, ValidateException } from '@certd/lib-server'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; import { NotificationEntity } from '../entity/notification.js'; -import { NotificationInstanceConfig, notificationRegistry } from '@certd/pipeline'; +import { NotificationInstanceConfig, notificationRegistry, NotificationSendReq, sendNotification } from '@certd/pipeline'; +import { http, utils } from '@certd/basic'; +import { EmailService } from '../../basic/service/email-service.js'; +import { isComm } from '@certd/plus-core'; @Provide() @Scope(ScopeEnum.Singleton) @@ -11,6 +14,12 @@ export class NotificationService extends BaseService { @InjectEntityModel(NotificationEntity) repository: Repository; + @Inject() + emailService: EmailService; + + @Inject() + sysSettingsService: SysSettingsService; + //@ts-ignore getRepository() { return this.repository; @@ -124,4 +133,54 @@ export class NotificationService extends BaseService { }); return this.buildNotificationInstanceConfig(res); } + + async send(req: NotificationSendReq, userId?: number) { + const logger = req.logger; + let notifyConfig: NotificationInstanceConfig = null; + if (req.id && req.id > 0) { + notifyConfig = await this.getById(req.id, userId); + if (!notifyConfig) { + logger.warn(`未找到通知配置<${req.id}>`); + } + } + if (!notifyConfig) { + if (req.id === 0 || req.useDefault) { + notifyConfig = await this.getDefault(userId); + if (!notifyConfig) { + logger.warn(`未找到默认通知配置`); + } + } + } + + if (notifyConfig) { + //发送通知 + logger.info('发送通知, 使用通知渠道:' + notifyConfig.name); + + let siteTitle = 'Certd'; + if (isComm()) { + const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); + siteTitle = siteInfo?.title || siteTitle; + } + req.body.title = `【${siteTitle}】${req.body.title}`; + await sendNotification({ + config: notifyConfig, + ctx: { + http: http, + logger: logger, + utils: utils, + emailService: this.emailService, + }, + body: req.body, + }); + } else { + if (req.useEmail && req.emailAddress) { + logger.info('使用邮件通知'); + await this.emailService.send({ + receivers: [req.emailAddress], + subject: req.body.title, + content: req.body.content, + }); + } + } + } }