1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 22:18:07 +08:00

feat: 机构增加详情查看页 (#3097)

This commit is contained in:
zhengkunwang 2023-11-29 16:12:09 +08:00 committed by GitHub
parent 6db80141ed
commit 120bec57b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 238 additions and 86 deletions

View File

@ -86,7 +86,6 @@ type WebsiteCASearch struct {
type WebsiteCACreate struct {
CommonName string `json:"commonName" validate:"required"`
Country string `json:"country" validate:"required"`
Email string `json:"email" validate:"required"`
Organization string `json:"organization" validate:"required"`
OrganizationUint string `json:"organizationUint"`
Name string `json:"name" validate:"required"`

View File

@ -25,4 +25,10 @@ type WebsiteDnsAccountDTO struct {
type WebsiteCADTO struct {
model.WebsiteCA
CommonName string `json:"commonName" `
Country string `json:"country"`
Organization string `json:"organization"`
OrganizationUint string `json:"organizationUint"`
Province string `json:"province" `
City string `json:"city"`
}

View File

@ -35,7 +35,7 @@ type WebsiteCAService struct {
type IWebsiteCAService interface {
Page(search request.WebsiteCASearch) (int64, []response.WebsiteCADTO, error)
Create(create request.WebsiteCACreate) (*request.WebsiteCACreate, error)
GetCA(id uint) (response.WebsiteCADTO, error)
GetCA(id uint) (*response.WebsiteCADTO, error)
Delete(id uint) error
ObtainSSL(req request.WebsiteCAObtain) error
}
@ -69,9 +69,10 @@ func (w WebsiteCAService) Create(create request.WebsiteCACreate) (*request.Websi
}
pkixName := pkix.Name{
CommonName: create.CommonName,
Country: []string{create.Country},
Organization: []string{create.Organization},
CommonName: create.CommonName,
Country: []string{create.Country},
Organization: []string{create.Organization},
OrganizationalUnit: []string{create.OrganizationUint},
}
if create.Province != "" {
pkixName.Province = []string{create.Province}
@ -138,14 +139,29 @@ func (w WebsiteCAService) Create(create request.WebsiteCACreate) (*request.Websi
return &create, nil
}
func (w WebsiteCAService) GetCA(id uint) (response.WebsiteCADTO, error) {
func (w WebsiteCAService) GetCA(id uint) (*response.WebsiteCADTO, error) {
res := &response.WebsiteCADTO{}
ca, err := websiteCARepo.GetFirst(commonRepo.WithByID(id))
if err != nil {
return response.WebsiteCADTO{}, err
return nil, err
}
return response.WebsiteCADTO{
WebsiteCA: ca,
}, nil
res.WebsiteCA = ca
certBlock, _ := pem.Decode([]byte(ca.CSR))
if certBlock == nil {
return nil, buserr.New("ErrSSLCertificateFormat")
}
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return nil, err
}
res.CommonName = cert.Issuer.CommonName
res.Organization = strings.Join(cert.Issuer.Organization, ",")
res.Country = strings.Join(cert.Issuer.Country, ",")
res.Province = strings.Join(cert.Issuer.Province, ",")
res.City = strings.Join(cert.Issuer.Locality, ",")
res.OrganizationUint = strings.Join(cert.Issuer.OrganizationalUnit, ",")
return res, nil
}
func (w WebsiteCAService) Delete(id uint) error {
@ -157,7 +173,6 @@ func (w WebsiteCAService) Delete(id uint) error {
}
func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
var (
domains []string
ips []net.IP

View File

@ -17,5 +17,6 @@ func (a *WebsiteDnsAccountRouter) InitWebsiteCARouter(Router *gin.RouterGroup) {
groupRouter.POST("/del", baseApi.DeleteWebsiteCA)
groupRouter.POST("/obtain", baseApi.ObtainWebsiteCA)
groupRouter.POST("/renew", baseApi.RenewWebsiteCA)
groupRouter.GET("/:id", baseApi.GetWebsiteCA)
}
}

View File

@ -18935,7 +18935,6 @@ const docTemplate = `{
"required": [
"commonName",
"country",
"email",
"keyType",
"name",
"organization"
@ -18950,9 +18949,6 @@ const docTemplate = `{
"country": {
"type": "string"
},
"email": {
"type": "string"
},
"keyType": {
"type": "string",
"enum": [
@ -19532,12 +19528,18 @@ const docTemplate = `{
"autoRenew": {
"type": "boolean"
},
"description": {
"type": "string"
},
"dir": {
"type": "string"
},
"dnsAccountId": {
"type": "integer"
},
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
@ -19576,33 +19578,17 @@ const docTemplate = `{
"request.WebsiteSSLUpdate": {
"type": "object",
"required": [
"id",
"type"
"id"
],
"properties": {
"autoRenew": {
"type": "boolean"
},
"certificate": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "integer"
},
"privateKey": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"autoRenew",
"description",
"certificate",
"privateKey"
]
}
}
},
@ -20189,6 +20175,15 @@ const docTemplate = `{
"response.WebsiteCADTO": {
"type": "object",
"properties": {
"city": {
"type": "string"
},
"commonName": {
"type": "string"
},
"country": {
"type": "string"
},
"createdAt": {
"type": "string"
},
@ -20204,9 +20199,18 @@ const docTemplate = `{
"name": {
"type": "string"
},
"organization": {
"type": "string"
},
"organizationUint": {
"type": "string"
},
"privateKey": {
"type": "string"
},
"province": {
"type": "string"
},
"updatedAt": {
"type": "string"
}

View File

@ -18928,7 +18928,6 @@
"required": [
"commonName",
"country",
"email",
"keyType",
"name",
"organization"
@ -18943,9 +18942,6 @@
"country": {
"type": "string"
},
"email": {
"type": "string"
},
"keyType": {
"type": "string",
"enum": [
@ -19525,12 +19521,18 @@
"autoRenew": {
"type": "boolean"
},
"description": {
"type": "string"
},
"dir": {
"type": "string"
},
"dnsAccountId": {
"type": "integer"
},
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
@ -19569,33 +19571,17 @@
"request.WebsiteSSLUpdate": {
"type": "object",
"required": [
"id",
"type"
"id"
],
"properties": {
"autoRenew": {
"type": "boolean"
},
"certificate": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "integer"
},
"privateKey": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"autoRenew",
"description",
"certificate",
"privateKey"
]
}
}
},
@ -20182,6 +20168,15 @@
"response.WebsiteCADTO": {
"type": "object",
"properties": {
"city": {
"type": "string"
},
"commonName": {
"type": "string"
},
"country": {
"type": "string"
},
"createdAt": {
"type": "string"
},
@ -20197,9 +20192,18 @@
"name": {
"type": "string"
},
"organization": {
"type": "string"
},
"organizationUint": {
"type": "string"
},
"privateKey": {
"type": "string"
},
"province": {
"type": "string"
},
"updatedAt": {
"type": "string"
}

View File

@ -3747,8 +3747,6 @@ definitions:
type: string
country:
type: string
email:
type: string
keyType:
enum:
- P256
@ -3769,7 +3767,6 @@ definitions:
required:
- commonName
- country
- email
- keyType
- name
- organization
@ -4145,10 +4142,14 @@ definitions:
type: boolean
autoRenew:
type: boolean
description:
type: string
dir:
type: string
dnsAccountId:
type: integer
id:
type: integer
keyType:
type: string
otherDomains:
@ -4180,24 +4181,12 @@ definitions:
properties:
autoRenew:
type: boolean
certificate:
type: string
description:
type: string
id:
type: integer
privateKey:
type: string
type:
enum:
- autoRenew
- description
- certificate
- privateKey
type: string
required:
- id
- type
type: object
request.WebsiteSSLUpload:
properties:
@ -4586,6 +4575,12 @@ definitions:
type: object
response.WebsiteCADTO:
properties:
city:
type: string
commonName:
type: string
country:
type: string
createdAt:
type: string
csr:
@ -4596,8 +4591,14 @@ definitions:
type: string
name:
type: string
organization:
type: string
organizationUint:
type: string
privateKey:
type: string
province:
type: string
updatedAt:
type: string
type: object

View File

@ -473,7 +473,6 @@ export namespace Website {
name: string;
commonName: string;
country: string;
email: string;
organization: string;
organizationUint: string;
keyType: string;
@ -481,6 +480,15 @@ export namespace Website {
city: string;
}
export interface CADTO extends CA {
commonName: string;
country: string;
organization: string;
organizationUint: string;
province: string;
city: string;
}
export interface SSLObtainByCA {
id: number;
domains: string;

View File

@ -270,3 +270,7 @@ export const DownloadFile = (params: Website.SSLDownload) => {
timeout: TimeoutEnum.T_40S,
});
};
export const GetCA = (id: number) => {
return http.get<Website.CADTO>(`/websites/ca/${id}`);
};

View File

@ -1851,6 +1851,7 @@ const message = {
dir: 'directory',
pushDirHelper:
'Two files will be generated in this directory, the certificate file: fullchain.pem and the key file: privkey.pem',
organizationDetail: 'Organization Details',
},
firewall: {
create: 'Create rule',

View File

@ -1737,6 +1737,7 @@ const message = {
pushDir: '推送憑證到本機目錄',
dir: '目錄',
pushDirHelper: '會在此目錄下產生兩個文件憑證檔案fullchain.pem 金鑰檔案privkey.pem',
organizationDetail: '機構詳情',
},
firewall: {
create: '創建規則',

View File

@ -1737,6 +1737,7 @@ const message = {
pushDir: '推送证书到本地目录',
dir: '目录',
pushDirHelper: '会在此目录下生成两个文件证书文件fullchain.pem 密钥文件privkey.pem',
organizationDetail: '机构详情',
},
firewall: {
create: '创建规则',

View File

@ -15,9 +15,6 @@
<el-form-item :label="$t('ssl.commonName')" prop="commonName">
<el-input v-model.trim="ca.commonName"></el-input>
</el-form-item>
<el-form-item :label="$t('website.email')" prop="email">
<el-input v-model.trim="ca.email"></el-input>
</el-form-item>
<el-form-item :label="$t('ssl.company')" prop="organization">
<el-input v-model.trim="ca.organization"></el-input>
</el-form-item>
@ -72,7 +69,6 @@ const caForm = ref<FormInstance>();
const em = defineEmits(['close']);
const rules = ref({
email: [Rules.requiredInput, Rules.email],
keyType: [Rules.requiredSelect],
name: [Rules.requiredInput, Rules.name],
country: [Rules.requiredSelect],
@ -82,7 +78,6 @@ const rules = ref({
const initData = () => ({
name: '',
email: '',
keyType: 'P256',
commonName: '',
country: 'CN',

View File

@ -0,0 +1,103 @@
<template>
<el-drawer :close-on-click-modal="false" v-model="open" size="50%">
<template #header>
<DrawerHeader :header="$t('ssl.organizationDetail')" :back="handleClose" />
</template>
<div v-loading="loading">
<el-radio-group v-model="curr">
<el-radio-button label="detail">{{ $t('ssl.msg') }}</el-radio-button>
<el-radio-button label="ssl">csr</el-radio-button>
<el-radio-button label="key">{{ $t('ssl.key') }}</el-radio-button>
</el-radio-group>
<div v-if="curr === 'detail'" class="mt-5">
<el-descriptions border :column="1">
<el-descriptions-item :label="$t('commons.table.name')">
{{ ca.name }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.commonName')">
{{ ca.commonName }}
</el-descriptions-item>
<el-descriptions-item :label="$t('website.brand')">
{{ ca.organization }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.department')">
{{ ca.organizationUint }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.country')">
{{ ca.country }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.province')">
{{ ca.province }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.city')">
{{ ca.city }}
</el-descriptions-item>
</el-descriptions>
</div>
<div v-else-if="curr === 'ssl'" class="mt-5">
<el-input v-model="ca.csr" :autosize="{ minRows: 15, maxRows: 30 }" type="textarea" id="textArea" />
<div>
<br />
<el-button type="primary" @click="copyText(ca.csr)">{{ $t('file.copy') }}</el-button>
</div>
</div>
<div v-else class="mt-5">
<el-input
v-model="ca.privateKey"
:autosize="{ minRows: 15, maxRows: 30 }"
type="textarea"
id="textArea"
/>
<div>
<br />
<el-button type="primary" @click="copyText(ca.privateKey)">{{ $t('file.copy') }}</el-button>
</div>
</div>
</div>
</el-drawer>
</template>
<script lang="ts" setup>
import DrawerHeader from '@/components/drawer-header/index.vue';
import { GetCA } from '@/api/modules/website';
import { ref } from 'vue';
import i18n from '@/lang';
import useClipboard from 'vue-clipboard3';
import { MsgError, MsgSuccess } from '@/utils/message';
const { toClipboard } = useClipboard();
const open = ref(false);
const id = ref(0);
const curr = ref('detail');
const ca = ref<any>({});
const loading = ref(false);
const handleClose = () => {
open.value = false;
};
const acceptParams = (caID: number) => {
ca.value = {};
id.value = caID;
curr.value = 'detail';
get();
open.value = true;
};
const get = async () => {
const res = await GetCA(id.value);
ca.value = res.data;
};
const copyText = async (msg) => {
try {
await toClipboard(msg);
MsgSuccess(i18n.global.t('commons.msg.copySuccess'));
} catch (e) {
MsgError(i18n.global.t('commons.msg.copyFailed'));
}
};
defineExpose({
acceptParams,
});
</script>

View File

@ -7,28 +7,29 @@
<template #toolbar>
<el-button type="primary" @click="openCreate">{{ $t('ssl.createCA') }}</el-button>
</template>
<el-table-column
:label="$t('commons.table.name')"
fix
show-overflow-tooltip
prop="name"
min-width="100px"
></el-table-column>
<el-table-column :label="$t('website.keyType')" fix show-overflow-tooltip prop="keyType">
<el-table-column :label="$t('commons.table.name')" show-overflow-tooltip prop="name"></el-table-column>
<el-table-column :label="$t('website.keyType')" show-overflow-tooltip prop="keyType">
<template #default="{ row }">
{{ getKeyName(row.keyType) }}
</template>
</el-table-column>
<el-table-column
prop="createdAt"
:label="$t('commons.table.date')"
:formatter="dateFormat"
show-overflow-tooltip
/>
<fu-table-operations
:ellipsis="1"
:ellipsis="3"
:buttons="buttons"
:label="$t('commons.table.operate')"
fixed="right"
fix
width="250px"
/>
</ComplexTable>
<Create ref="createRef" @close="search()" />
<Obtain ref="obtainRef" @close="handleClose()" />
<Obtain ref="obtainRef" @close="search()" />
<Detail ref="detailRef" />
</el-drawer>
<OpDialog ref="opRef" @search="search" />
</template>
@ -41,7 +42,8 @@ import { DeleteCA, SearchCAs } from '@/api/modules/website';
import i18n from '@/lang';
import { reactive, ref } from 'vue';
import Create from './create/index.vue';
import { getKeyName } from '@/utils/util';
import Detail from './detail/index.vue';
import { getKeyName, dateFormat } from '@/utils/util';
import Obtain from './obtain/index.vue';
const open = ref(false);
@ -57,6 +59,7 @@ const paginationConfig = reactive({
const opRef = ref();
const obtainRef = ref();
const em = defineEmits(['close']);
const detailRef = ref();
const buttons = [
{
@ -65,6 +68,12 @@ const buttons = [
obtain(row);
},
},
{
label: i18n.global.t('ssl.detail'),
click: function (row: Website.CA) {
detailRef.value.acceptParams(row.id);
},
},
{
label: i18n.global.t('commons.button.delete'),
click: function (row: Website.CA) {