Skip to content

Commit 86bc75f

Browse files
feat: 证书增加下载功能 (#3090)
Refs #2767
1 parent 59c216c commit 86bc75f

File tree

10 files changed

+308
-9
lines changed

10 files changed

+308
-9
lines changed

backend/app/api/v1/website_ssl.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package v1
22

33
import (
4+
"net/http"
5+
"net/url"
46
"reflect"
7+
"strconv"
58

69
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
710
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -213,3 +216,32 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
213216
}
214217
helper.SuccessWithData(c, nil)
215218
}
219+
220+
// @Tags Website SSL
221+
// @Summary Download SSL file
222+
// @Description 下载证书文件
223+
// @Accept json
224+
// @Param request body request.WebsiteResourceReq true "request"
225+
// @Success 200
226+
// @Security ApiKeyAuth
227+
// @Router /websites/ssl/download [post]
228+
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"下载证书文件 [domain]","formatEN":"download ssl file [domain]"}
229+
func (b *BaseApi) DownloadWebsiteSSL(c *gin.Context) {
230+
var req request.WebsiteResourceReq
231+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
232+
return
233+
}
234+
file, err := websiteSSLService.DownloadFile(req.ID)
235+
if err != nil {
236+
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
237+
return
238+
}
239+
info, err := file.Stat()
240+
if err != nil {
241+
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
242+
return
243+
}
244+
c.Header("Content-Length", strconv.FormatInt(info.Size(), 10))
245+
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name()))
246+
http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file)
247+
}

backend/app/service/website_ssl.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/1Panel-dev/1Panel/backend/app/repo"
1212
"github.com/1Panel-dev/1Panel/backend/buserr"
1313
"github.com/1Panel-dev/1Panel/backend/constant"
14+
"github.com/1Panel-dev/1Panel/backend/global"
1415
"github.com/1Panel-dev/1Panel/backend/i18n"
1516
"github.com/1Panel-dev/1Panel/backend/utils/common"
1617
"github.com/1Panel-dev/1Panel/backend/utils/files"
@@ -41,6 +42,7 @@ type IWebsiteSSLService interface {
4142
Upload(req request.WebsiteSSLUpload) error
4243
ObtainSSL(apply request.WebsiteSSLApply) error
4344
SyncForRestart() error
45+
DownloadFile(id uint) (*os.File, error)
4446
}
4547

4648
func NewIWebsiteSSLService() IWebsiteSSLService {
@@ -425,6 +427,34 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
425427
return websiteSSLRepo.Create(context.Background(), websiteSSL)
426428
}
427429

430+
func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) {
431+
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(id))
432+
if err != nil {
433+
return nil, err
434+
}
435+
fileOp := files.NewFileOp()
436+
dir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/ssl", websiteSSL.PrimaryDomain)
437+
if fileOp.Stat(dir) {
438+
if err = fileOp.DeleteDir(dir); err != nil {
439+
return nil, err
440+
}
441+
}
442+
if err = fileOp.CreateDir(dir, 0666); err != nil {
443+
return nil, err
444+
}
445+
if err = fileOp.WriteFile(path.Join(dir, "fullchain.pem"), strings.NewReader(websiteSSL.Pem), 0644); err != nil {
446+
return nil, err
447+
}
448+
if err = fileOp.WriteFile(path.Join(dir, "privkey.pem"), strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil {
449+
return nil, err
450+
}
451+
fileName := websiteSSL.PrimaryDomain + ".zip"
452+
if err = fileOp.Compress([]string{path.Join(dir, "fullchain.pem"), path.Join(dir, "privkey.pem")}, dir, fileName, files.SdkZip); err != nil {
453+
return nil, err
454+
}
455+
return os.Open(path.Join(dir, fileName))
456+
}
457+
428458
func (w WebsiteSSLService) SyncForRestart() error {
429459
sslList, err := websiteSSLRepo.List()
430460
if err != nil {

backend/router/ro_website_ssl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) {
2424
groupRouter.POST("/update", baseApi.UpdateWebsiteSSL)
2525
groupRouter.POST("/upload", baseApi.UploadWebsiteSSL)
2626
groupRouter.POST("/obtain", baseApi.ApplyWebsiteSSL)
27+
groupRouter.POST("/download", baseApi.DownloadWebsiteSSL)
2728
}
2829
}

cmd/server/docs/docs.go

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12879,6 +12879,57 @@ const docTemplate = `{
1287912879
}
1288012880
}
1288112881
},
12882+
"/websites/ssl/download": {
12883+
"post": {
12884+
"security": [
12885+
{
12886+
"ApiKeyAuth": []
12887+
}
12888+
],
12889+
"description": "下载证书文件",
12890+
"consumes": [
12891+
"application/json"
12892+
],
12893+
"tags": [
12894+
"Website SSL"
12895+
],
12896+
"summary": "Download SSL file",
12897+
"parameters": [
12898+
{
12899+
"description": "request",
12900+
"name": "request",
12901+
"in": "body",
12902+
"required": true,
12903+
"schema": {
12904+
"$ref": "#/definitions/request.WebsiteResourceReq"
12905+
}
12906+
}
12907+
],
12908+
"responses": {
12909+
"200": {
12910+
"description": "OK"
12911+
}
12912+
},
12913+
"x-panel-log": {
12914+
"BeforeFunctions": [
12915+
{
12916+
"db": "website_ssls",
12917+
"input_column": "id",
12918+
"input_value": "id",
12919+
"isList": false,
12920+
"output_column": "primary_domain",
12921+
"output_value": "domain"
12922+
}
12923+
],
12924+
"bodyKeys": [
12925+
"id"
12926+
],
12927+
"formatEN": "download ssl file [domain]",
12928+
"formatZH": "下载证书文件 [domain]",
12929+
"paramKeys": []
12930+
}
12931+
}
12932+
},
1288212933
"/websites/ssl/obtain": {
1288312934
"post": {
1288412935
"security": [
@@ -17478,6 +17529,9 @@ const docTemplate = `{
1747817529
"createdAt": {
1747917530
"type": "string"
1748017531
},
17532+
"description": {
17533+
"type": "string"
17534+
},
1748117535
"dir": {
1748217536
"type": "string"
1748317537
},
@@ -19522,14 +19576,33 @@ const docTemplate = `{
1952219576
"request.WebsiteSSLUpdate": {
1952319577
"type": "object",
1952419578
"required": [
19525-
"id"
19579+
"id",
19580+
"type"
1952619581
],
1952719582
"properties": {
1952819583
"autoRenew": {
1952919584
"type": "boolean"
1953019585
},
19586+
"certificate": {
19587+
"type": "string"
19588+
},
19589+
"description": {
19590+
"type": "string"
19591+
},
1953119592
"id": {
1953219593
"type": "integer"
19594+
},
19595+
"privateKey": {
19596+
"type": "string"
19597+
},
19598+
"type": {
19599+
"type": "string",
19600+
"enum": [
19601+
"autoRenew",
19602+
"description",
19603+
"certificate",
19604+
"privateKey"
19605+
]
1953319606
}
1953419607
}
1953519608
},
@@ -19551,6 +19624,9 @@ const docTemplate = `{
1955119624
"privateKeyPath": {
1955219625
"type": "string"
1955319626
},
19627+
"sslID": {
19628+
"type": "integer"
19629+
},
1955419630
"type": {
1955519631
"type": "string",
1955619632
"enum": [

cmd/server/docs/swagger.json

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12872,6 +12872,57 @@
1287212872
}
1287312873
}
1287412874
},
12875+
"/websites/ssl/download": {
12876+
"post": {
12877+
"security": [
12878+
{
12879+
"ApiKeyAuth": []
12880+
}
12881+
],
12882+
"description": "下载证书文件",
12883+
"consumes": [
12884+
"application/json"
12885+
],
12886+
"tags": [
12887+
"Website SSL"
12888+
],
12889+
"summary": "Download SSL file",
12890+
"parameters": [
12891+
{
12892+
"description": "request",
12893+
"name": "request",
12894+
"in": "body",
12895+
"required": true,
12896+
"schema": {
12897+
"$ref": "#/definitions/request.WebsiteResourceReq"
12898+
}
12899+
}
12900+
],
12901+
"responses": {
12902+
"200": {
12903+
"description": "OK"
12904+
}
12905+
},
12906+
"x-panel-log": {
12907+
"BeforeFunctions": [
12908+
{
12909+
"db": "website_ssls",
12910+
"input_column": "id",
12911+
"input_value": "id",
12912+
"isList": false,
12913+
"output_column": "primary_domain",
12914+
"output_value": "domain"
12915+
}
12916+
],
12917+
"bodyKeys": [
12918+
"id"
12919+
],
12920+
"formatEN": "download ssl file [domain]",
12921+
"formatZH": "下载证书文件 [domain]",
12922+
"paramKeys": []
12923+
}
12924+
}
12925+
},
1287512926
"/websites/ssl/obtain": {
1287612927
"post": {
1287712928
"security": [
@@ -17471,6 +17522,9 @@
1747117522
"createdAt": {
1747217523
"type": "string"
1747317524
},
17525+
"description": {
17526+
"type": "string"
17527+
},
1747417528
"dir": {
1747517529
"type": "string"
1747617530
},
@@ -19515,14 +19569,33 @@
1951519569
"request.WebsiteSSLUpdate": {
1951619570
"type": "object",
1951719571
"required": [
19518-
"id"
19572+
"id",
19573+
"type"
1951919574
],
1952019575
"properties": {
1952119576
"autoRenew": {
1952219577
"type": "boolean"
1952319578
},
19579+
"certificate": {
19580+
"type": "string"
19581+
},
19582+
"description": {
19583+
"type": "string"
19584+
},
1952419585
"id": {
1952519586
"type": "integer"
19587+
},
19588+
"privateKey": {
19589+
"type": "string"
19590+
},
19591+
"type": {
19592+
"type": "string",
19593+
"enum": [
19594+
"autoRenew",
19595+
"description",
19596+
"certificate",
19597+
"privateKey"
19598+
]
1952619599
}
1952719600
}
1952819601
},
@@ -19544,6 +19617,9 @@
1954419617
"privateKeyPath": {
1954519618
"type": "string"
1954619619
},
19620+
"sslID": {
19621+
"type": "integer"
19622+
},
1954719623
"type": {
1954819624
"type": "string",
1954919625
"enum": [

0 commit comments

Comments
 (0)