mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +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/app/dto/request"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Tags Website CA
|
// @Tags Website CA
|
||||||
@ -142,3 +145,33 @@ func (b *BaseApi) RenewWebsiteCA(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
helper.SuccessWithOutData(c)
|
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/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"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/i18n"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||||
@ -39,6 +40,7 @@ type IWebsiteCAService interface {
|
|||||||
GetCA(id uint) (*response.WebsiteCADTO, error)
|
GetCA(id uint) (*response.WebsiteCADTO, error)
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error)
|
ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error)
|
||||||
|
DownloadFile(id uint) (*os.File, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIWebsiteCAService() IWebsiteCAService {
|
func NewIWebsiteCAService() IWebsiteCAService {
|
||||||
@ -414,3 +416,31 @@ func createPrivateKey(keyType string) (privateKey any, publicKey any, privateKey
|
|||||||
privateKeyBytes = caPrivateKeyPEM.Bytes()
|
privateKeyBytes = caPrivateKeyPEM.Bytes()
|
||||||
return
|
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("/obtain", baseApi.ObtainWebsiteCA)
|
||||||
groupRouter.POST("/renew", baseApi.RenewWebsiteCA)
|
groupRouter.POST("/renew", baseApi.RenewWebsiteCA)
|
||||||
groupRouter.GET("/:id", baseApi.GetWebsiteCA)
|
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) => {
|
export const UpdateDefaultHtml = (req: Website.WebsiteHtmlUpdate) => {
|
||||||
return http.post(`/websites/default/html/update`, req);
|
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',
|
false: 'false',
|
||||||
example: 'e.g.:',
|
example: 'e.g.:',
|
||||||
button: {
|
button: {
|
||||||
create: 'Create',
|
create: 'Create ',
|
||||||
add: 'Add ',
|
add: 'Add ',
|
||||||
save: 'Save ',
|
save: 'Save ',
|
||||||
set: 'Setting',
|
set: 'Setting',
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
|
<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<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>
|
||||||
<el-button-group class="ml-4">
|
<el-button-group class="ml-4">
|
||||||
<el-button plain :disabled="selects.length === 0" @click="onBatchChangeStatus('enable')">
|
<el-button plain :disabled="selects.length === 0" @click="onBatchChangeStatus('enable')">
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<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>
|
||||||
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
||||||
{{ $t('commons.button.delete') }}
|
{{ $t('commons.button.delete') }}
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<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>
|
||||||
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
|
||||||
{{ $t('commons.button.delete') }}
|
{{ $t('commons.button.delete') }}
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
import { Website } from '@/api/interface/website';
|
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 i18n from '@/lang';
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import Create from './create/index.vue';
|
import Create from './create/index.vue';
|
||||||
@ -79,6 +79,12 @@ const buttons = [
|
|||||||
detailRef.value.acceptParams(row.id);
|
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'),
|
label: i18n.global.t('commons.button.delete'),
|
||||||
click: function (row: Website.CA) {
|
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({
|
defineExpose({
|
||||||
acceptParams,
|
acceptParams,
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user