feat: drop deprecated notify service

This commit is contained in:
Fu Diwei
2025-07-24 21:09:05 +08:00
parent d29427b018
commit c494b1869d
18 changed files with 25 additions and 545 deletions
+2 -72
View File
@@ -6,7 +6,6 @@ import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
@@ -16,16 +15,9 @@ import (
"github.com/certimate-go/certimate/internal/app"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/internal/domain/dtos"
"github.com/certimate-go/certimate/internal/notify"
"github.com/certimate-go/certimate/internal/repository"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
)
const (
defaultExpireSubject = "有 ${COUNT} 张证书即将过期"
defaultExpireMessage = "有 ${COUNT} 张证书即将过期,域名分别为 ${DOMAINS},请保持关注!"
)
type certificateRepository interface {
ListExpireSoon(ctx context.Context) ([]*domain.Certificate, error)
GetById(ctx context.Context, id string) (*domain.Certificate, error)
@@ -49,24 +41,6 @@ func NewCertificateService(certificateRepo certificateRepository, settingsRepo s
}
func (s *CertificateService) InitSchedule(ctx context.Context) error {
// 每日发送过期证书提醒
app.GetScheduler().MustAdd("certificateExpireSoonNotify", "0 0 * * *", func() {
certificates, err := s.certificateRepo.ListExpireSoon(context.Background())
if err != nil {
app.GetLogger().Error("failed to get certificates which expire soon", "err", err)
return
}
notification := buildExpireSoonNotification(certificates)
if notification == nil {
return
}
if err := notify.SendToAllChannels(notification.Subject, notification.Message); err != nil {
app.GetLogger().Error("failed to send notification", "err", err)
}
})
// 每日清理过期证书
app.GetScheduler().MustAdd("certificateExpiredCleanup", "0 0 * * *", func() {
settings, err := s.settingsRepo.GetByName(ctx, "persistence")
@@ -75,7 +49,7 @@ func (s *CertificateService) InitSchedule(ctx context.Context) error {
return
}
var settingsContent *domain.PersistenceSettingsContent
var settingsContent *domain.SettingsContentAsPersistence
json.Unmarshal([]byte(settings.Content), &settingsContent)
if settingsContent != nil && settingsContent.ExpiredCertificatesMaxDaysRetention != 0 {
ret, err := s.certificateRepo.DeleteWhere(
@@ -95,7 +69,7 @@ func (s *CertificateService) InitSchedule(ctx context.Context) error {
return nil
}
func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error) {
func (s *CertificateService) DownloadArchivedFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error) {
certificate, err := s.certificateRepo.GetById(ctx, req.CertificateId)
if err != nil {
return nil, err
@@ -246,47 +220,3 @@ func (s *CertificateService) ValidatePrivateKey(ctx context.Context, req *dtos.C
IsValid: true,
}, nil
}
func buildExpireSoonNotification(certificates []*domain.Certificate) *struct {
Subject string
Message string
} {
if len(certificates) == 0 {
return nil
}
subject := defaultExpireSubject
message := defaultExpireMessage
// 查询模板信息
settingsRepo := repository.NewSettingsRepository()
settings, err := settingsRepo.GetByName(context.Background(), "notifyTemplates")
if err == nil {
var templates *domain.NotifyTemplatesSettingsContent
json.Unmarshal([]byte(settings.Content), &templates)
if templates != nil && len(templates.NotifyTemplates) > 0 {
subject = templates.NotifyTemplates[0].Subject
message = templates.NotifyTemplates[0].Message
}
}
// 替换变量
count := len(certificates)
domains := make([]string, count)
for i, record := range certificates {
domains[i] = record.SubjectAltNames
}
countStr := strconv.Itoa(count)
domainStr := strings.Join(domains, ";")
subject = strings.ReplaceAll(subject, "${COUNT}", countStr)
subject = strings.ReplaceAll(subject, "${DOMAINS}", domainStr)
message = strings.ReplaceAll(message, "${COUNT}", countStr)
message = strings.ReplaceAll(message, "${DOMAINS}", domainStr)
// 返回消息
return &struct {
Subject string
Message string
}{Subject: subject, Message: message}
}
+1 -3
View File
@@ -1,7 +1,5 @@
package dtos
import "github.com/certimate-go/certimate/internal/domain"
type NotifyTestPushReq struct {
Channel domain.NotifyChannelType `json:"channel"`
Provider string `json:"provider"`
}
-25
View File
@@ -1,25 +0,0 @@
package domain
type NotifyChannelType string
/*
消息通知渠道常量值。
注意:如果追加新的常量值,请保持以 ASCII 排序。
NOTICE: If you add new constant, please keep ASCII order.
*/
// Deprecated: v0.4.x 将废弃
const (
NotifyChannelTypeBark = NotifyChannelType("bark")
NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk")
NotifyChannelTypeEmail = NotifyChannelType("email")
NotifyChannelTypeGotify = NotifyChannelType("gotify")
NotifyChannelTypeLark = NotifyChannelType("lark")
NotifyChannelTypeMattermost = NotifyChannelType("mattermost")
NotifyChannelTypePushover = NotifyChannelType("pushover")
NotifyChannelTypePushPlus = NotifyChannelType("pushplus")
NotifyChannelTypeServerChan = NotifyChannelType("serverchan")
NotifyChannelTypeTelegram = NotifyChannelType("telegram")
NotifyChannelTypeWebhook = NotifyChannelType("webhook")
NotifyChannelTypeWeCom = NotifyChannelType("wecom")
)
+1 -32
View File
@@ -1,10 +1,5 @@
package domain
import (
"encoding/json"
"fmt"
)
const CollectionNameSettings = "settings"
type Settings struct {
@@ -13,33 +8,7 @@ type Settings struct {
Content string `json:"content" db:"content"`
}
// Deprecated: v0.4.x 将废弃
type NotifyTemplatesSettingsContent struct {
NotifyTemplates []struct {
Subject string `json:"subject"`
Message string `json:"message"`
} `json:"notifyTemplates"`
}
// Deprecated: v0.4.x 将废弃
type NotifyChannelsSettingsContent map[string]map[string]any
// Deprecated: v0.4.x 将废弃
func (s *Settings) GetNotifyChannelConfig(channel string) (map[string]any, error) {
conf := &NotifyChannelsSettingsContent{}
if err := json.Unmarshal([]byte(s.Content), conf); err != nil {
return nil, err
}
v, ok := (*conf)[channel]
if !ok {
return nil, fmt.Errorf("channel \"%s\" not found", channel)
}
return v, nil
}
type PersistenceSettingsContent struct {
type SettingsContentAsPersistence struct {
WorkflowRunsMaxDaysRetention int `json:"workflowRunsMaxDaysRetention"`
ExpiredCertificatesMaxDaysRetention int `json:"expiredCertificatesMaxDaysRetention"`
}
-2
View File
@@ -107,7 +107,6 @@ type WorkflowNodeConfigForDeploy struct {
}
type WorkflowNodeConfigForNotify struct {
Channel string `json:"channel,omitempty"` // Deprecated: v0.4.x 将废弃
Provider string `json:"provider"` // 通知提供商
ProviderAccessId string `json:"providerAccessId"` // 通知提供商授权记录 ID
ProviderConfig map[string]any `json:"providerConfig,omitempty"` // 通知提供商额外配置
@@ -173,7 +172,6 @@ func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy {
func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify {
return WorkflowNodeConfigForNotify{
Channel: xmaps.GetString(n.Config, "channel"),
Provider: xmaps.GetString(n.Config, "provider"),
ProviderAccessId: xmaps.GetString(n.Config, "providerAccessId"),
ProviderConfig: xmaps.GetKVMapAny(n.Config, "providerConfig"),
-81
View File
@@ -1,81 +0,0 @@
package notify
import (
"context"
"encoding/json"
"fmt"
"golang.org/x/sync/errgroup"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/internal/repository"
"github.com/certimate-go/certimate/pkg/core"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
// Deprecated: v0.4.x 将废弃
func SendToAllChannels(subject, message string) error {
notifiers, err := getEnabledNotifiers()
if err != nil {
return err
}
if len(notifiers) == 0 {
return nil
}
var eg errgroup.Group
for _, n := range notifiers {
if n == nil {
continue
}
eg.Go(func() error {
_, err := n.Notify(context.Background(), subject, message)
return err
})
}
err = eg.Wait()
return err
}
// Deprecated: v0.4.x 将废弃
func SendToChannel(subject, message string, channel string, channelConfig map[string]any) error {
notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(channel), channelConfig)
if err != nil {
return err
}
_, err = notifier.Notify(context.Background(), subject, message)
return err
}
// Deprecated: v0.4.x 将废弃
func getEnabledNotifiers() ([]core.Notifier, error) {
settingsRepo := repository.NewSettingsRepository()
settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels")
if err != nil {
return nil, fmt.Errorf("find notifyChannels error: %w", err)
}
rs := make(map[string]map[string]any)
if err := json.Unmarshal([]byte(settings.Content), &rs); err != nil {
return nil, fmt.Errorf("unmarshal notifyChannels error: %w", err)
}
notifiers := make([]core.Notifier, 0)
for k, v := range rs {
if !xmaps.GetBool(v, "enabled") {
continue
}
notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(k), v)
if err != nil {
continue
}
notifiers = append(notifiers, notifier)
}
return notifiers, nil
}
-108
View File
@@ -1,108 +0,0 @@
package notify
import (
"fmt"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/pkg/core"
pBark "github.com/certimate-go/certimate/pkg/core/notifier/providers/bark"
pDingTalk "github.com/certimate-go/certimate/pkg/core/notifier/providers/dingtalkbot"
pEmail "github.com/certimate-go/certimate/pkg/core/notifier/providers/email"
pGotify "github.com/certimate-go/certimate/pkg/core/notifier/providers/gotify"
pLark "github.com/certimate-go/certimate/pkg/core/notifier/providers/larkbot"
pMattermost "github.com/certimate-go/certimate/pkg/core/notifier/providers/mattermost"
pPushover "github.com/certimate-go/certimate/pkg/core/notifier/providers/pushover"
pPushPlus "github.com/certimate-go/certimate/pkg/core/notifier/providers/pushplus"
pServerChan "github.com/certimate-go/certimate/pkg/core/notifier/providers/serverchan"
pTelegram "github.com/certimate-go/certimate/pkg/core/notifier/providers/telegrambot"
pWebhook "github.com/certimate-go/certimate/pkg/core/notifier/providers/webhook"
pWeCom "github.com/certimate-go/certimate/pkg/core/notifier/providers/wecombot"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
// Deprecated: v0.4.x 将废弃
func createNotifierProviderUseGlobalSettings(channel domain.NotifyChannelType, channelConfig map[string]any) (core.Notifier, error) {
/*
注意:如果追加新的常量值,请保持以 ASCII 排序。
NOTICE: If you add new constant, please keep ASCII order.
*/
switch channel {
case domain.NotifyChannelTypeBark:
return pBark.NewNotifierProvider(&pBark.NotifierProviderConfig{
DeviceKey: xmaps.GetString(channelConfig, "deviceKey"),
ServerUrl: xmaps.GetString(channelConfig, "serverUrl"),
})
case domain.NotifyChannelTypeDingTalk:
return pDingTalk.NewNotifierProvider(&pDingTalk.NotifierProviderConfig{
WebhookUrl: "https://oapi.dingtalk.com/robot/send?access_token=" + xmaps.GetString(channelConfig, "accessToken"),
Secret: xmaps.GetString(channelConfig, "secret"),
})
case domain.NotifyChannelTypeEmail:
return pEmail.NewNotifierProvider(&pEmail.NotifierProviderConfig{
SmtpHost: xmaps.GetString(channelConfig, "smtpHost"),
SmtpPort: xmaps.GetInt32(channelConfig, "smtpPort"),
SmtpTls: xmaps.GetOrDefaultBool(channelConfig, "smtpTLS", true),
Username: xmaps.GetOrDefaultString(channelConfig, "username", xmaps.GetString(channelConfig, "senderAddress")),
Password: xmaps.GetString(channelConfig, "password"),
SenderAddress: xmaps.GetString(channelConfig, "senderAddress"),
ReceiverAddress: xmaps.GetString(channelConfig, "receiverAddress"),
})
case domain.NotifyChannelTypeGotify:
return pGotify.NewNotifierProvider(&pGotify.NotifierProviderConfig{
ServerUrl: xmaps.GetString(channelConfig, "url"),
Token: xmaps.GetString(channelConfig, "token"),
Priority: xmaps.GetOrDefaultInt64(channelConfig, "priority", 1),
})
case domain.NotifyChannelTypeLark:
return pLark.NewNotifierProvider(&pLark.NotifierProviderConfig{
WebhookUrl: xmaps.GetString(channelConfig, "webhookUrl"),
})
case domain.NotifyChannelTypeMattermost:
return pMattermost.NewNotifierProvider(&pMattermost.NotifierProviderConfig{
ServerUrl: xmaps.GetString(channelConfig, "serverUrl"),
ChannelId: xmaps.GetString(channelConfig, "channelId"),
Username: xmaps.GetString(channelConfig, "username"),
Password: xmaps.GetString(channelConfig, "password"),
})
case domain.NotifyChannelTypePushover:
return pPushover.NewNotifierProvider(&pPushover.NotifierProviderConfig{
Token: xmaps.GetString(channelConfig, "token"),
User: xmaps.GetString(channelConfig, "user"),
})
case domain.NotifyChannelTypePushPlus:
return pPushPlus.NewNotifierProvider(&pPushPlus.NotifierProviderConfig{
Token: xmaps.GetString(channelConfig, "token"),
})
case domain.NotifyChannelTypeServerChan:
return pServerChan.NewNotifierProvider(&pServerChan.NotifierProviderConfig{
ServerUrl: xmaps.GetString(channelConfig, "url"),
})
case domain.NotifyChannelTypeTelegram:
return pTelegram.NewNotifierProvider(&pTelegram.NotifierProviderConfig{
BotToken: xmaps.GetString(channelConfig, "apiToken"),
ChatId: xmaps.GetInt64(channelConfig, "chatId"),
})
case domain.NotifyChannelTypeWebhook:
return pWebhook.NewNotifierProvider(&pWebhook.NotifierProviderConfig{
WebhookUrl: xmaps.GetString(channelConfig, "url"),
AllowInsecureConnections: xmaps.GetBool(channelConfig, "allowInsecureConnections"),
})
case domain.NotifyChannelTypeWeCom:
return pWeCom.NewNotifierProvider(&pWeCom.NotifierProviderConfig{
WebhookUrl: xmaps.GetString(channelConfig, "webhookUrl"),
})
}
return nil, fmt.Errorf("unsupported notifier channel '%s'", channelConfig)
}
+9 -32
View File
@@ -4,44 +4,21 @@ import (
"context"
"fmt"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/internal/domain/dtos"
)
// Deprecated: v0.4.x 将废弃
const (
notifyTestTitle = "测试通知"
notifyTestBody = "欢迎使用 Certimate ,这是一条测试通知。"
notifyTestTitle = "[Certimate] Notification Test"
notifyTestBody = "Welcome to use Certimate!"
)
// Deprecated: v0.4.x 将废弃
type settingsRepository interface {
GetByName(ctx context.Context, name string) (*domain.Settings, error)
type NotifyService struct{}
func NewNotifyService() *NotifyService {
return &NotifyService{}
}
// Deprecated: v0.4.x 将废弃
type NotifyService struct {
settingsRepo settingsRepository
}
// Deprecated: v0.4.x 将废弃
func NewNotifyService(settingsRepo settingsRepository) *NotifyService {
return &NotifyService{
settingsRepo: settingsRepo,
}
}
// Deprecated: v0.4.x 将废弃
func (n *NotifyService) Test(ctx context.Context, req *dtos.NotifyTestPushReq) error {
settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels")
if err != nil {
return fmt.Errorf("failed to get notify channels settings: %w", err)
}
channelConfig, err := settings.GetNotifyChannelConfig(string(req.Channel))
if err != nil {
return fmt.Errorf("failed to get notify channel \"%s\" config: %w", req.Channel, err)
}
return SendToChannel(notifyTestTitle, notifyTestBody, string(req.Channel), channelConfig)
func (n *NotifyService) TestPush(ctx context.Context, req *dtos.NotifyTestPushReq) error {
// TODO: 测试通知
return fmt.Errorf("not implemented")
}
+2 -2
View File
@@ -11,7 +11,7 @@ import (
)
type certificateService interface {
ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error)
DownloadArchivedFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error)
ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error)
ValidatePrivateKey(ctx context.Context, req *dtos.CertificateValidatePrivateKeyReq) (*dtos.CertificateValidatePrivateKeyResp, error)
}
@@ -38,7 +38,7 @@ func (handler *CertificateHandler) archiveFile(e *core.RequestEvent) error {
return resp.Err(e, err)
}
if res, err := handler.service.ArchiveFile(e.Request.Context(), req); err != nil {
if res, err := handler.service.DownloadArchivedFile(e.Request.Context(), req); err != nil {
return resp.Err(e, err)
} else {
return resp.Ok(e, res)
+2 -2
View File
@@ -11,7 +11,7 @@ import (
)
type notifyService interface {
Test(ctx context.Context, req *dtos.NotifyTestPushReq) error
TestPush(ctx context.Context, req *dtos.NotifyTestPushReq) error
}
type NotifyHandler struct {
@@ -33,7 +33,7 @@ func (handler *NotifyHandler) test(e *core.RequestEvent) error {
return resp.Err(e, err)
}
if err := handler.service.Test(e.Request.Context(), req); err != nil {
if err := handler.service.TestPush(e.Request.Context(), req); err != nil {
return resp.Err(e, err)
}
+1 -1
View File
@@ -32,7 +32,7 @@ func Register(router *router.Router[*core.RequestEvent]) {
certificateSvc = certificate.NewCertificateService(certificateRepo, settingsRepo)
workflowSvc = workflow.NewWorkflowService(workflowRepo, workflowRunRepo, settingsRepo)
statisticsSvc = statistics.NewStatisticsService(statisticsRepo)
notifySvc = notify.NewNotifyService(settingsRepo)
notifySvc = notify.NewNotifyService()
group := router.Group("/api")
group.Bind(apis.RequireSuperuserAuth())
@@ -33,33 +33,6 @@ func (n *notifyNode) Process(ctx context.Context) error {
nodeCfg := n.node.GetConfigForNotify()
n.logger.Info("ready to send notification ...", slog.Any("config", nodeCfg))
if nodeCfg.Provider == "" {
// Deprecated: v0.4.x 将废弃
// 兼容旧版本的通知渠道
n.logger.Warn("WARNING! you are using the notification channel from global settings, which will be deprecated in the future")
// 获取通知配置
settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels")
if err != nil {
return err
}
// 获取通知渠道
channelConfig, err := settings.GetNotifyChannelConfig(nodeCfg.Channel)
if err != nil {
return err
}
// 发送通知
if err := notify.SendToChannel(nodeCfg.Subject, nodeCfg.Message, nodeCfg.Channel, channelConfig); err != nil {
n.logger.Warn("failed to send notification", slog.String("channel", nodeCfg.Channel))
return err
}
n.logger.Info("notification completed")
return nil
}
// 检测是否可以跳过本次执行
if skippable := n.checkCanSkip(ctx); skippable {
n.logger.Info(fmt.Sprintf("skip this notification, because all the previous nodes have been skipped"))
+1 -1
View File
@@ -59,7 +59,7 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
return
}
var settingsContent *domain.PersistenceSettingsContent
var settingsContent *domain.SettingsContentAsPersistence
json.Unmarshal([]byte(settings.Content), &settingsContent)
if settingsContent != nil && settingsContent.WorkflowRunsMaxDaysRetention != 0 {
ret, err := s.workflowRunRepo.DeleteWhere(
+2 -2
View File
@@ -2,7 +2,7 @@ import { ClientResponseError } from "pocketbase";
import { getPocketBase } from "@/repository/_pocketbase";
export const notifyTest = async (channel: string) => {
export const notifyTest = async (provider: string) => {
const pb = getPocketBase();
const resp = await pb.send<BaseResponse>("/api/notify/test", {
@@ -11,7 +11,7 @@ export const notifyTest = async (channel: string) => {
"Content-Type": "application/json",
},
body: {
channel,
provider,
},
});
@@ -1,126 +0,0 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useRequest } from "ahooks";
import { Button, Form, Input, Skeleton, message, notification } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { ClientResponseError } from "pocketbase";
import { z } from "zod";
import Show from "@/components/Show";
import { type NotifyTemplatesSettingsContent, SETTINGS_NAMES, defaultNotifyTemplate } from "@/domain/settings";
import { useAntdForm } from "@/hooks";
import { get as getSettings, save as saveSettings } from "@/repository/settings";
import { getErrMsg } from "@/utils/error";
export interface NotifyTemplateFormProps {
className?: string;
style?: React.CSSProperties;
}
const NotifyTemplateForm = ({ className, style }: NotifyTemplateFormProps) => {
const { t } = useTranslation();
const [messageApi, MessageContextHolder] = message.useMessage();
const [notificationApi, NotificationContextHolder] = notification.useNotification();
const formSchema = z.object({
subject: z
.string()
.min(1, t("settings.notification.template.form.subject.placeholder"))
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
message: z
.string()
.min(1, t("settings.notification.template.form.message.placeholder"))
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
});
const formRule = createSchemaFieldRule(formSchema);
const {
form: formInst,
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: defaultNotifyTemplate,
onSubmit: async (values) => {
try {
const settings = await getSettings<NotifyTemplatesSettingsContent>(SETTINGS_NAMES.NOTIFY_TEMPLATES);
await saveSettings<NotifyTemplatesSettingsContent>({
...settings,
content: {
notifyTemplates: [values],
},
});
messageApi.success(t("common.text.operation_succeeded"));
} catch (err) {
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
throw err;
}
},
});
const [formChanged, setFormChanged] = useState(false);
const { loading } = useRequest(
() => {
return getSettings<NotifyTemplatesSettingsContent>(SETTINGS_NAMES.NOTIFY_TEMPLATES);
},
{
onError: (err) => {
if (err instanceof ClientResponseError && err.isAbort) {
return;
}
console.error(err);
},
onFinally: (_, resp) => {
const template = resp?.content?.notifyTemplates?.[0] ?? defaultNotifyTemplate;
formInst.setFieldsValue(template);
},
}
);
const handleInputChange = () => {
setFormChanged(true);
};
return (
<div className={className} style={style}>
{MessageContextHolder}
{NotificationContextHolder}
<Show when={!loading} fallback={<Skeleton active />}>
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
<Form.Item
name="subject"
label={t("settings.notification.template.form.subject.label")}
extra={t("settings.notification.template.form.subject.extra")}
rules={[formRule]}
>
<Input placeholder={t("settings.notification.template.form.subject.placeholder")} onChange={handleInputChange} />
</Form.Item>
<Form.Item
name="message"
label={t("settings.notification.template.form.message.label")}
extra={t("settings.notification.template.form.message.extra")}
rules={[formRule]}
>
<Input.TextArea
autoSize={{ minRows: 3, maxRows: 10 }}
placeholder={t("settings.notification.template.form.message.placeholder")}
onChange={handleInputChange}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" disabled={!formChanged} loading={formPending}>
{t("common.button.save")}
</Button>
</Form.Item>
</Form>
</Show>
</div>
);
};
export default NotifyTemplateForm;
@@ -8,12 +8,12 @@ import { getErrMsg } from "@/utils/error";
export interface NotifyTestButtonProps {
className?: string;
style?: React.CSSProperties;
channel: string;
disabled?: boolean;
provider: string;
size?: ButtonProps["size"];
}
const NotifyTestButton = ({ className, style, channel, disabled, size }: NotifyTestButtonProps) => {
const NotifyTestButton = ({ className, style, provider, disabled, size }: NotifyTestButtonProps) => {
const { t } = useTranslation();
const [messageApi, MessageContextHolder] = message.useMessage();
@@ -21,10 +21,10 @@ const NotifyTestButton = ({ className, style, channel, disabled, size }: NotifyT
const { loading, run: executeNotifyTest } = useRequest(
() => {
return notifyTest(channel);
return notifyTest(provider);
},
{
refreshDeps: [channel],
refreshDeps: [provider],
manual: true,
onSuccess: () => {
messageApi.success(t("settings.notification.push_test.pushed"));
-21
View File
@@ -2,11 +2,6 @@ import { type CAProviderType } from "./provider";
export const SETTINGS_NAMES = Object.freeze({
EMAILS: "emails",
NOTIFY_TEMPLATES: "notifyTemplates",
/**
* @deprecated
*/
NOTIFY_CHANNELS: "notifyChannels",
SSL_PROVIDER: "sslProvider",
PERSISTENCE: "persistence",
} as const);
@@ -24,22 +19,6 @@ export type EmailsSettingsContent = {
};
// #endregion
// #region Settings: NotifyTemplates
export type NotifyTemplatesSettingsContent = {
notifyTemplates: NotifyTemplate[];
};
export type NotifyTemplate = {
subject: string;
message: string;
};
export const defaultNotifyTemplate: NotifyTemplate = {
subject: "有 ${COUNT} 张证书即将过期",
message: "有 ${COUNT} 张证书即将过期,域名分别为 ${DOMAINS},请保持关注!",
};
// #endregion
// #region Settings: SSLProvider
export type SSLProviderSettingsContent = {
provider: CAProviderType;
-4
View File
@@ -210,10 +210,6 @@ export const defaultNodeConfigForDeploy = (): Partial<WorkflowNodeConfigForDeplo
export type WorkflowNodeConfigForNotify = {
subject: string;
message: string;
/**
* @deprecated
*/
channel?: string;
provider: string;
providerAccessId: string;
providerConfig?: Record<string, unknown>;