1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-02-12 11:30:07 +08:00

feat: 增加批量删除证书功能 (#3076)

This commit is contained in:
zhengkunwang 2023-11-27 17:00:09 +08:00 committed by GitHub
parent a90b79bf76
commit 50b4458926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 114 additions and 31 deletions

View File

@ -132,17 +132,17 @@ func (b *BaseApi) GetDNSResolve(c *gin.Context) {
// @Summary Delete website ssl // @Summary Delete website ssl
// @Description 删除网站 ssl // @Description 删除网站 ssl
// @Accept json // @Accept json
// @Param request body request.WebsiteResourceReq true "request" // @Param request body request.WebsiteBatchDelReq true "request"
// @Success 200 // @Success 200
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /websites/ssl/del [post] // @Router /websites/ssl/del [post]
// @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":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"} // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"}
func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) { func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
var req request.WebsiteResourceReq var req request.WebsiteBatchDelReq
if err := helper.CheckBindAndValidate(&req, c); err != nil { if err := helper.CheckBindAndValidate(&req, c); err != nil {
return return
} }
if err := websiteSSLService.Delete(req.ID); err != nil { if err := websiteSSLService.Delete(req.IDs); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }

View File

@ -58,6 +58,10 @@ type WebsiteResourceReq struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
} }
type WebsiteBatchDelReq struct {
IDs []uint `json:"ids" validate:"required"`
}
type WebsiteSSLUpdate struct { type WebsiteSSLUpdate struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
AutoRenew bool `json:"autoRenew"` AutoRenew bool `json:"autoRenew"`

View File

@ -149,6 +149,7 @@ func (w WebsiteCAService) GetCA(id uint) (response.WebsiteCADTO, error) {
} }
func (w WebsiteCAService) Delete(id uint) error { func (w WebsiteCAService) Delete(id uint) error {
return websiteCARepo.DeleteBy(commonRepo.WithByID(id)) return websiteCARepo.DeleteBy(commonRepo.WithByID(id))
} }

View File

@ -38,7 +38,7 @@ type IWebsiteSSLService interface {
Renew(sslId uint) error Renew(sslId uint) error
GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error)
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error)
Delete(id uint) error Delete(ids []uint) error
Update(update request.WebsiteSSLUpdate) error Update(update request.WebsiteSSLUpdate) error
Upload(req request.WebsiteSSLUpload) error Upload(req request.WebsiteSSLUpload) error
ObtainSSL(apply request.WebsiteSSLApply) error ObtainSSL(apply request.WebsiteSSLApply) error
@ -299,6 +299,8 @@ func (w WebsiteSSLService) Renew(sslId uint) error {
if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppOpenresty, appInstall.Name, "root")); err != nil { if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppOpenresty, appInstall.Name, "root")); err != nil {
return err return err
} }
case constant.SelfSigned:
} }
resource, err := client.RenewSSL(websiteSSL.CertURL) resource, err := client.RenewSSL(websiteSSL.CertURL)
@ -380,11 +382,23 @@ func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO
return res, nil return res, nil
} }
func (w WebsiteSSLService) Delete(id uint) error { func (w WebsiteSSLService) Delete(ids []uint) error {
if websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(id)); len(websites) > 0 { var names []string
return buserr.New(constant.ErrSSLCannotDelete) for _, id := range ids {
if websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(id)); len(websites) > 0 {
oldSSL, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(id))
if oldSSL.ID > 0 {
names = append(names, oldSSL.PrimaryDomain)
}
continue
} else {
_ = websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
}
} }
return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id)) if len(names) > 0 {
return buserr.WithName("ErrSSLCannotDelete", strings.Join(names, ","))
}
return nil
} }
func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error { func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {

View File

@ -85,7 +85,7 @@ ErrDomainIsUsed: "Domain is already used by website {{ .name }}"
ErrDomainFormat: "{{ .name }} domain format error" ErrDomainFormat: "{{ .name }} domain format error"
#ssl #ssl
ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed" ErrSSLCannotDelete: "The certificate {{ .name }} is being used by the website and cannot be removed"
ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted" ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted"
ErrSSLApply: "The certificate continues to be signed successfully, but openresty reload fails, please check the configuration" ErrSSLApply: "The certificate continues to be signed successfully, but openresty reload fails, please check the configuration"
ErrEmailIsExist: 'Email is already exist' ErrEmailIsExist: 'Email is already exist'

View File

@ -85,7 +85,7 @@ ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正確" ErrDomainFormat: "{{ .name }} 域名格式不正確"
#ssl #ssl
ErrSSLCannotDelete: "證書正在被網站使用,無法刪除" ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除"
ErrAccountCannotDelete: "帳號關聯證書,無法刪除" ErrAccountCannotDelete: "帳號關聯證書,無法刪除"
ErrSSLApply: "證書續簽成功openresty reload失敗請檢查配置" ErrSSLApply: "證書續簽成功openresty reload失敗請檢查配置"
ErrEmailIsExist: '郵箱已存在' ErrEmailIsExist: '郵箱已存在'

View File

@ -85,7 +85,7 @@ ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正确" ErrDomainFormat: "{{ .name }} 域名格式不正确"
#ssl #ssl
ErrSSLCannotDelete: "证书正在被网站使用,无法删除" ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
ErrAccountCannotDelete: "账号关联证书,无法删除" ErrAccountCannotDelete: "账号关联证书,无法删除"
ErrSSLApply: "证书续签成功openresty reload失败请检查配置" ErrSSLApply: "证书续签成功openresty reload失败请检查配置"
ErrEmailIsExist: '邮箱已存在' ErrEmailIsExist: '邮箱已存在'

View File

@ -1,5 +1,5 @@
// Code generated by swaggo/swag. DO NOT EDIT. // Package docs GENERATED BY SWAG; DO NOT EDIT
// This file was generated by swaggo/swag
package docs package docs
import "github.com/swaggo/swag" import "github.com/swaggo/swag"
@ -12850,7 +12850,7 @@ const docTemplate = `{
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/request.WebsiteResourceReq" "$ref": "#/definitions/request.WebsiteBatchDelReq"
} }
} }
], ],
@ -12864,14 +12864,14 @@ const docTemplate = `{
{ {
"db": "website_ssls", "db": "website_ssls",
"input_column": "id", "input_column": "id",
"input_value": "id", "input_value": "ids",
"isList": false, "isList": true,
"output_column": "primary_domain", "output_column": "primary_domain",
"output_value": "domain" "output_value": "domain"
} }
], ],
"bodyKeys": [ "bodyKeys": [
"id" "ids"
], ],
"formatEN": "Delete ssl [domain]", "formatEN": "Delete ssl [domain]",
"formatZH": "删除 ssl [domain]", "formatZH": "删除 ssl [domain]",
@ -18907,6 +18907,20 @@ const docTemplate = `{
} }
} }
}, },
"request.WebsiteBatchDelReq": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"request.WebsiteCACreate": { "request.WebsiteCACreate": {
"type": "object", "type": "object",
"required": [ "required": [

View File

@ -12843,7 +12843,7 @@
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/request.WebsiteResourceReq" "$ref": "#/definitions/request.WebsiteBatchDelReq"
} }
} }
], ],
@ -12857,14 +12857,14 @@
{ {
"db": "website_ssls", "db": "website_ssls",
"input_column": "id", "input_column": "id",
"input_value": "id", "input_value": "ids",
"isList": false, "isList": true,
"output_column": "primary_domain", "output_column": "primary_domain",
"output_value": "domain" "output_value": "domain"
} }
], ],
"bodyKeys": [ "bodyKeys": [
"id" "ids"
], ],
"formatEN": "Delete ssl [domain]", "formatEN": "Delete ssl [domain]",
"formatZH": "删除 ssl [domain]", "formatZH": "删除 ssl [domain]",
@ -18900,6 +18900,20 @@
} }
} }
}, },
"request.WebsiteBatchDelReq": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"request.WebsiteCACreate": { "request.WebsiteCACreate": {
"type": "object", "type": "object",
"required": [ "required": [

View File

@ -3724,6 +3724,15 @@ definitions:
- keyType - keyType
- type - type
type: object type: object
request.WebsiteBatchDelReq:
properties:
ids:
items:
type: integer
type: array
required:
- ids
type: object
request.WebsiteCACreate: request.WebsiteCACreate:
properties: properties:
city: city:
@ -12840,7 +12849,7 @@ paths:
name: request name: request
required: true required: true
schema: schema:
$ref: '#/definitions/request.WebsiteResourceReq' $ref: '#/definitions/request.WebsiteBatchDelReq'
responses: responses:
"200": "200":
description: OK description: OK
@ -12853,12 +12862,12 @@ paths:
BeforeFunctions: BeforeFunctions:
- db: website_ssls - db: website_ssls
input_column: id input_column: id
input_value: id input_value: ids
isList: false isList: true
output_column: primary_domain output_column: primary_domain
output_value: domain output_value: domain
bodyKeys: bodyKeys:
- id - ids
formatEN: Delete ssl [domain] formatEN: Delete ssl [domain]
formatZH: 删除 ssl [domain] formatZH: 删除 ssl [domain]
paramKeys: [] paramKeys: []

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<el-dialog v-model="open" :title="form.title" width="30%" :close-on-click-modal="false"> <el-dialog v-model="open" :title="form.title" width="30%" :close-on-click-modal="false" @close="handleClose">
<div v-loading="loading"> <div v-loading="loading">
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="22"> <el-col :span="22">
@ -98,6 +98,11 @@ const onConfirm = async () => {
}); });
}; };
const handleClose = () => {
emit('cancel');
open.value = false;
};
onMounted(() => {}); onMounted(() => {});
defineExpose({ defineExpose({

View File

@ -25,10 +25,20 @@
<el-button type="primary" plain @click="openDnsAccount()"> <el-button type="primary" plain @click="openDnsAccount()">
{{ $t('website.dnsAccountManage') }} {{ $t('website.dnsAccountManage') }}
</el-button> </el-button>
<el-button plain @click="deleteSSL(null)" :disabled="selects.length === 0">
{{ $t('commons.button.delete') }}
</el-button>
</template> </template>
<template #main> <template #main>
<br /> <br />
<ComplexTable :data="data" :pagination-config="paginationConfig" @search="search()" v-loading="loading"> <ComplexTable
:data="data"
:pagination-config="paginationConfig"
@search="search()"
v-model:selects="selects"
v-loading="loading"
>
<el-table-column type="selection" width="30" />
<el-table-column <el-table-column
:label="$t('website.domain')" :label="$t('website.domain')"
fix fix
@ -129,7 +139,7 @@
<Detail ref="detailRef"></Detail> <Detail ref="detailRef"></Detail>
<SSLUpload ref="sslUploadRef" @close="search()"></SSLUpload> <SSLUpload ref="sslUploadRef" @close="search()"></SSLUpload>
<Apply ref="applyRef" @search="search" /> <Apply ref="applyRef" @search="search" />
<OpDialog ref="opRef" @search="search" /> <OpDialog ref="opRef" @search="search" @cancel="search" />
<Log ref="logRef" @close="search()" /> <Log ref="logRef" @close="search()" />
<CA ref="caRef" @close="search()" /> <CA ref="caRef" @close="search()" />
</LayoutContent> </LayoutContent>
@ -172,6 +182,7 @@ const sslUploadRef = ref();
const applyRef = ref(); const applyRef = ref();
const logRef = ref(); const logRef = ref();
const caRef = ref(); const caRef = ref();
let selects = ref<any>([]);
const routerButton = [ const routerButton = [
{ {
@ -277,16 +288,27 @@ const applySSL = (row: Website.SSLDTO) => {
}; };
const deleteSSL = async (row: any) => { const deleteSSL = async (row: any) => {
let names = [];
let params = {};
if (row == null) {
names = selects.value.map((item: Website.SSLDTO) => item.primaryDomain);
params = { ids: selects.value.map((item: Website.SSLDTO) => item.id) };
} else {
names = [row.primaryDomain];
params = { ids: [row.id] };
}
opRef.value.acceptParams({ opRef.value.acceptParams({
title: i18n.global.t('commons.button.delete'), title: i18n.global.t('commons.button.delete'),
names: [row.primaryDomain], names: names,
msg: i18n.global.t('commons.msg.operatorHelper', [ msg: i18n.global.t('commons.msg.operatorHelper', [
i18n.global.t('website.ssl'), i18n.global.t('website.ssl'),
i18n.global.t('commons.button.delete'), i18n.global.t('commons.button.delete'),
]), ]),
api: DeleteSSL, api: DeleteSSL,
params: { id: row.id }, params: params,
}); });
search();
}; };
onMounted(() => { onMounted(() => {