diff --git a/backend/app/api/v1/website_ca.go b/backend/app/api/v1/website_ca.go index 52c8b89c8..986b6fa9f 100644 --- a/backend/app/api/v1/website_ca.go +++ b/backend/app/api/v1/website_ca.go @@ -6,6 +6,9 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/gin-gonic/gin" + "net/http" + "net/url" + "strconv" ) // @Tags Website CA @@ -142,3 +145,33 @@ func (b *BaseApi) RenewWebsiteCA(c *gin.Context) { } helper.SuccessWithOutData(c) } + +// @Tags Website CA +// @Summary Download CA file +// @Description 下载 CA 证书文件 +// @Accept json +// @Param request body request.WebsiteResourceReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/ca/download [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"下载 CA 证书文件 [name]","formatEN":"download ca file [name]"} +func (b *BaseApi) DownloadCAFile(c *gin.Context) { + var req request.WebsiteResourceReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + file, err := websiteCAService.DownloadFile(req.ID) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + defer file.Close() + info, err := file.Stat() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + c.Header("Content-Length", strconv.FormatInt(info.Size(), 10)) + c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name())) + http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file) +} diff --git a/backend/app/service/website_ca.go b/backend/app/service/website_ca.go index ef37c6d52..a93b6ad34 100644 --- a/backend/app/service/website_ca.go +++ b/backend/app/service/website_ca.go @@ -15,6 +15,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/i18n" "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/common" @@ -39,6 +40,7 @@ type IWebsiteCAService interface { GetCA(id uint) (*response.WebsiteCADTO, error) Delete(id uint) error ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error) + DownloadFile(id uint) (*os.File, error) } func NewIWebsiteCAService() IWebsiteCAService { @@ -414,3 +416,31 @@ func createPrivateKey(keyType string) (privateKey any, publicKey any, privateKey privateKeyBytes = caPrivateKeyPEM.Bytes() return } + +func (w WebsiteCAService) DownloadFile(id uint) (*os.File, error) { + ca, err := websiteCARepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return nil, err + } + fileOp := files.NewFileOp() + dir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/ssl", ca.Name) + if fileOp.Stat(dir) { + if err = fileOp.DeleteDir(dir); err != nil { + return nil, err + } + } + if err = fileOp.CreateDir(dir, 0666); err != nil { + return nil, err + } + if err = fileOp.WriteFile(path.Join(dir, "ca.csr"), strings.NewReader(ca.CSR), 0644); err != nil { + return nil, err + } + if err = fileOp.WriteFile(path.Join(dir, "private.key"), strings.NewReader(ca.PrivateKey), 0644); err != nil { + return nil, err + } + fileName := ca.Name + ".zip" + if err = fileOp.Compress([]string{path.Join(dir, "ca.csr"), path.Join(dir, "private.key")}, dir, fileName, files.SdkZip, ""); err != nil { + return nil, err + } + return os.Open(path.Join(dir, fileName)) +} diff --git a/backend/router/ro_website_ca.go b/backend/router/ro_website_ca.go index c994519b0..9701a569d 100644 --- a/backend/router/ro_website_ca.go +++ b/backend/router/ro_website_ca.go @@ -21,5 +21,6 @@ func (a *WebsiteCARouter) InitRouter(Router *gin.RouterGroup) { groupRouter.POST("/obtain", baseApi.ObtainWebsiteCA) groupRouter.POST("/renew", baseApi.RenewWebsiteCA) groupRouter.GET("/:id", baseApi.GetWebsiteCA) + groupRouter.POST("/download", baseApi.DownloadCAFile) } } diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts index 496910189..f07984b98 100644 --- a/frontend/src/api/modules/website.ts +++ b/frontend/src/api/modules/website.ts @@ -276,3 +276,10 @@ export const GetDefaultHtml = (type: string) => { export const UpdateDefaultHtml = (req: Website.WebsiteHtmlUpdate) => { return http.post(`/websites/default/html/update`, req); }; + +export const DownloadCAFile = (params: Website.SSLDownload) => { + return http.download(`/websites/ca/download`, params, { + responseType: 'blob', + timeout: TimeoutEnum.T_40S, + }); +}; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 63a5a2be1..ace369cce 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -12,7 +12,7 @@ const message = { false: 'false', example: 'e.g.:', button: { - create: 'Create', + create: 'Create ', add: 'Add ', save: 'Save ', set: 'Setting', diff --git a/frontend/src/views/cronjob/index.vue b/frontend/src/views/cronjob/index.vue index 0b706675e..a72d44432 100644 --- a/frontend/src/views/cronjob/index.vue +++ b/frontend/src/views/cronjob/index.vue @@ -13,7 +13,7 @@ - {{ $t('commons.button.create') }} {{ $t('cronjob.cronTask') }} + {{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }} diff --git a/frontend/src/views/host/firewall/forward/index.vue b/frontend/src/views/host/firewall/forward/index.vue index 947df7056..69b1443e0 100644 --- a/frontend/src/views/host/firewall/forward/index.vue +++ b/frontend/src/views/host/firewall/forward/index.vue @@ -22,7 +22,7 @@ - {{ $t('commons.button.create') }} {{ $t('firewall.forwardRule') }} + {{ $t('commons.button.create') }}{{ $t('firewall.forwardRule') }} {{ $t('commons.button.delete') }} diff --git a/frontend/src/views/host/firewall/port/index.vue b/frontend/src/views/host/firewall/port/index.vue index 817eac5a4..c60a81ace 100644 --- a/frontend/src/views/host/firewall/port/index.vue +++ b/frontend/src/views/host/firewall/port/index.vue @@ -55,7 +55,7 @@ - {{ $t('commons.button.create') }} {{ $t('firewall.portRule') }} + {{ $t('commons.button.create') }}{{ $t('firewall.portRule') }} {{ $t('commons.button.delete') }} diff --git a/frontend/src/views/website/ssl/ca/index.vue b/frontend/src/views/website/ssl/ca/index.vue index 24f7fa492..ec7045f5e 100644 --- a/frontend/src/views/website/ssl/ca/index.vue +++ b/frontend/src/views/website/ssl/ca/index.vue @@ -43,7 +43,7 @@