feat: download certificate archive
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -152,6 +152,6 @@ type WorkflowNodeIOValueSelector struct {
|
||||
}
|
||||
|
||||
type WorkflowRunReq struct {
|
||||
WorkflowId string `json:"workflowId"`
|
||||
WorkflowId string `json:"-"`
|
||||
Trigger WorkflowTriggerType `json:"trigger"`
|
||||
}
|
||||
|
||||
42
internal/rest/handlers/certificate.go
Normal file
42
internal/rest/handlers/certificate.go
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user