refactor: clean code

This commit is contained in:
Fu Diwei 2026-05-22 22:39:50 +08:00
parent e36e0ae123
commit 92084d96bc
22 changed files with 191 additions and 171 deletions

View File

@ -31,7 +31,7 @@ func NewACMEAccount(config *ACMEConfig, email string, register bool) (*ACMEAccou
ctx := context.Background()
accountRepo := repository.NewACMEAccountRepository()
account, err := accountRepo.GetByCAAndEmail(ctx, string(config.CAProvider), config.CADirUrl, email)
account, err := accountRepo.GetByCAAndEmail(ctx, config.CAProvider.String(), config.CADirUrl, email)
if err != nil {
if !domain.IsRecordNotFoundError(err) {
return nil, fmt.Errorf("failed to get acme account record: %w", err)
@ -55,7 +55,7 @@ func NewACMEAccount(config *ACMEConfig, email string, register bool) (*ACMEAccou
}
account = &ACMEAccount{
CA: string(config.CAProvider),
CA: config.CAProvider.String(),
Email: email,
PrivateKey: keyPEM,
ACMEDirUrl: config.CADirUrl,
@ -116,7 +116,7 @@ func NewACMEAccountWithSingleFlight(config *ACMEConfig, email string) (*ACMEAcco
return nil, fmt.Errorf("the email is empty")
}
resp, err, _ := registrationSg.Do(fmt.Sprintf("%s|%s|%s", string(config.CAProvider), config.CADirUrl, email), func() (any, error) {
resp, err, _ := registrationSg.Do(fmt.Sprintf("%s|%s|%s", config.CAProvider, config.CADirUrl, email), func() (any, error) {
return NewACMEAccount(config, email, true)
})
if err != nil {

View File

@ -58,14 +58,14 @@ func NewACMEConfig(options *ACMEConfigOptions) (*ACMEConfig, error) {
settings, _ := settingsRepo.GetByName(context.Background(), domain.SettingsNameSSLProvider)
if settings != nil {
sslProviderSettings := settings.Content.AsSSLProvider()
caProvider = string(sslProviderSettings.Provider)
caProvider = sslProviderSettings.Provider.String()
caAccessConfig = sslProviderSettings.Configs[sslProviderSettings.Provider]
}
}
if caProvider == "" {
// default CA: Let's Encrypt
caProvider = string(domain.AccessProviderTypeLetsEncrypt)
caProvider = domain.AccessProviderTypeLetsEncrypt.String()
}
if caAccessConfig == nil {
@ -79,23 +79,23 @@ func NewACMEConfig(options *ACMEConfigOptions) (*ACMEConfig, error) {
if err := xmaps.Populate(caAccessConfig, &credentials); err != nil {
return nil, err
} else if strings.EqualFold(credentials.ValidationType, "DV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"DV"]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSectigo.String()+"DV"]
} else if strings.EqualFold(credentials.ValidationType, "OV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"OV"]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSectigo.String()+"OV"]
} else if strings.EqualFold(credentials.ValidationType, "EV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"EV"]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSectigo.String()+"EV"]
} else {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSectigo.String()]
}
case domain.CAProviderTypeSSLCom:
// TODO: fix this after migrate lego to v5
if strings.HasPrefix(string(options.CertifierKeyType), "RSA") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)+"RSA"]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSSLCom.String()+"RSA"]
} else if strings.HasPrefix(string(options.CertifierKeyType), "EC") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)+"ECC"]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSSLCom.String()+"ECC"]
} else {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)]
ca.CADirUrl = acmeDirUrls[domain.CAProviderTypeSSLCom.String()]
}
case domain.CAProviderTypeACMECA:
@ -108,7 +108,7 @@ func NewACMEConfig(options *ACMEConfigOptions) (*ACMEConfig, error) {
ca.CADirUrl = credentials.Endpoint
default:
endpoint := acmeDirUrls[string(ca.CAProvider)]
endpoint := acmeDirUrls[ca.CAProvider.String()]
if endpoint == "" {
return nil, fmt.Errorf("the endpoint of the ACME CA provider is empty")
}

View File

@ -57,16 +57,26 @@ func (s *CertificateService) DownloadCertificate(ctx context.Context, req *dtos.
zipWriter := zip.NewWriter(&buf)
defer zipWriter.Close()
var bytes []byte
switch strings.ToUpper(req.CertificateFormat) {
case "", string(domain.CertificateFormatTypePEM):
var zipBytes []byte
switch req.FileFormat {
case "", domain.CertificateFormatTypePEM:
{
serverCertPEM, intermediaCertPEM, err := xcert.ExtractCertificatesFromPEM(certificate.Certificate)
if err != nil {
return nil, fmt.Errorf("failed to extract certs: %w", err)
}
certWriter, err := zipWriter.Create(fmt.Sprintf("%s.pem", canonicalName))
keyWriter, err := zipWriter.Create(fmt.Sprintf("%s.key", canonicalName))
if err != nil {
return nil, err
} else {
_, err = keyWriter.Write([]byte(certificate.PrivateKey))
if err != nil {
return nil, err
}
}
certWriter, err := zipWriter.Create(fmt.Sprintf("%s.crt", canonicalName))
if err != nil {
return nil, err
} else {
@ -96,25 +106,15 @@ func (s *CertificateService) DownloadCertificate(ctx context.Context, req *dtos.
}
}
keyWriter, err := zipWriter.Create(fmt.Sprintf("%s.key", canonicalName))
if err != nil {
return nil, err
} else {
_, err = keyWriter.Write([]byte(certificate.PrivateKey))
if err != nil {
return nil, err
}
}
err = zipWriter.Close()
if err != nil {
return nil, err
}
bytes = buf.Bytes()
zipBytes = buf.Bytes()
}
case string(domain.CertificateFormatTypePFX):
case domain.CertificateFormatTypePFX:
{
const pfxPassword = "certimate"
@ -148,10 +148,10 @@ func (s *CertificateService) DownloadCertificate(ctx context.Context, req *dtos.
return nil, err
}
bytes = buf.Bytes()
zipBytes = buf.Bytes()
}
case string(domain.CertificateFormatTypeJKS):
case domain.CertificateFormatTypeJKS:
{
const jksPassword = "certimate"
@ -185,7 +185,7 @@ func (s *CertificateService) DownloadCertificate(ctx context.Context, req *dtos.
return nil, err
}
bytes = buf.Bytes()
zipBytes = buf.Bytes()
}
default:
@ -193,8 +193,7 @@ func (s *CertificateService) DownloadCertificate(ctx context.Context, req *dtos.
}
resp := &dtos.CertificateDownloadResp{
FileFormat: "zip",
FileBytes: bytes,
ZipBytes: zipBytes,
}
return resp, nil
}

View File

@ -78,6 +78,10 @@ func (c *Certificate) PopulateFromPEM(certPEM, privkeyPEM string) *Certificate {
type CertificateSourceType string
func (t CertificateSourceType) String() string {
return string(t)
}
const (
CertificateSourceTypeRequest = CertificateSourceType("request")
CertificateSourceTypeUpload = CertificateSourceType("upload")
@ -85,15 +89,9 @@ const (
type CertificateKeyAlgorithmType string
const (
CertificateKeyAlgorithmTypeRSA2048 = CertificateKeyAlgorithmType("RSA2048")
CertificateKeyAlgorithmTypeRSA3072 = CertificateKeyAlgorithmType("RSA3072")
CertificateKeyAlgorithmTypeRSA4096 = CertificateKeyAlgorithmType("RSA4096")
CertificateKeyAlgorithmTypeRSA8192 = CertificateKeyAlgorithmType("RSA8192")
CertificateKeyAlgorithmTypeEC256 = CertificateKeyAlgorithmType("EC256")
CertificateKeyAlgorithmTypeEC384 = CertificateKeyAlgorithmType("EC384")
CertificateKeyAlgorithmTypeEC512 = CertificateKeyAlgorithmType("EC512")
)
func (t CertificateKeyAlgorithmType) String() string {
return string(t)
}
func (t CertificateKeyAlgorithmType) ToLegoKeyType() (certcrypto.KeyType, error) {
keyTypeMap := map[CertificateKeyAlgorithmType]certcrypto.KeyType{
@ -112,8 +110,22 @@ func (t CertificateKeyAlgorithmType) ToLegoKeyType() (certcrypto.KeyType, error)
return certcrypto.RSA2048, fmt.Errorf("unsupported key algorithm type: '%s'", t)
}
const (
CertificateKeyAlgorithmTypeRSA2048 = CertificateKeyAlgorithmType("RSA2048")
CertificateKeyAlgorithmTypeRSA3072 = CertificateKeyAlgorithmType("RSA3072")
CertificateKeyAlgorithmTypeRSA4096 = CertificateKeyAlgorithmType("RSA4096")
CertificateKeyAlgorithmTypeRSA8192 = CertificateKeyAlgorithmType("RSA8192")
CertificateKeyAlgorithmTypeEC256 = CertificateKeyAlgorithmType("EC256")
CertificateKeyAlgorithmTypeEC384 = CertificateKeyAlgorithmType("EC384")
CertificateKeyAlgorithmTypeEC512 = CertificateKeyAlgorithmType("EC512")
)
type CertificateFormatType string
func (t CertificateFormatType) String() string {
return string(t)
}
const (
CertificateFormatTypePEM CertificateFormatType = "PEM"
CertificateFormatTypePFX CertificateFormatType = "PFX"

View File

@ -1,13 +1,16 @@
package dtos
import (
"github.com/certimate-go/certimate/internal/domain"
)
type CertificateDownloadReq struct {
CertificateId string `json:"-"`
CertificateFormat string `json:"format"`
CertificateId string `json:"-"`
FileFormat domain.CertificateFormatType `json:"format"`
}
type CertificateDownloadResp struct {
FileBytes []byte `json:"fileBytes"`
FileFormat string `json:"fileFormat"`
ZipBytes []byte `json:"zipBytes"`
}
type CertificateRevokeReq struct {

View File

@ -1,8 +1,12 @@
package dtos
import (
"github.com/certimate-go/certimate/internal/domain"
)
type NotifyTestPushReq struct {
Provider string `json:"provider"`
AccessId string `json:"accessId"`
Provider domain.NotificationProviderType `json:"provider"`
AccessId string `json:"accessId"`
}
type NotifyTestPushResp struct{}

View File

@ -1,6 +1,8 @@
package dtos
import "github.com/certimate-go/certimate/internal/domain"
import (
"github.com/certimate-go/certimate/internal/domain"
)
type WorkflowStartRunReq struct {
WorkflowId string `json:"-"`
@ -12,8 +14,8 @@ type WorkflowStartRunResp struct {
}
type WorkflowCancelRunReq struct {
WorkflowId string `json:"-"`
RunId string `json:"-"`
WorkflowId string `bind:"path" json:"-"`
RunId string `bind:"path" json:"-"`
}
type WorkflowCancelRunResp struct{}

View File

@ -2,6 +2,10 @@ package domain
type AccessProviderType string
func (t AccessProviderType) String() string {
return string(t)
}
/*
授权提供商类型常量值
@ -129,6 +133,10 @@ const (
type CAProviderType string
func (t CAProviderType) String() string {
return string(t)
}
/*
证书颁发机构提供商常量值
短横线前的部分始终等于授权提供商类型
@ -152,6 +160,10 @@ const (
type ACMEDns01ProviderType string
func (t ACMEDns01ProviderType) String() string {
return string(t)
}
/*
ACME DNS-01 提供商常量值
短横线前的部分始终等于授权提供商类型
@ -240,6 +252,10 @@ const (
type ACMEHttp01ProviderType string
func (t ACMEHttp01ProviderType) String() string {
return string(t)
}
/*
ACME HTTP-01 提供商常量值
短横线前的部分始终等于授权提供商类型
@ -256,6 +272,10 @@ const (
type DeploymentProviderType string
func (t DeploymentProviderType) String() string {
return string(t)
}
/*
部署证书主机提供商常量值
短横线前的部分始终等于授权提供商类型
@ -398,6 +418,10 @@ const (
type NotificationProviderType string
func (t NotificationProviderType) String() string {
return string(t)
}
/*
消息通知提供商常量值
短横线前的部分始终等于授权提供商类型

View File

@ -74,6 +74,10 @@ func (g *WorkflowGraph) Clone() *WorkflowGraph {
type WorkflowTriggerType string
func (t WorkflowTriggerType) String() string {
return string(t)
}
const (
WorkflowTriggerTypeScheduled = WorkflowTriggerType("scheduled")
WorkflowTriggerTypeManual = WorkflowTriggerType("manual")
@ -88,6 +92,10 @@ type WorkflowNode struct {
type WorkflowNodeType string
func (t WorkflowNodeType) String() string {
return string(t)
}
const (
WorkflowNodeTypeStart = WorkflowNodeType("start")
WorkflowNodeTypeEnd = WorkflowNodeType("end")
@ -149,7 +157,7 @@ func (c WorkflowNodeConfig) AsBizApply() WorkflowNodeConfigForBizApply {
ProviderAccessId: xmaps.GetString(c, "providerAccessId"),
ProviderConfig: xmaps.GetKVMapAny(c, "providerConfig"),
KeySource: xmaps.GetOrDefaultString(c, "keySource", "auto"),
KeyAlgorithm: xmaps.GetOrDefaultString(c, "keyAlgorithm", string(CertificateKeyAlgorithmTypeRSA2048)),
KeyAlgorithm: xmaps.GetOrDefaultString(c, "keyAlgorithm", CertificateKeyAlgorithmTypeRSA2048.String()),
KeyContent: xmaps.GetString(c, "keyContent"),
CAProvider: xmaps.GetString(c, "caProvider"),
CAProviderAccessId: xmaps.GetString(c, "caProviderAccessId"),

View File

@ -19,6 +19,10 @@ type WorkflowRun struct {
type WorkflowRunStatusType string
func (t WorkflowRunStatusType) String() string {
return string(t)
}
const (
WorkflowRunStatusTypePending WorkflowRunStatusType = "pending"
WorkflowRunStatusTypeProcessing WorkflowRunStatusType = "processing"

View File

@ -36,7 +36,7 @@ func (n *NotifyService) TestPush(ctx context.Context, req *dtos.NotifyTestPushRe
notifier := NewClient()
notifyReq := &SendNotificationRequest{
Provider: req.Provider,
Provider: req.Provider.String(),
ProviderAccessConfig: accessConfig,
ProviderExtendedConfig: make(map[string]any),
Subject: testSubject,

View File

@ -117,14 +117,14 @@ func (r *CertificateRepository) Save(ctx context.Context, certificate *domain.Ce
}
}
record.Set("source", string(certificate.Source))
record.Set("source", certificate.Source.String())
record.Set("subjectAltNames", certificate.SubjectAltNames)
record.Set("serialNumber", certificate.SerialNumber)
record.Set("certificate", certificate.Certificate)
record.Set("privateKey", certificate.PrivateKey)
record.Set("issuerOrg", certificate.IssuerOrg)
record.Set("issuerCertificate", certificate.IssuerCertificate)
record.Set("keyAlgorithm", string(certificate.KeyAlgorithm))
record.Set("keyAlgorithm", certificate.KeyAlgorithm.String())
record.Set("validityNotBefore", certificate.ValidityNotBefore)
record.Set("validityNotAfter", certificate.ValidityNotAfter)
record.Set("validityInterval", certificate.ValidityInterval)

View File

@ -24,7 +24,7 @@ func (r *WorkflowRepository) ListEnabledScheduled(ctx context.Context) ([]*domai
"enabled={:enabled} && trigger={:trigger}",
"-created",
0, 0,
dbx.Params{"enabled": true, "trigger": string(domain.WorkflowTriggerTypeScheduled)},
dbx.Params{"enabled": true, "trigger": domain.WorkflowTriggerTypeScheduled.String()},
)
if err != nil {
return nil, err
@ -76,7 +76,7 @@ func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow
record.Set("name", workflow.Name)
record.Set("description", workflow.Description)
record.Set("trigger", string(workflow.Trigger))
record.Set("trigger", workflow.Trigger.String())
record.Set("triggerCron", workflow.TriggerCron)
record.Set("enabled", workflow.Enabled)
record.Set("graphDraft", workflow.GraphDraft)
@ -84,7 +84,7 @@ func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow
record.Set("hasDraft", workflow.HasDraft)
record.Set("hasContent", workflow.HasContent)
record.Set("lastRunRef", workflow.LastRunId)
record.Set("lastRunStatus", string(workflow.LastRunStatus))
record.Set("lastRunStatus", workflow.LastRunStatus.String())
record.Set("lastRunTime", workflow.LastRunTime)
if err := app.GetApp().Save(record); err != nil {
return workflow, err

View File

@ -50,8 +50,8 @@ func (r *WorkflowRunRepository) Save(ctx context.Context, workflowRun *domain.Wo
}
record.Set("workflowRef", workflowRun.WorkflowId)
record.Set("trigger", string(workflowRun.Trigger))
record.Set("status", string(workflowRun.Status))
record.Set("trigger", workflowRun.Trigger.String())
record.Set("status", workflowRun.Status.String())
record.Set("startedAt", workflowRun.StartedAt)
record.Set("endedAt", workflowRun.EndedAt)
record.Set("graph", workflowRun.Graph)
@ -88,8 +88,8 @@ func (r *WorkflowRunRepository) SaveWithCascading(ctx context.Context, workflowR
err = app.GetApp().RunInTransaction(func(txApp core.App) error {
record.Set("workflowRef", workflowRun.WorkflowId)
record.Set("trigger", string(workflowRun.Trigger))
record.Set("status", string(workflowRun.Status))
record.Set("trigger", workflowRun.Trigger.String())
record.Set("status", workflowRun.Status.String())
record.Set("startedAt", workflowRun.StartedAt)
record.Set("endedAt", workflowRun.EndedAt)
record.Set("graph", workflowRun.Graph)

View File

@ -59,7 +59,7 @@ func onWorkflowRecordCreateOrUpdate(_ context.Context, record *core.Record) erro
triggerCron := record.GetString("triggerCron")
// 如果非定时触发或未启用,移除定时任务
if !enabled || trigger != string(domain.WorkflowTriggerTypeScheduled) {
if !enabled || trigger != domain.WorkflowTriggerTypeScheduled.String() {
scheduler.Remove(fmt.Sprintf("workflow#%s", record.Id))
return nil
}

View File

@ -150,8 +150,8 @@ func (s *WorkflowService) cleanupHistoryRuns(ctx context.Context) error {
if persistenceSettings.WorkflowRunsRetentionMaxDays != 0 {
ret, err := s.workflowRunRepo.DeleteWhere(
ctx,
dbx.NewExp(fmt.Sprintf("status!='%s'", string(domain.WorkflowRunStatusTypePending))),
dbx.NewExp(fmt.Sprintf("status!='%s'", string(domain.WorkflowRunStatusTypeProcessing))),
dbx.NewExp(fmt.Sprintf("status!='%s'", domain.WorkflowRunStatusTypePending)),
dbx.NewExp(fmt.Sprintf("status!='%s'", domain.WorkflowRunStatusTypeProcessing)),
dbx.NewExp(fmt.Sprintf("endedAt<DATETIME('now', '-%d days')", persistenceSettings.WorkflowRunsRetentionMaxDays)),
)
if err != nil {

39
ui/src/api/_api.ts Normal file
View File

@ -0,0 +1,39 @@
import { ClientResponseError, type SendOptions } from "pocketbase";
import { getPocketBase } from "@/repository/_pocketbase";
const pb = getPocketBase();
type Options = Pick<SendOptions, "body" | "headers"> & {
url: string;
};
export async function get<T = any>({ url, ...opts }: Options) {
const resp = await pb.send<BaseResponse<T>>(url, {
method: "GET",
...opts,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
}
export async function post<T = any>({ url, headers, ...opts }: Options) {
const resp = await pb.send<BaseResponse<T>>(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers,
},
...opts,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
}

View File

@ -1,44 +1,22 @@
import { ClientResponseError } from "pocketbase";
import { type CertificateFormatType } from "@/domain/certificate";
import { getPocketBase } from "@/repository/_pocketbase";
export const download = async (certificateId: string, format?: CertificateFormatType) => {
const pb = getPocketBase();
import { post as httpPost } from "./_api";
export const download = (certificateId: string, format?: CertificateFormatType) => {
type RespData = {
fileBytes: string;
zipBytes: string;
};
const resp = await pb.send<BaseResponse<RespData>>(`/api/certificates/${encodeURIComponent(certificateId)}/download`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
return httpPost<RespData>({
url: `/api/certificates/${encodeURIComponent(certificateId)}/download`,
body: {
format: format,
fileFormat: format,
},
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};
export const revoke = async (certificateId: string) => {
const pb = getPocketBase();
const resp = await pb.send<BaseResponse>(`/api/certificates/${encodeURIComponent(certificateId)}/revoke`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
export const revoke = (certificateId: string) => {
return httpPost({
url: `/api/certificates/${encodeURIComponent(certificateId)}/revoke`,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};

View File

@ -1,24 +1,11 @@
import { ClientResponseError } from "pocketbase";
import { getPocketBase } from "@/repository/_pocketbase";
import { post as httpPost } from "./_api";
export const testPushNotification = async ({ provider, accessId }: { provider: string; accessId: string }) => {
const pb = getPocketBase();
const resp = await pb.send<BaseResponse>("/api/notifications/test", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
return httpPost({
url: `/api/notifications/test`,
body: {
provider,
accessId,
},
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};

View File

@ -1,18 +1,11 @@
import { ClientResponseError } from "pocketbase";
import { type Statistics } from "@/domain/statistics";
import { getPocketBase } from "@/repository/_pocketbase";
import { get as httpGet } from "./_api";
export const get = async () => {
const pb = getPocketBase();
type RespData = Statistics;
const resp = await pb.send<BaseResponse<Statistics>>("/api/statistics", {
method: "GET",
return httpGet<RespData>({
url: `/api/statistics`,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};

View File

@ -1,63 +1,30 @@
import { ClientResponseError } from "pocketbase";
import { WORKFLOW_TRIGGERS } from "@/domain/workflow";
import { getPocketBase } from "@/repository/_pocketbase";
export const getStats = async () => {
const pb = getPocketBase();
import { get as httpGet, post as httpPost } from "./_api";
export const getStats = () => {
type RespData = {
concurrency: number;
pendingRunIds: string[];
processingRunIds: string[];
};
const resp = await pb.send<BaseResponse<RespData>>(`/api/workflows/stats`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
return httpGet<RespData>({
url: `/api/workflows/stats`,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};
export const startRun = async (workflowId: string) => {
const pb = getPocketBase();
const resp = await pb.send<BaseResponse>(`/api/workflows/${encodeURIComponent(workflowId)}/runs`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
export const startRun = (workflowId: string) => {
return httpPost({
url: `/api/workflows/${encodeURIComponent(workflowId)}/runs`,
body: {
trigger: WORKFLOW_TRIGGERS.MANUAL,
},
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};
export const cancelRun = async (workflowId: string, runId: string) => {
const pb = getPocketBase();
const resp = await pb.send<BaseResponse>(`/api/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cancel`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
export const cancelRun = (workflowId: string, runId: string) => {
return httpPost({
url: `/api/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cancel`,
});
if (resp.code != 0) {
throw new ClientResponseError({ status: resp.code, response: resp, data: {} });
}
return resp;
};

View File

@ -22,7 +22,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
const handleDownloadClick = async (format: CertificateFormatType) => {
try {
const res = await downloadCertificate(data.id, format);
const bstr = atob(res.data.fileBytes);
const bstr = atob(res.data.zipBytes);
const u8arr = Uint8Array.from(bstr, (ch) => ch.charCodeAt(0));
const blob = new Blob([u8arr], { type: "application/zip" });
saveAs(blob, `${data.id}-${data.subjectAltNames}.zip`);