| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 | package certificateimport (	"net/http"	"os"	"github.com/0xJacky/Nginx-UI/internal/cert"	"github.com/0xJacky/Nginx-UI/internal/helper"	"github.com/0xJacky/Nginx-UI/internal/nginx"	"github.com/0xJacky/Nginx-UI/internal/notification"	"github.com/0xJacky/Nginx-UI/model"	"github.com/0xJacky/Nginx-UI/query"	"github.com/gin-gonic/gin"	"github.com/go-acme/lego/v4/certcrypto"	"github.com/spf13/cast"	"github.com/uozi-tech/cosy"	"github.com/uozi-tech/cosy/logger")type APICertificate struct {	*model.Cert	SSLCertificate    string     `json:"ssl_certificate,omitempty"`	SSLCertificateKey string     `json:"ssl_certificate_key,omitempty"`	CertificateInfo   *cert.Info `json:"certificate_info,omitempty"`}func Transformer(certModel *model.Cert) (certificate *APICertificate) {	var sslCertificationBytes, sslCertificationKeyBytes []byte	var certificateInfo *cert.Info	if certModel.SSLCertificatePath != "" &&		helper.IsUnderDirectory(certModel.SSLCertificatePath, nginx.GetConfPath()) {		if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {			sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)			if !cert.IsCertificate(string(sslCertificationBytes)) {				sslCertificationBytes = []byte{}			}		}		certificateInfo, _ = cert.GetCertInfo(certModel.SSLCertificatePath)	}	if certModel.SSLCertificateKeyPath != "" &&		helper.IsUnderDirectory(certModel.SSLCertificateKeyPath, nginx.GetConfPath()) {		if _, err := os.Stat(certModel.SSLCertificateKeyPath); err == nil {			sslCertificationKeyBytes, _ = os.ReadFile(certModel.SSLCertificateKeyPath)			if !cert.IsPrivateKey(string(sslCertificationKeyBytes)) {				sslCertificationKeyBytes = []byte{}			}		}	}	return &APICertificate{		Cert:              certModel,		SSLCertificate:    string(sslCertificationBytes),		SSLCertificateKey: string(sslCertificationKeyBytes),		CertificateInfo:   certificateInfo,	}}func GetCertList(c *gin.Context) {	s := logger.NewSessionLogger(c)	s.Info("GetCertList")	cosy.Core[model.Cert](c).SetFussy("name", "domain").		SetTransformer(func(m *model.Cert) any {			info, _ := cert.GetCertInfo(m.SSLCertificatePath)			return APICertificate{				Cert:            m,				CertificateInfo: info,			}		}).PagingList()}func GetCert(c *gin.Context) {	q := query.Cert	id := cast.ToUint64(c.Param("id"))	if contextId, ok := c.Get("id"); ok {		id = cast.ToUint64(contextId)	}	certModel, err := q.FirstByID(id)	if err != nil {		cosy.ErrHandler(c, err)		return	}	c.JSON(http.StatusOK, Transformer(certModel))}func AddCert(c *gin.Context) {	cosy.Core[model.Cert](c).		SetValidRules(gin.H{			"name":                       "omitempty",			"ssl_certificate_path":       "required,certificate_path",			"ssl_certificate_key_path":   "required,privatekey_path",			"ssl_certificate":            "omitempty,certificate",			"ssl_certificate_key":        "omitempty,privatekey",			"key_type":                   "omitempty,auto_cert_key_type",			"challenge_method":           "omitempty,oneof=http01 dns01",			"dns_credential_id":          "omitempty",			"acme_user_id":               "omitempty",			"sync_node_ids":              "omitempty",			"must_staple":                "omitempty",			"lego_disable_cname_support": "omitempty",			"revoke_old":                 "omitempty",		}).		BeforeExecuteHook(func(ctx *cosy.Ctx[model.Cert]) {			sslCertificate := cast.ToString(ctx.Payload["ssl_certificate"])			// Detect and set certificate type			if sslCertificate != "" {				keyType, err := cert.GetKeyType(sslCertificate)				if err == nil && keyType != "" {					// Set KeyType based on certificate type					switch keyType {					case "2048":						ctx.Model.KeyType = certcrypto.RSA2048					case "3072":						ctx.Model.KeyType = certcrypto.RSA3072					case "4096":						ctx.Model.KeyType = certcrypto.RSA4096					case "P256":						ctx.Model.KeyType = certcrypto.EC256					case "P384":						ctx.Model.KeyType = certcrypto.EC384					}				}			}		}).		ExecutedHook(func(ctx *cosy.Ctx[model.Cert]) {			sslCertificate := cast.ToString(ctx.Payload["ssl_certificate"])			sslCertificateKey := cast.ToString(ctx.Payload["ssl_certificate_key"])			if sslCertificate != "" && sslCertificateKey != "" {				content := &cert.Content{					SSLCertificatePath:    ctx.Model.SSLCertificatePath,					SSLCertificateKeyPath: ctx.Model.SSLCertificateKeyPath,					SSLCertificate:        sslCertificate,					SSLCertificateKey:     sslCertificateKey,				}				err := content.WriteFile()				if err != nil {					ctx.AbortWithError(err)					return				}			}			err := cert.SyncToRemoteServer(&ctx.Model)			if err != nil {				notification.Error("Sync Certificate Error", err.Error(), nil)				return			}			ctx.Context.Set("id", ctx.Model.ID)		}).		SetNextHandler(GetCert).		Create()}func ModifyCert(c *gin.Context) {	cosy.Core[model.Cert](c).		SetValidRules(gin.H{			"name":                       "omitempty",			"ssl_certificate_path":       "required,certificate_path",			"ssl_certificate_key_path":   "required,privatekey_path",			"ssl_certificate":            "omitempty,certificate",			"ssl_certificate_key":        "omitempty,privatekey",			"key_type":                   "omitempty,auto_cert_key_type",			"challenge_method":           "omitempty,oneof=http01 dns01",			"dns_credential_id":          "omitempty",			"acme_user_id":               "omitempty",			"sync_node_ids":              "omitempty",			"must_staple":                "omitempty",			"lego_disable_cname_support": "omitempty",			"revoke_old":                 "omitempty",		}).		BeforeExecuteHook(func(ctx *cosy.Ctx[model.Cert]) {			sslCertificate := cast.ToString(ctx.Payload["ssl_certificate"])			// Detect and set certificate type			if sslCertificate != "" {				keyType, err := cert.GetKeyType(sslCertificate)				if err == nil && keyType != "" {					// Set KeyType based on certificate type					switch keyType {					case "2048":						ctx.Model.KeyType = certcrypto.RSA2048					case "3072":						ctx.Model.KeyType = certcrypto.RSA3072					case "4096":						ctx.Model.KeyType = certcrypto.RSA4096					case "P256":						ctx.Model.KeyType = certcrypto.EC256					case "P384":						ctx.Model.KeyType = certcrypto.EC384					}				}			}		}).		ExecutedHook(func(ctx *cosy.Ctx[model.Cert]) {			sslCertificate := cast.ToString(ctx.Payload["ssl_certificate"])			sslCertificateKey := cast.ToString(ctx.Payload["ssl_certificate_key"])			content := &cert.Content{				SSLCertificatePath:    ctx.Model.SSLCertificatePath,				SSLCertificateKeyPath: ctx.Model.SSLCertificateKeyPath,				SSLCertificate:        sslCertificate,				SSLCertificateKey:     sslCertificateKey,			}			err := content.WriteFile()			if err != nil {				ctx.AbortWithError(err)				return			}			err = cert.SyncToRemoteServer(&ctx.Model)			if err != nil {				notification.Error("Sync Certificate Error", err.Error(), nil)				return			}		}).		SetNextHandler(GetCert).		Modify()}func RemoveCert(c *gin.Context) {	cosy.Core[model.Cert](c).Destroy()}func SyncCertificate(c *gin.Context) {	var json cert.SyncCertificatePayload	if !cosy.BindAndValid(c, &json) {		return	}	certModel := &model.Cert{		Name:                  json.Name,		SSLCertificatePath:    json.SSLCertificatePath,		SSLCertificateKeyPath: json.SSLCertificateKeyPath,		KeyType:               json.KeyType,		AutoCert:              model.AutoCertSync,	}	db := model.UseDB()	err := db.Where(certModel).FirstOrCreate(certModel).Error	if err != nil {		cosy.ErrHandler(c, err)		return	}	content := &cert.Content{		SSLCertificatePath:    json.SSLCertificatePath,		SSLCertificateKeyPath: json.SSLCertificateKeyPath,		SSLCertificate:        json.SSLCertificate,		SSLCertificateKey:     json.SSLCertificateKey,	}	err = content.WriteFile()	if err != nil {		cosy.ErrHandler(c, err)		return	}	nginx.Reload()	c.JSON(http.StatusOK, gin.H{		"message": "ok",	})}
 |