feat: rename domain to subjectAltNames

This commit is contained in:
Fu Diwei 2025-01-04 13:52:11 +08:00
parent 5387c373e0
commit 9246878d0e
13 changed files with 59 additions and 109 deletions

View File

@ -54,8 +54,8 @@ type Certificate struct {
}
type ApplyOption struct {
Domains string `json:"domains"`
ContactEmail string `json:"contactEmail"`
SubjectAltNames string `json:"subjectAltNames"`
AccessConfig string `json:"accessConfig"`
KeyAlgorithm string `json:"keyAlgorithm"`
Nameservers string `json:"nameservers"`
@ -132,8 +132,8 @@ func GetWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
}
applyConfig := &ApplyOption{
Domains: node.GetConfigString("domains"),
ContactEmail: node.GetConfigString("contactEmail"),
SubjectAltNames: node.GetConfigString("subjectAltNames"),
AccessConfig: access.Config,
KeyAlgorithm: node.GetConfigString("keyAlgorithm"),
Nameservers: node.GetConfigString("nameservers"),
@ -243,7 +243,7 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro
myUser.Registration = reg
}
domains := strings.Split(option.SubjectAltNames, ";")
domains := strings.Split(option.Domains, ";")
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,

View File

@ -83,7 +83,7 @@ func buildMsg(records []domain.Certificate) *domain.NotifyMessage {
domains := make([]string, count)
for i, record := range records {
domains[i] = record.SAN
domains[i] = record.SubjectAltNames
}
countStr := strconv.Itoa(count)

View File

@ -4,13 +4,10 @@ import (
"context"
"fmt"
"github.com/pocketbase/pocketbase/models"
"github.com/usual2970/certimate/internal/applicant"
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/repository"
)
/*
@ -47,8 +44,8 @@ const (
)
type DeployerOption struct {
DomainId string `json:"domainId"`
Domain string `json:"domain"`
NodeId string `json:"nodeId"`
Domains string `json:"domains"`
AccessConfig string `json:"accessConfig"`
AccessRecord *domain.Access `json:"-"`
DeployConfig domain.DeployConfig `json:"deployConfig"`
@ -62,66 +59,7 @@ type Deployer interface {
GetID() string
}
func Gets(record *models.Record, cert *applicant.Certificate) ([]Deployer, error) {
rs := make([]Deployer, 0)
if record.GetString("deployConfig") == "" {
return rs, nil
}
deployConfigs := make([]domain.DeployConfig, 0)
err := record.UnmarshalJSONField("deployConfig", &deployConfigs)
if err != nil {
return nil, fmt.Errorf("解析部署配置失败: %w", err)
}
if len(deployConfigs) == 0 {
return rs, nil
}
for _, deployConfig := range deployConfigs {
deployer, err := newWithDeployConfig(record, cert, deployConfig)
if err != nil {
return nil, err
}
rs = append(rs, deployer)
}
return rs, nil
}
func GetWithTypeAndOption(deployType string, option *DeployerOption) (Deployer, error) {
return newWithTypeAndOption(deployType, option)
}
func newWithDeployConfig(record *models.Record, cert *applicant.Certificate, deployConfig domain.DeployConfig) (Deployer, error) {
accessRepo := repository.NewAccessRepository()
access, err := accessRepo.GetById(context.Background(), deployConfig.ProviderAccessId)
if err != nil {
return nil, fmt.Errorf("获取access失败:%w", err)
}
option := &DeployerOption{
DomainId: record.Id,
Domain: record.GetString("domain"),
AccessConfig: access.Config,
AccessRecord: access,
DeployConfig: deployConfig,
}
if cert != nil {
option.Certificate = *cert
} else {
option.Certificate = applicant.Certificate{
Certificate: record.GetString("certificate"),
PrivateKey: record.GetString("privateKey"),
}
}
return newWithTypeAndOption(deployConfig.Provider, option)
}
func newWithTypeAndOption(deployType string, option *DeployerOption) (Deployer, error) {
deployer, logger, err := createDeployer(deployType, option.AccessRecord.Config, option.DeployConfig.NodeConfig)
if err != nil {
return nil, err

View File

@ -6,7 +6,7 @@ var ValidityDuration = time.Hour * 24 * 10
type Certificate struct {
Meta
SAN string `json:"san" db:"san"`
SubjectAltNames string `json:"san" db:"san"`
Certificate string `json:"certificate" db:"certificate"`
PrivateKey string `json:"privateKey" db:"privateKey"`
IssuerCertificate string `json:"issuerCertificate" db:"issuerCertificate"`

View File

@ -79,7 +79,7 @@ func (w *WorkflowOutputRepository) GetCertificate(ctx context.Context, nodeId st
Certificate: record.GetString("certificate"),
PrivateKey: record.GetString("privateKey"),
IssuerCertificate: record.GetString("issuerCertificate"),
SAN: record.GetString("san"),
SubjectAltNames: record.GetString("san"),
WorkflowOutputId: record.GetString("output"),
ExpireAt: record.GetDateTime("expireAt").Time(),
CertUrl: record.GetString("certUrl"),
@ -131,7 +131,7 @@ func (w *WorkflowOutputRepository) Save(ctx context.Context, output *domain.Work
certRecord.Set("certificate", certificate.Certificate)
certRecord.Set("privateKey", certificate.PrivateKey)
certRecord.Set("issuerCertificate", certificate.IssuerCertificate)
certRecord.Set("san", certificate.SAN)
certRecord.Set("san", certificate.SubjectAltNames)
certRecord.Set("output", certificate.WorkflowOutputId)
certRecord.Set("expireAt", certificate.ExpireAt)
certRecord.Set("certUrl", certificate.CertUrl)

View File

@ -96,7 +96,7 @@ func (a *applyNode) Run(ctx context.Context) error {
}
certificateRecord := &domain.Certificate{
SAN: strings.Join(cert.DNSNames, ";"),
SubjectAltNames: strings.Join(cert.DNSNames, ";"),
Certificate: certificate.Certificate,
PrivateKey: certificate.PrivateKey,
IssuerCertificate: certificate.IssuerCertificate,

View File

@ -66,8 +66,8 @@ func (d *deployNode) Run(ctx context.Context) error {
}
option := &deployer.DeployerOption{
DomainId: d.node.Id,
Domain: cert.SAN,
NodeId: d.node.Id,
Domains: cert.SubjectAltNames,
AccessConfig: access.Config,
AccessRecord: access,
Certificate: applicant.Certificate{

View File

@ -6,7 +6,15 @@ import { produce } from "immer";
import Show from "@/components/Show";
import { deployProvidersMap } from "@/domain/provider";
import { notifyChannelsMap } from "@/domain/settings";
import { WORKFLOW_TRIGGERS, type WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
import {
WORKFLOW_TRIGGERS,
type WorkflowNode,
type WorkflowNodeConfigAsApply,
type WorkflowNodeConfigAsDeploy,
type WorkflowNodeConfigAsNotify,
type WorkflowNodeConfigAsStart,
WorkflowNodeType,
} from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
@ -32,28 +40,31 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
switch (node.type) {
case WorkflowNodeType.Start: {
const config = (node.config as WorkflowNodeConfigAsStart) ?? {};
return (
<div className="flex items-center justify-between space-x-2">
<Typography.Text className="truncate">
{node.config?.trigger === WORKFLOW_TRIGGERS.AUTO
{config.trigger === WORKFLOW_TRIGGERS.AUTO
? t("workflow.props.trigger.auto")
: node.config?.trigger === WORKFLOW_TRIGGERS.MANUAL
: config.trigger === WORKFLOW_TRIGGERS.MANUAL
? t("workflow.props.trigger.manual")
: " "}
</Typography.Text>
<Typography.Text className="truncate" type="secondary">
{node.config?.trigger === WORKFLOW_TRIGGERS.AUTO ? (node.config?.triggerCron as string) : ""}
{config.trigger === WORKFLOW_TRIGGERS.AUTO ? config.triggerCron : ""}
</Typography.Text>
</div>
);
}
case WorkflowNodeType.Apply: {
return <Typography.Text className="truncate">{(node.config?.domain as string) || " "}</Typography.Text>;
const config = (node.config as WorkflowNodeConfigAsApply) ?? {};
return <Typography.Text className="truncate">{config.domains || " "}</Typography.Text>;
}
case WorkflowNodeType.Deploy: {
const provider = deployProvidersMap.get(node.config?.provider as string);
const config = (node.config as WorkflowNodeConfigAsDeploy) ?? {};
const provider = deployProvidersMap.get(config.provider);
return (
<Space>
<Avatar src={provider?.icon} size="small" />
@ -63,7 +74,8 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
}
case WorkflowNodeType.Notify: {
const channel = notifyChannelsMap.get(node.config?.channel as string);
const config = (node.config as WorkflowNodeConfigAsNotify) ?? {};
const channel = notifyChannelsMap.get(config.channel as string);
return (
<div className="flex items-center justify-between space-x-2">
<Typography.Text className="truncate">{t(channel?.name ?? " ")}</Typography.Text>

View File

@ -12,7 +12,7 @@ import MultipleInput from "@/components/MultipleInput";
import AccessEditModal from "@/components/access/AccessEditModal";
import AccessSelect from "@/components/access/AccessSelect";
import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider";
import { type WorkflowApplyNodeConfig, type WorkflowNode } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigAsApply } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useAccessesStore } from "@/stores/access";
import { useContactEmailsStore } from "@/stores/contact";
@ -26,7 +26,7 @@ export type ApplyNodeFormProps = {
const MULTIPLE_INPUT_DELIMITER = ";";
const initFormModel = (): Partial<WorkflowApplyNodeConfig> => {
const initFormModel = (): Partial<WorkflowNodeConfigAsApply> => {
return {
keyAlgorithm: "RSA2048",
propagationTimeout: 60,
@ -43,12 +43,12 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
const { hidePanel } = usePanel();
const formSchema = z.object({
domain: z.string({ message: t("workflow_node.apply.form.domains.placeholder") }).refine((v) => {
domains: z.string({ message: t("workflow_node.apply.form.domains.placeholder") }).refine((v) => {
return String(v)
.split(MULTIPLE_INPUT_DELIMITER)
.every((e) => validDomainName(e, true));
}, t("common.errmsg.domain_invalid")),
email: z.string({ message: t("workflow_node.apply.form.contact_email.placeholder") }).email("common.errmsg.email_invalid"),
contactEmail: z.string({ message: t("workflow_node.apply.form.contact_email.placeholder") }).email("common.errmsg.email_invalid"),
providerAccessId: z
.string({ message: t("workflow_node.apply.form.provider_access.placeholder") })
.min(1, t("workflow_node.apply.form.provider_access.placeholder")),
@ -76,16 +76,16 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowApplyNodeConfig) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigAsApply) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await addEmail(values.email);
await addEmail(values.contactEmail);
await updateNode(
produce(node, (draft) => {
draft.config = {
provider: accesses.find((e) => e.id === values.providerAccessId)?.provider,
...values,
} as WorkflowApplyNodeConfig;
} as WorkflowNodeConfigAsApply;
draft.validated = true;
})
);
@ -93,13 +93,13 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
},
});
const [fieldDomains, setFieldDomains] = useState(node?.config?.domain as string);
const [fieldDomains, setFieldDomains] = useState(node?.config?.domains as string);
const [fieldNameservers, setFieldNameservers] = useState(node?.config?.nameservers as string);
const handleFieldDomainsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setFieldDomains(value);
formInst.setFieldValue("domain", value);
formInst.setFieldValue("domains", value);
};
const handleFieldNameserversChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@ -111,7 +111,7 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
return (
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
<Form.Item
name="domain"
name="domains"
label={t("workflow_node.apply.form.domains.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.domains.tooltip") }}></span>}
@ -132,7 +132,7 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
}
onFinish={(v) => {
setFieldDomains(v);
formInst.setFieldValue("domain", v);
formInst.setFieldValue("domains", v);
}}
/>
</Space.Compact>

View File

@ -12,7 +12,7 @@ import AccessSelect from "@/components/access/AccessSelect";
import DeployProviderPicker from "@/components/provider/DeployProviderPicker";
import DeployProviderSelect from "@/components/provider/DeployProviderSelect";
import { ACCESS_USAGES, DEPLOY_PROVIDERS, accessProvidersMap, deployProvidersMap } from "@/domain/provider";
import { type WorkflowDeployNodeConfig, type WorkflowNode } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigAsDeploy } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import { usePanel } from "../PanelProvider";
@ -44,7 +44,7 @@ export type DeployFormProps = {
node: WorkflowNode;
};
const initFormModel = (): Partial<WorkflowDeployNodeConfig> => {
const initFormModel = (): Partial<WorkflowNodeConfigAsDeploy> => {
return {};
};
@ -67,7 +67,7 @@ const DeployNodeForm = ({ node }: DeployFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowDeployNodeConfig) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigAsDeploy) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -8,7 +8,7 @@ import { produce } from "immer";
import { z } from "zod";
import { notifyChannelsMap } from "@/domain/settings";
import { type WorkflowNode, type WorkflowNotifyNodeConfig } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigAsNotify } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useNotifyChannelsStore } from "@/stores/notify";
import { useWorkflowStore } from "@/stores/workflow";
@ -18,7 +18,7 @@ export type NotifyNodeFormProps = {
node: WorkflowNode;
};
const initFormModel = (): Partial<WorkflowNotifyNodeConfig> => {
const initFormModel = (): Partial<WorkflowNodeConfigAsNotify> => {
return {
subject: "Completed!",
message: "Your workflow has been completed on Certimate.",
@ -57,7 +57,7 @@ const NotifyNodeForm = ({ node }: NotifyNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowNotifyNodeConfig) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigAsNotify) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -7,7 +7,7 @@ import { produce } from "immer";
import { z } from "zod";
import Show from "@/components/Show";
import { WORKFLOW_TRIGGERS, type WorkflowNode, type WorkflowStartNodeConfig } from "@/domain/workflow";
import { WORKFLOW_TRIGGERS, type WorkflowNode, type WorkflowNodeConfigAsStart } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import { getNextCronExecutions, validCronExpression } from "@/utils/cron";
@ -17,7 +17,7 @@ export type StartNodeFormProps = {
node: WorkflowNode;
};
const initFormModel = (): WorkflowStartNodeConfig => {
const initFormModel = (): WorkflowNodeConfigAsStart => {
return {
trigger: WORKFLOW_TRIGGERS.AUTO,
triggerCron: "0 0 * * *",
@ -54,7 +54,7 @@ const StartNodeForm = ({ node }: StartNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowStartNodeConfig) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigAsStart) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -92,14 +92,14 @@ export type WorkflowNode = {
validated?: boolean;
};
export type WorkflowStartNodeConfig = {
export type WorkflowNodeConfigAsStart = {
trigger: string;
triggerCron?: string;
};
export type WorkflowApplyNodeConfig = {
domain: string;
email: string;
export type WorkflowNodeConfigAsApply = {
domains: string;
contactEmail: string;
provider: string;
providerAccessId: string;
keyAlgorithm: string;
@ -108,22 +108,22 @@ export type WorkflowApplyNodeConfig = {
disableFollowCNAME?: boolean;
};
export type WorkflowDeployNodeConfig = {
export type WorkflowNodeConfigAsDeploy = {
provider: string;
providerAccessId: string;
certificate: string;
[key: string]: unknown;
};
export type WorkflowNotifyNodeConfig = {
export type WorkflowNodeConfigAsNotify = {
channel: string;
subject: string;
message: string;
};
export type WorkflowBranchNodeConfig = never;
export type WorkflowNodeConfigAsBranch = never;
export type WorkflowEndNodeConfig = never;
export type WorkflowNodeConfigAsEnd = never;
export type WorkflowNodeIO = {
name: string;