mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 12:39:01 +08:00
parent
f370f7eacf
commit
08125b150a
@ -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)
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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<BlobPart>(`/websites/ca/download`, params, {
|
||||
responseType: 'blob',
|
||||
timeout: TimeoutEnum.T_40S,
|
||||
});
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ const message = {
|
||||
false: 'false',
|
||||
example: 'e.g.:',
|
||||
button: {
|
||||
create: 'Create',
|
||||
create: 'Create ',
|
||||
add: 'Add ',
|
||||
save: 'Save ',
|
||||
set: 'Setting',
|
||||
|
@ -13,7 +13,7 @@
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
|
||||
<el-button type="primary" @click="onOpenDialog('create')">
|
||||
{{ $t('commons.button.create') }} {{ $t('cronjob.cronTask') }}
|
||||
{{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }}
|
||||
</el-button>
|
||||
<el-button-group class="ml-4">
|
||||
<el-button plain :disabled="selects.length === 0" @click="onBatchChangeStatus('enable')">
|
||||
|
@ -22,7 +22,7 @@
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
<el-button type="primary" @click="onOpenDialog('create')">
|
||||
{{ $t('commons.button.create') }} {{ $t('firewall.forwardRule') }}
|
||||
{{ $t('commons.button.create') }}{{ $t('firewall.forwardRule') }}
|
||||
</el-button>
|
||||
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
||||
{{ $t('commons.button.delete') }}
|
||||
|
@ -55,7 +55,7 @@
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
<el-button type="primary" @click="onOpenDialog('create')">
|
||||
{{ $t('commons.button.create') }} {{ $t('firewall.portRule') }}
|
||||
{{ $t('commons.button.create') }}{{ $t('firewall.portRule') }}
|
||||
</el-button>
|
||||
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
||||
{{ $t('commons.button.delete') }}
|
||||
|
@ -43,7 +43,7 @@
|
||||
<script lang="ts" setup>
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { Website } from '@/api/interface/website';
|
||||
import { DeleteCA, SearchCAs } from '@/api/modules/website';
|
||||
import { DeleteCA, SearchCAs, DownloadCAFile } from '@/api/modules/website';
|
||||
import i18n from '@/lang';
|
||||
import { reactive, ref } from 'vue';
|
||||
import Create from './create/index.vue';
|
||||
@ -79,6 +79,12 @@ const buttons = [
|
||||
detailRef.value.acceptParams(row.id);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.download'),
|
||||
click: function (row: Website.CA) {
|
||||
onDownload(row);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.delete'),
|
||||
click: function (row: Website.CA) {
|
||||
@ -129,6 +135,23 @@ const deleteCA = async (row: any) => {
|
||||
});
|
||||
};
|
||||
|
||||
const onDownload = (row: Website.CA) => {
|
||||
loading.value = true;
|
||||
DownloadCAFile({ id: row.id })
|
||||
.then((res) => {
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([res]));
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = downloadUrl;
|
||||
a.download = row.name + '.zip';
|
||||
const event = new MouseEvent('click');
|
||||
a.dispatchEvent(event);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user