Skip to content

Commit ac68fd0

Browse files
committed
refactor(cert): introducing new management page
1. User can now view the latest renew logs of the certain certificate. 2. Add manually renew button in certificate modify page for managed certificate (auto cert)
1 parent 7c47f08 commit ac68fd0

36 files changed

+1921
-1299
lines changed

api/certificate/certificate.go

Lines changed: 59 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,31 @@ package certificate
33
import (
44
"github.com/0xJacky/Nginx-UI/api"
55
"github.com/0xJacky/Nginx-UI/api/cosy"
6-
"github.com/0xJacky/Nginx-UI/api/sites"
76
"github.com/0xJacky/Nginx-UI/internal/cert"
87
"github.com/0xJacky/Nginx-UI/model"
8+
"github.com/0xJacky/Nginx-UI/query"
99
"github.com/gin-gonic/gin"
1010
"github.com/spf13/cast"
1111
"net/http"
1212
"os"
13-
"path/filepath"
1413
)
1514

16-
func GetCertList(c *gin.Context) {
17-
cosy.Core[model.Cert](c).SetFussy("name", "domain").PagingList()
15+
type APICertificate struct {
16+
*model.Cert
17+
SSLCertificate string `json:"ssl_certificate,omitempty"`
18+
SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
19+
CertificateInfo *cert.Info `json:"certificate_info,omitempty"`
1820
}
1921

20-
func getCert(c *gin.Context, certModel *model.Cert) {
21-
type resp struct {
22-
*model.Cert
23-
SSLCertificate string `json:"ssl_certificate"`
24-
SSLCertificateKey string `json:"ssl_certificate_key"`
25-
CertificateInfo *sites.CertificateInfo `json:"certificate_info,omitempty"`
26-
}
27-
22+
func Transformer(certModel *model.Cert) (certificate *APICertificate) {
2823
var sslCertificationBytes, sslCertificationKeyBytes []byte
29-
var certificateInfo *sites.CertificateInfo
24+
var certificateInfo *cert.Info
3025
if certModel.SSLCertificatePath != "" {
3126
if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {
3227
sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)
3328
}
3429

35-
pubKey, err := cert.GetCertInfo(certModel.SSLCertificatePath)
36-
37-
if err != nil {
38-
api.ErrHandler(c, err)
39-
return
40-
}
41-
42-
certificateInfo = &sites.CertificateInfo{
43-
SubjectName: pubKey.Subject.CommonName,
44-
IssuerName: pubKey.Issuer.CommonName,
45-
NotAfter: pubKey.NotAfter,
46-
NotBefore: pubKey.NotBefore,
47-
}
30+
certificateInfo, _ = cert.GetCertInfo(certModel.SSLCertificatePath)
4831
}
4932

5033
if certModel.SSLCertificateKeyPath != "" {
@@ -53,32 +36,48 @@ func getCert(c *gin.Context, certModel *model.Cert) {
5336
}
5437
}
5538

56-
c.JSON(http.StatusOK, resp{
57-
certModel,
58-
string(sslCertificationBytes),
59-
string(sslCertificationKeyBytes),
60-
certificateInfo,
61-
})
39+
return &APICertificate{
40+
Cert: certModel,
41+
SSLCertificate: string(sslCertificationBytes),
42+
SSLCertificateKey: string(sslCertificationKeyBytes),
43+
CertificateInfo: certificateInfo,
44+
}
45+
}
46+
47+
func GetCertList(c *gin.Context) {
48+
cosy.Core[model.Cert](c).SetFussy("name", "domain").SetTransformer(func(m *model.Cert) any {
49+
50+
info, _ := cert.GetCertInfo(m.SSLCertificatePath)
51+
52+
return APICertificate{
53+
Cert: m,
54+
CertificateInfo: info,
55+
}
56+
}).PagingList()
6257
}
6358

6459
func GetCert(c *gin.Context) {
65-
certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id")))
60+
q := query.Cert
61+
62+
certModel, err := q.FirstByID(cast.ToInt(c.Param("id")))
6663

6764
if err != nil {
6865
api.ErrHandler(c, err)
6966
return
7067
}
7168

72-
getCert(c, &certModel)
69+
c.JSON(http.StatusOK, Transformer(certModel))
7370
}
7471

7572
func AddCert(c *gin.Context) {
7673
var json struct {
7774
Name string `json:"name"`
7875
SSLCertificatePath string `json:"ssl_certificate_path" binding:"required"`
7976
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
80-
SSLCertification string `json:"ssl_certification"`
81-
SSLCertificationKey string `json:"ssl_certification_key"`
77+
SSLCertificate string `json:"ssl_certificate"`
78+
SSLCertificateKey string `json:"ssl_certificate_key"`
79+
ChallengeMethod string `json:"challenge_method"`
80+
DnsCredentialID int `json:"dns_credential_id"`
8281
}
8382
if !api.BindAndValid(c, &json) {
8483
return
@@ -87,6 +86,8 @@ func AddCert(c *gin.Context) {
8786
Name: json.Name,
8887
SSLCertificatePath: json.SSLCertificatePath,
8988
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
89+
ChallengeMethod: json.ChallengeMethod,
90+
DnsCredentialID: json.DnsCredentialID,
9091
}
9192

9293
err := certModel.Insert()
@@ -96,35 +97,21 @@ func AddCert(c *gin.Context) {
9697
return
9798
}
9899

99-
err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
100-
if err != nil {
101-
api.ErrHandler(c, err)
102-
return
100+
content := &cert.Content{
101+
SSLCertificatePath: json.SSLCertificatePath,
102+
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
103+
SSLCertificate: json.SSLCertificate,
104+
SSLCertificateKey: json.SSLCertificateKey,
103105
}
104106

105-
err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
107+
err = content.WriteFile()
108+
106109
if err != nil {
107110
api.ErrHandler(c, err)
108111
return
109112
}
110113

111-
if json.SSLCertification != "" {
112-
err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644)
113-
if err != nil {
114-
api.ErrHandler(c, err)
115-
return
116-
}
117-
}
118-
119-
if json.SSLCertificationKey != "" {
120-
err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644)
121-
if err != nil {
122-
api.ErrHandler(c, err)
123-
return
124-
}
125-
}
126-
127-
getCert(c, certModel)
114+
c.JSON(http.StatusOK, Transformer(certModel))
128115
}
129116

130117
func ModifyCert(c *gin.Context) {
@@ -136,13 +123,17 @@ func ModifyCert(c *gin.Context) {
136123
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
137124
SSLCertificate string `json:"ssl_certificate"`
138125
SSLCertificateKey string `json:"ssl_certificate_key"`
126+
ChallengeMethod string `json:"challenge_method"`
127+
DnsCredentialID int `json:"dns_credential_id"`
139128
}
140129

141130
if !api.BindAndValid(c, &json) {
142131
return
143132
}
144133

145-
certModel, err := model.FirstCertByID(id)
134+
q := query.Cert
135+
136+
certModel, err := q.FirstByID(id)
146137
if err != nil {
147138
api.ErrHandler(c, err)
148139
return
@@ -152,41 +143,29 @@ func ModifyCert(c *gin.Context) {
152143
Name: json.Name,
153144
SSLCertificatePath: json.SSLCertificatePath,
154145
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
146+
ChallengeMethod: json.ChallengeMethod,
147+
DnsCredentialID: json.DnsCredentialID,
155148
})
156149

157150
if err != nil {
158151
api.ErrHandler(c, err)
159152
return
160153
}
161154

162-
err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
163-
if err != nil {
164-
api.ErrHandler(c, err)
165-
return
155+
content := &cert.Content{
156+
SSLCertificatePath: json.SSLCertificatePath,
157+
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
158+
SSLCertificate: json.SSLCertificate,
159+
SSLCertificateKey: json.SSLCertificateKey,
166160
}
167161

168-
err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
162+
err = content.WriteFile()
163+
169164
if err != nil {
170165
api.ErrHandler(c, err)
171166
return
172167
}
173168

174-
if json.SSLCertificate != "" {
175-
err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertificate), 0644)
176-
if err != nil {
177-
api.ErrHandler(c, err)
178-
return
179-
}
180-
}
181-
182-
if json.SSLCertificateKeyPath != "" {
183-
err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificateKey), 0644)
184-
if err != nil {
185-
api.ErrHandler(c, err)
186-
return
187-
}
188-
}
189-
190169
GetCert(c)
191170
}
192171

api/certificate/issue.go

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type IssueCertResponse struct {
2424
SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
2525
}
2626

27-
func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
27+
func handleIssueCertLogChan(conn *websocket.Conn, log *cert.Logger, logChan chan string) {
2828
defer func() {
2929
if err := recover(); err != nil {
3030
logger.Error(err)
@@ -33,6 +33,8 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
3333

3434
for logString := range logChan {
3535

36+
log.Info(logString)
37+
3638
err := conn.WriteJSON(IssueCertResponse{
3739
Status: Info,
3840
Message: logString,
@@ -42,7 +44,6 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
4244
logger.Error(err)
4345
return
4446
}
45-
4647
}
4748
}
4849

@@ -65,9 +66,9 @@ func IssueCert(c *gin.Context) {
6566
}(ws)
6667

6768
// read
68-
buffer := &cert.ConfigPayload{}
69+
payload := &cert.ConfigPayload{}
6970

70-
err = ws.ReadJSON(buffer)
71+
err = ws.ReadJSON(payload)
7172

7273
if err != nil {
7374
logger.Error(err)
@@ -84,15 +85,20 @@ func IssueCert(c *gin.Context) {
8485
logChan := make(chan string, 1)
8586
errChan := make(chan error, 1)
8687

87-
go cert.IssueCert(buffer, logChan, errChan)
88+
log := &cert.Logger{}
89+
log.SetCertModel(&certModel)
90+
91+
go cert.IssueCert(payload, logChan, errChan)
8892

89-
go handleIssueCertLogChan(ws, logChan)
93+
go handleIssueCertLogChan(ws, log, logChan)
9094

9195
// block, until errChan closes
9296
for err = range errChan {
93-
errLog := &cert.AutoCertErrorLog{}
94-
errLog.SetCertModel(&certModel)
95-
errLog.Exit("issue cert", err)
97+
98+
log.Error(err)
99+
100+
// Save logs to db
101+
log.Exit()
96102

97103
err = ws.WriteJSON(IssueCertResponse{
98104
Status: Error,
@@ -107,12 +113,12 @@ func IssueCert(c *gin.Context) {
107113
return
108114
}
109115

110-
certDirName := strings.Join(buffer.ServerName, "_")
116+
certDirName := strings.Join(payload.ServerName, "_")
111117
sslCertificatePath := nginx.GetConfPath("ssl", certDirName, "fullchain.cer")
112118
sslCertificateKeyPath := nginx.GetConfPath("ssl", certDirName, "private.key")
113119

114120
err = certModel.Updates(&model.Cert{
115-
Domains: buffer.ServerName,
121+
Domains: payload.ServerName,
116122
SSLCertificatePath: sslCertificatePath,
117123
SSLCertificateKeyPath: sslCertificateKeyPath,
118124
})
@@ -126,7 +132,8 @@ func IssueCert(c *gin.Context) {
126132
return
127133
}
128134

129-
certModel.ClearLog()
135+
// Save logs to db
136+
log.Exit()
130137

131138
err = ws.WriteJSON(IssueCertResponse{
132139
Status: Success,

api/sites/domain.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
package sites
22

33
import (
4-
"github.com/0xJacky/Nginx-UI/api"
5-
"github.com/0xJacky/Nginx-UI/internal/cert"
6-
"github.com/0xJacky/Nginx-UI/internal/config"
7-
"github.com/0xJacky/Nginx-UI/internal/helper"
8-
"github.com/0xJacky/Nginx-UI/internal/logger"
9-
"github.com/0xJacky/Nginx-UI/internal/nginx"
10-
"github.com/0xJacky/Nginx-UI/model"
11-
"github.com/0xJacky/Nginx-UI/query"
12-
"github.com/gin-gonic/gin"
13-
"github.com/sashabaranov/go-openai"
14-
"net/http"
15-
"os"
16-
"strings"
4+
"github.com/0xJacky/Nginx-UI/api"
5+
"github.com/0xJacky/Nginx-UI/internal/cert"
6+
"github.com/0xJacky/Nginx-UI/internal/config"
7+
"github.com/0xJacky/Nginx-UI/internal/helper"
8+
"github.com/0xJacky/Nginx-UI/internal/logger"
9+
"github.com/0xJacky/Nginx-UI/internal/nginx"
10+
"github.com/0xJacky/Nginx-UI/model"
11+
"github.com/0xJacky/Nginx-UI/query"
12+
"github.com/gin-gonic/gin"
13+
"github.com/sashabaranov/go-openai"
14+
"net/http"
15+
"os"
16+
"strings"
1717
)
1818

1919
func GetDomains(c *gin.Context) {
@@ -146,7 +146,7 @@ func GetDomain(c *gin.Context) {
146146

147147
c.Set("maybe_error", "")
148148

149-
certInfoMap := make(map[int]CertificateInfo)
149+
certInfoMap := make(map[int]*cert.Info)
150150
for serverIdx, server := range nginxConfig.Servers {
151151
for _, directive := range server.Directives {
152152
if directive.Directive == "ssl_certificate" {
@@ -158,12 +158,7 @@ func GetDomain(c *gin.Context) {
158158
break
159159
}
160160

161-
certInfoMap[serverIdx] = CertificateInfo{
162-
SubjectName: pubKey.Subject.CommonName,
163-
IssuerName: pubKey.Issuer.CommonName,
164-
NotAfter: pubKey.NotAfter,
165-
NotBefore: pubKey.NotBefore,
166-
}
161+
certInfoMap[serverIdx] = pubKey
167162

168163
break
169164
}

0 commit comments

Comments
 (0)