refactor: clean code

This commit is contained in:
Fu Diwei 2025-02-11 19:31:24 +08:00
parent f3c7d096bc
commit 94408e8a9f
5 changed files with 58 additions and 35 deletions

View File

@ -5,7 +5,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"errors" "fmt"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -59,7 +59,7 @@ func (s *CertificateService) InitSchedule(ctx context.Context) error {
return nil return nil
} }
func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) ([]byte, error) { func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error) {
certificate, err := s.certRepo.GetById(ctx, req.CertificateId) certificate, err := s.certRepo.GetById(ctx, req.CertificateId)
if err != nil { if err != nil {
return nil, err return nil, err
@ -69,6 +69,10 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
zipWriter := zip.NewWriter(&buf) zipWriter := zip.NewWriter(&buf)
defer zipWriter.Close() defer zipWriter.Close()
resp := &dtos.CertificateArchiveFileResp{
FileFormat: "zip",
}
switch strings.ToUpper(req.Format) { switch strings.ToUpper(req.Format) {
case "", "PEM": case "", "PEM":
{ {
@ -97,7 +101,8 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
return nil, err return nil, err
} }
return buf.Bytes(), nil resp.FileBytes = buf.Bytes()
return resp, nil
} }
case "PFX": case "PFX":
@ -134,7 +139,8 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
return nil, err return nil, err
} }
return buf.Bytes(), nil resp.FileBytes = buf.Bytes()
return resp, nil
} }
case "JKS": case "JKS":
@ -171,7 +177,8 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
return nil, err return nil, err
} }
return buf.Bytes(), nil resp.FileBytes = buf.Bytes()
return resp, nil
} }
default: default:
@ -180,25 +187,30 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
} }
func (s *CertificateService) ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error) { func (s *CertificateService) ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error) {
info, err := certs.ParseCertificateFromPEM(req.Certificate) certX509, err := certs.ParseCertificateFromPEM(req.Certificate)
if err != nil {
return nil, err
} else if time.Now().After(certX509.NotAfter) {
return nil, fmt.Errorf("certificate has expired at %s", certX509.NotAfter.UTC().Format(time.RFC3339))
}
return &dtos.CertificateValidateCertificateResp{
IsValid: true,
Domains: strings.Join(certX509.DNSNames, ";"),
}, nil
}
func (s *CertificateService) ValidatePrivateKey(ctx context.Context, req *dtos.CertificateValidatePrivateKeyReq) (*dtos.CertificateValidatePrivateKeyResp, error) {
_, err := certcrypto.ParsePEMPrivateKey([]byte(req.PrivateKey))
if err != nil { if err != nil {
return nil, err return nil, err
} }
if time.Now().After(info.NotAfter) { return &dtos.CertificateValidatePrivateKeyResp{
return nil, errors.New("证书已过期") IsValid: true,
}
return &dtos.CertificateValidateCertificateResp{
Domains: strings.Join(info.DNSNames, ";"),
}, nil }, nil
} }
func (s *CertificateService) ValidatePrivateKey(ctx context.Context, req *dtos.CertificateValidatePrivateKeyReq) error {
_, err := certcrypto.ParsePEMPrivateKey([]byte(req.PrivateKey))
return err
}
func buildExpireSoonNotification(certificates []*domain.Certificate) *struct { func buildExpireSoonNotification(certificates []*domain.Certificate) *struct {
Subject string Subject string
Message string Message string

View File

@ -5,22 +5,24 @@ type CertificateArchiveFileReq struct {
Format string `json:"format"` Format string `json:"format"`
} }
type CertificateArchiveFileResp struct {
FileBytes []byte `json:"fileBytes"`
FileFormat string `json:"fileFormat"`
}
type CertificateValidateCertificateReq struct { type CertificateValidateCertificateReq struct {
Certificate string `json:"certificate"` Certificate string `json:"certificate"`
} }
type CertificateValidateCertificateResp struct { type CertificateValidateCertificateResp struct {
Domains string `json:"domains"` IsValid bool `json:"isValid"`
Domains string `json:"domains,omitempty"`
} }
type CertificateValidatePrivateKeyReq struct { type CertificateValidatePrivateKeyReq struct {
PrivateKey string `json:"privateKey"` PrivateKey string `json:"privateKey"`
} }
type CertificateUploadReq struct { type CertificateValidatePrivateKeyResp struct {
WorkflowId string `json:"workflowId"` IsValid bool `json:"isValid"`
WorkflowNodeId string `json:"workflowNodeId"`
CertificateId string `json:"certificateId"`
Certificate string `json:"certificate"`
PrivateKey string `json:"privateKey"`
} }

View File

@ -11,9 +11,9 @@ import (
) )
type certificateService interface { type certificateService interface {
ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) ([]byte, error) ArchiveFile(ctx context.Context, req *dtos.CertificateArchiveFileReq) (*dtos.CertificateArchiveFileResp, error)
ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error) ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error)
ValidatePrivateKey(ctx context.Context, req *dtos.CertificateValidatePrivateKeyReq) error ValidatePrivateKey(ctx context.Context, req *dtos.CertificateValidatePrivateKeyReq) (*dtos.CertificateValidatePrivateKeyResp, error)
} }
type CertificateHandler struct { type CertificateHandler struct {
@ -38,10 +38,10 @@ func (handler *CertificateHandler) archiveFile(e *core.RequestEvent) error {
return resp.Err(e, err) return resp.Err(e, err)
} }
if bt, err := handler.service.ArchiveFile(e.Request.Context(), req); err != nil { if res, err := handler.service.ArchiveFile(e.Request.Context(), req); err != nil {
return resp.Err(e, err) return resp.Err(e, err)
} else { } else {
return resp.Ok(e, bt) return resp.Ok(e, res)
} }
} }
@ -51,10 +51,10 @@ func (handler *CertificateHandler) validateCertificate(e *core.RequestEvent) err
return resp.Err(e, err) return resp.Err(e, err)
} }
if rs, err := handler.service.ValidateCertificate(e.Request.Context(), req); err != nil { if res, err := handler.service.ValidateCertificate(e.Request.Context(), req); err != nil {
return resp.Err(e, err) return resp.Err(e, err)
} else { } else {
return resp.Ok(e, rs) return resp.Ok(e, res)
} }
} }
@ -64,9 +64,9 @@ func (handler *CertificateHandler) validatePrivateKey(e *core.RequestEvent) erro
return resp.Err(e, err) return resp.Err(e, err)
} }
if err := handler.service.ValidatePrivateKey(e.Request.Context(), req); err != nil { if res, err := handler.service.ValidatePrivateKey(e.Request.Context(), req); err != nil {
return resp.Err(e, err) return resp.Err(e, err)
} else { } else {
return resp.Ok(e, nil) return resp.Ok(e, res)
} }
} }

View File

@ -3,10 +3,14 @@ import { ClientResponseError } from "pocketbase";
import { type CertificateFormatType } from "@/domain/certificate"; import { type CertificateFormatType } from "@/domain/certificate";
import { getPocketBase } from "@/repository/_pocketbase"; import { getPocketBase } from "@/repository/_pocketbase";
type ArchiveRespData = {
fileBytes: string;
};
export const archive = async (certificateId: string, format?: CertificateFormatType) => { export const archive = async (certificateId: string, format?: CertificateFormatType) => {
const pb = getPocketBase(); const pb = getPocketBase();
const resp = await pb.send<BaseResponse<string>>(`/api/certificates/${encodeURIComponent(certificateId)}/archive`, { const resp = await pb.send<BaseResponse<ArchiveRespData>>(`/api/certificates/${encodeURIComponent(certificateId)}/archive`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -24,6 +28,7 @@ export const archive = async (certificateId: string, format?: CertificateFormatT
}; };
type ValidateCertificateResp = { type ValidateCertificateResp = {
isValid: boolean;
domains: string; domains: string;
}; };
@ -46,9 +51,13 @@ export const validateCertificate = async (certificate: string) => {
return resp; return resp;
}; };
type ValidatePrivateKeyResp = {
isValid: boolean;
};
export const validatePrivateKey = async (privateKey: string) => { export const validatePrivateKey = async (privateKey: string) => {
const pb = getPocketBase(); const pb = getPocketBase();
const resp = await pb.send<BaseResponse>(`/api/certificates/validate/private-key`, { const resp = await pb.send<BaseResponse<ValidatePrivateKeyResp>>(`/api/certificates/validate/private-key`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

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