feat: download certificate archive

This commit is contained in:
Fu Diwei
2025-01-18 07:07:50 +08:00
parent d28b89f03e
commit d5e4ea385d
16 changed files with 265 additions and 139 deletions

View File

@@ -1,6 +1,8 @@
package certificate
import (
"archive/zip"
"bytes"
"context"
"encoding/json"
"strconv"
@@ -9,6 +11,7 @@ import (
"github.com/usual2970/certimate/internal/app"
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/notify"
"github.com/usual2970/certimate/internal/pkg/utils/certs"
"github.com/usual2970/certimate/internal/repository"
)
@@ -18,6 +21,7 @@ const (
)
type certificateRepository interface {
GetById(ctx context.Context, id string) (*domain.Certificate, error)
ListExpireSoon(ctx context.Context) ([]*domain.Certificate, error)
}
@@ -51,6 +55,126 @@ func (s *CertificateService) InitSchedule(ctx context.Context) error {
return nil
}
func (s *CertificateService) ArchiveFile(ctx context.Context, req *domain.CertificateArchiveFileReq) ([]byte, error) {
certificate, err := s.repo.GetById(ctx, req.CertificateId)
if err != nil {
return nil, err
}
var buf bytes.Buffer
zipWriter := zip.NewWriter(&buf)
defer zipWriter.Close()
switch strings.ToUpper(req.Format) {
case "", "PEM":
{
certWriter, err := zipWriter.Create("certbundle.pem")
if err != nil {
return nil, err
}
_, err = certWriter.Write([]byte(certificate.Certificate))
if err != nil {
return nil, err
}
keyWriter, err := zipWriter.Create("privkey.pem")
if err != nil {
return nil, err
}
_, err = keyWriter.Write([]byte(certificate.PrivateKey))
if err != nil {
return nil, err
}
err = zipWriter.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
case "PFX":
{
const pfxPassword = "certimate"
certPFX, err := certs.TransformCertificateFromPEMToPFX(certificate.Certificate, certificate.PrivateKey, pfxPassword)
if err != nil {
return nil, err
}
certWriter, err := zipWriter.Create("cert.pfx")
if err != nil {
return nil, err
}
_, err = certWriter.Write(certPFX)
if err != nil {
return nil, err
}
keyWriter, err := zipWriter.Create("pfx-password.txt")
if err != nil {
return nil, err
}
_, err = keyWriter.Write([]byte(pfxPassword))
if err != nil {
return nil, err
}
err = zipWriter.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
case "JKS":
{
const jksPassword = "certimate"
certJKS, err := certs.TransformCertificateFromPEMToJKS(certificate.Certificate, certificate.PrivateKey, jksPassword, jksPassword, jksPassword)
if err != nil {
return nil, err
}
certWriter, err := zipWriter.Create("cert.jks")
if err != nil {
return nil, err
}
_, err = certWriter.Write(certJKS)
if err != nil {
return nil, err
}
keyWriter, err := zipWriter.Create("jks-password.txt")
if err != nil {
return nil, err
}
_, err = keyWriter.Write([]byte(jksPassword))
if err != nil {
return nil, err
}
err = zipWriter.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
default:
return nil, domain.ErrInvalidParams
}
}
func buildExpireSoonNotification(certificates []*domain.Certificate) *struct {
Subject string
Message string

View File

@@ -25,3 +25,8 @@ type Certificate struct {
WorkflowOutputId string `json:"workflowOutputId" db:"workflowOutputId"`
DeletedAt *time.Time `json:"deleted" db:"deleted"`
}
type CertificateArchiveFileReq struct {
CertificateId string `json:"-"`
Format string `json:"format"`
}

View File

@@ -152,6 +152,6 @@ type WorkflowNodeIOValueSelector struct {
}
type WorkflowRunReq struct {
WorkflowId string `json:"workflowId"`
WorkflowId string `json:"-"`
Trigger WorkflowTriggerType `json:"trigger"`
}

View File

@@ -0,0 +1,42 @@
package handlers
import (
"context"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/router"
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/rest/resp"
)
type certificateService interface {
ArchiveFile(ctx context.Context, req *domain.CertificateArchiveFileReq) ([]byte, error)
}
type CertificateHandler struct {
service certificateService
}
func NewCertificateHandler(router *router.RouterGroup[*core.RequestEvent], service certificateService) {
handler := &CertificateHandler{
service: service,
}
group := router.Group("/certificates")
group.POST("/{id}/archive", handler.run)
}
func (handler *CertificateHandler) run(e *core.RequestEvent) error {
req := &domain.CertificateArchiveFileReq{}
req.CertificateId = e.Request.PathValue("id")
if err := e.BindBody(req); err != nil {
return resp.Err(e, err)
}
if bt, err := handler.service.ArchiveFile(e.Request.Context(), req); err != nil {
return resp.Err(e, err)
} else {
return resp.Ok(e, bt)
}
}

View File

@@ -24,12 +24,13 @@ func NewWorkflowHandler(router *router.RouterGroup[*core.RequestEvent], service
service: service,
}
group := router.Group("/workflow")
group.POST("/run", handler.run)
group := router.Group("/workflows")
group.POST("/{id}/run", handler.run)
}
func (handler *WorkflowHandler) run(e *core.RequestEvent) error {
req := &domain.WorkflowRunReq{}
req.WorkflowId = e.Request.PathValue("id")
if err := e.BindBody(req); err != nil {
return resp.Err(e, err)
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/router"
"github.com/usual2970/certimate/internal/certificate"
"github.com/usual2970/certimate/internal/notify"
"github.com/usual2970/certimate/internal/repository"
"github.com/usual2970/certimate/internal/rest/handlers"
@@ -15,14 +16,15 @@ import (
)
var (
notifySvc *notify.NotifyService
workflowSvc *workflow.WorkflowService
statisticsSvc *statistics.StatisticsService
certificateSvc *certificate.CertificateService
workflowSvc *workflow.WorkflowService
statisticsSvc *statistics.StatisticsService
notifySvc *notify.NotifyService
)
func Register(router *router.Router[*core.RequestEvent]) {
notifyRepo := repository.NewSettingsRepository()
notifySvc = notify.NewNotifyService(notifyRepo)
certificateRepo := repository.NewCertificateRepository()
certificateSvc = certificate.NewCertificateService(certificateRepo)
workflowRepo := repository.NewWorkflowRepository()
workflowSvc = workflow.NewWorkflowService(workflowRepo)
@@ -30,11 +32,15 @@ func Register(router *router.Router[*core.RequestEvent]) {
statisticsRepo := repository.NewStatisticsRepository()
statisticsSvc = statistics.NewStatisticsService(statisticsRepo)
notifyRepo := repository.NewSettingsRepository()
notifySvc = notify.NewNotifyService(notifyRepo)
group := router.Group("/api")
group.Bind(apis.RequireSuperuserAuth())
handlers.NewCertificateHandler(group, certificateSvc)
handlers.NewWorkflowHandler(group, workflowSvc)
handlers.NewNotifyHandler(group, notifySvc)
handlers.NewStatisticsHandler(group, statisticsSvc)
handlers.NewNotifyHandler(group, notifySvc)
}
func Unregister() {