Browse Source

完善SSL模块

main
dark 5 months ago
parent
commit
c5c0b02f97
  1. 12
      src/components/drawer-picker/DrawerPicker.tsx
  2. 78
      src/pages/websites/ssl/components/CAList.tsx
  3. 1
      src/pages/websites/ssl/components/DNSList.tsx
  4. 34
      src/pages/websites/ssl/index.tsx
  5. 7
      src/request.ts
  6. 11
      src/store/websites/ca.ts
  7. 16
      src/types/website/acme.d.ts
  8. 18
      src/types/website/ca.d.ts
  9. 8
      src/types/website/dns.d.ts
  10. 30
      src/types/website/ssl.d.ts

12
src/components/drawer-picker/DrawerPicker.tsx

@ -7,9 +7,10 @@ export interface DrawerPickerProps extends DrawerProps {
target?: React.ReactNode
children?: React.ReactNode
key?: string
foreRender?: boolean
}
const DrawerPicker = ({ children, target, ...props }: DrawerPickerProps) => {
const DrawerPicker = ({ children, target, foreRender, ...props }: DrawerPickerProps) => {
const { styles } = useStyle()
@ -22,15 +23,18 @@ const DrawerPicker = ({ children, target, ...props }: DrawerPickerProps) => {
return (
<div className={styles.container} key={props.key ?? generateUUID()}>
<span className={styles.target} onClick={() => {
<div className={styles.target} onClick={() => {
setOpen(true)
}}>
{getTarget()}
</span>
<Drawer {...props}
</div>
{
(foreRender || open) && <Drawer {...props}
open={open}
onClose={() => setOpen(false)}
>{children}</Drawer>
}
</div>
)
}

78
src/pages/websites/ssl/components/CAList.tsx

@ -4,7 +4,7 @@ import { ICA, } from '@/types/website/ca'
import { useTranslation } from '@/i18n.ts'
import { deleteCaAtom } from '@/store/websites/ca.ts'
import { useAtom, useAtomValue } from 'jotai'
import { Alert, Button, Form, Popconfirm } from 'antd'
import { Button, Form, Popconfirm } from 'antd'
import { KeyTypeEnum, KeyTypes } from '@/store/websites/ssl.ts'
import { caListAtom, caPageAtom, saveOrUpdateCaAtom } from '@/store/websites/ca.ts'
@ -39,6 +39,68 @@ const CAList = () => {
]
}
},
{
title: t('website.ssl.ca.form.common_name', '证书主体名称(CN)'),
dataIndex: 'common_name',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {
rules: [
{ required: true, message: t('message.required', '请输入') }
]
}
},
{
title: t('website.ssl.ca.form.organization', '公司/组织'),
dataIndex: 'organization',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {
rules: [
{ required: true, message: t('message.required', '请输入') }
]
}
},
{
title: t('website.ssl.ca.form.organization_uint', '部门'),
dataIndex: 'organization_uint',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {}
},
{
title: t('website.ssl.ca.form.country', '国家代号'),
dataIndex: 'country',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {
rules: [
{ required: true, message: t('message.required', '请输入') }
]
}
},
{
title: t('website.ssl.ca.form.province', '省份'),
dataIndex: 'province',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {}
},
{
title: t('website.ssl.ca.form.city', '城市'),
dataIndex: 'city',
hideInTable: true,
hideInSetting: true,
valueType: 'text',
formItemProps: {}
},
{
title: t('website.ssl.ca.columns.keyType', '密钥算法'),
@ -54,12 +116,12 @@ const CAList = () => {
},
},
{
title: t('website.ssl.ca.columns.url', 'URL'),
dataIndex: 'url',
valueType: 'text',
ellipsis: true, // 文本溢出省略
title: t('website.ssl.ca.columns.createAt', '时间'),
dataIndex: 'create_at',
valueType: 'dateTime',
hideInForm: true,
}, {
},
{
title: '操作',
valueType: 'option',
render: (_, record) => {
@ -83,7 +145,6 @@ const CAList = () => {
return (
<>
<Alert message={t('website.ssl.ca.tip', 'ca账户用于申请免费证书')}/>
<ProTable<ICA>
cardProps={{
bodyStyle: {
@ -96,11 +157,12 @@ const CAList = () => {
onClick={() => {
form.setFieldsValue({
id: 0,
country: 'CN',
keyType: KeyTypeEnum.EC256,
})
setOpen(true)
}}
type={'primary'}>{t('website.ssl.ca.add', '添加ca帐户')}</Button>
type={'primary'}>{t('website.ssl.ca.add', '创建机构')}</Button>
}
loading={isLoading}
dataSource={data?.rows ?? []}

1
src/pages/websites/ssl/components/DNSList.tsx

@ -192,6 +192,7 @@ const DNSList = () => {
{
name: [ 'type' ],
valueType: 'dependency',
hideInSetting: true,
columns: ({ type }) => {
return getKeyColumn(type, t)
}

34
src/pages/websites/ssl/index.tsx

@ -21,6 +21,7 @@ import AcmeList from './components/AcmeList.tsx'
import { acmeListAtom, AcmeType, getAcmeAccountTypeName } from '@/store/websites/acme.ts'
import { dnsListAtom, getDNSTypeName } from '@/store/websites/dns.ts'
import DNSList from './components/DNSList.tsx'
import CAList from '@/pages/websites/ssl/components/CAList.tsx'
const SSL = () => {
@ -33,7 +34,7 @@ const SSL = () => {
const { data: dnsData, isLoading: dnsLoading } = useAtomValue(dnsListAtom)
const { data, isLoading, isFetching, refetch } = useAtomValue(sslListAtom)
const { mutate: saveOrUpdate, isSuccess, isPending: isSubmitting } = useAtomValue(saveOrUpdateSslAtom)
const { mutate: delateSSL, isPending: isDeleteing } = useAtomValue(deleteSslAtom)
const { mutate: deleteSSL, isPending: isDeleting } = useAtomValue(deleteSslAtom)
const [ open, setOpen ] = useState(false)
@ -125,6 +126,7 @@ const SSL = () => {
{
name: [ 'provider' ],
valueType: 'dependency',
hideInSetting: true,
columns: ({ provider }) => {
if (provider === ProviderTypeEnum.DnsAccount) {
return [ {
@ -141,8 +143,6 @@ const SSL = () => {
value: item.id
}))
},
} ]
}
return []
@ -166,6 +166,7 @@ const SSL = () => {
{
name: [ 'pushDir' ],
valueType: 'dependency',
hideInSetting: true,
columns: ({ pushDir }) => {
if (pushDir) {
return [ {
@ -198,9 +199,9 @@ const SSL = () => {
</a>,
<Popconfirm
key={'del_confirm'}
disabled={isDeleteing}
disabled={isDeleting}
onConfirm={() => {
delateSSL(record.id)
deleteSSL(record.id)
}}
title={t('message.deleteConfirm')}>
<a key="del">
@ -222,6 +223,11 @@ const SSL = () => {
rowKey={'id'}
dataSource={data?.rows ?? []}
columns={columns}
columnsState={{
defaultValue: {
option: { fixed: 'right', disable: true },
},
}}
options={{
reload: () => {
refetch()
@ -238,9 +244,19 @@ const SSL = () => {
actions: [
<DrawerPicker
maskClosable={false}
title={t('website.ssl.actions.acme', 'Acme帐户')}
title={t('website.ssl.ca.title', '证书颁发机构')}
width={1000}
target={<Button type={'primary'} ghost={true}>
{t('website.ssl.actions.selfSigned', '自签证书')}
</Button>}
>
<CAList/>
</DrawerPicker>,
<DrawerPicker
maskClosable={false}
title={t('website.ssl.acme.title', 'Acme帐户')}
width={1000}
target={<Button>
target={<Button type={'primary'} ghost={true}>
{t('website.ssl.actions.acme', 'Acme帐户')}
</Button>}
>
@ -248,9 +264,9 @@ const SSL = () => {
</DrawerPicker>,
<DrawerPicker
maskClosable={false}
title={t('website.ssl.actions.dns', 'DNS帐户')}
title={t('website.ssl.dns.title', 'DNS帐户')}
width={1000}
target={<Button>
target={<Button type={'primary'} ghost={true}>
{t('website.ssl.actions.dns', 'DNS帐户')}
</Button>}>
<DNSList/>

7
src/request.ts

@ -46,7 +46,6 @@ axiosInstance.interceptors.response.use(
message.destroy()
const result = response.data as IApiResult
switch (result.code) {
case 200:
//login
@ -105,6 +104,12 @@ axiosInstance.interceptors.response.use(
}
window.location.href = `/login?redirect=${encodeURIComponent(redirect)}`
return
case 403:
message.error('没有权限')
break
case 404:
message.error('请求的资源不存在')
break
default:
message.error(response.data.message ?? response.data ?? error.message ?? '请求失败')
return Promise.reject(response)

11
src/store/websites/ca.ts

@ -2,7 +2,7 @@ import { atom } from 'jotai/index'
import { IApiResult, IPage } from '@/global'
import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query'
import websitesServ from '@/service/websites.ts'
import { message } from 'antd'
import { message, } from 'antd'
import { t } from 'i18next'
import { ICA } from '@/types/website/ca'
@ -22,7 +22,7 @@ export const caListAtom = atomWithQuery(get => ({
}))
//saveOrUpdate
export const saveOrUpdateCaAtom = atomWithMutation<any, ICA>(get => ({
export const saveOrUpdateCaAtom = atomWithMutation<any, ICA, IApiResult>(get => ({
mutationKey: [ 'saveOrUpdateCA' ],
mutationFn: async (data: ICA) => {
if (data.id > 0) {
@ -35,7 +35,12 @@ export const saveOrUpdateCaAtom = atomWithMutation<any, ICA>(get => ({
message.success(t(isAdd ? 'message.saveSuccess' : 'message.editSuccess', '保存成功'))
get(caListAtom).refetch()
return res
}
},
// onError: (err) => {
// const msg = err.data?.message || err.message || t('message.saveFail', '提交失败')
// message.error(msg)
// return err
// },
}))
export const deleteCaAtom = atomWithMutation<IApiResult, number>(get => ({

16
src/types/website/acme.d.ts

@ -1,14 +1,14 @@
export interface IAcmeAccount {
id: number;
createdAt?: string;
createdBy: number;
updatedAt?: string;
updatedBy: number;
created_at: string | null;
created_by: number;
updated_at: string | null;
updated_by: number;
email: string;
url: string;
privateKey: string;
private_key: string;
type: string;
eabKid: string;
eabHmacKey: string;
keyType: string;
eab_kid: string;
eab_hmac_key: string;
key_type: string;
}

18
src/types/website/ca.d.ts

@ -1,11 +1,17 @@
export interface ICA {
id: number;
createdAt: string | null;
createdBy: number;
updatedAt: string | null;
updatedBy: number;
created_at: string | null;
created_by: number;
updated_at: string | null;
updated_by: number;
csr: string;
name: string;
privateKey: string;
keyType: string;
common_name: string;
organization: string;
organization_unit: string;
country: string;
province: string;
city: string;
private_key: string;
key_type: string;
}

8
src/types/website/dns.d.ts

@ -1,9 +1,9 @@
export interface IDnsAccount {
id: number;
createdAt: string | null;
createdBy: number;
updatedAt: string | null;
updatedBy: number;
created_at: string | null;
created_by: number;
updated_at: string | null;
updated_by: number;
name: string;
type: string;
authorization: string;

30
src/types/website/ssl.d.ts

@ -1,27 +1,27 @@
export interface ISSL {
id: number;
createdAt: Date | null;
createdBy: number;
updatedAt: Date | null;
updatedBy: number;
primaryDomain: string;
privateKey: string;
created_at: string | null;
created_by: number;
updated_at: string | null;
updated_by: number;
primary_domain: string;
private_key: string;
pem: string;
domains: string;
certUrl: string;
cert_url: string;
type: string;
provider: string;
organization: string;
dnsAccountId: number;
acmeAccountId: number;
caId: number;
autoRenew: boolean;
expireDate: string | null;
startDate: string | null;
dns_account_id: number;
acme_account_id: number;
ca_id: number;
auto_renew: boolean;
expire_date: string | null;
start_date: string | null;
status: string;
message: string;
keyType: string;
pushDir: boolean;
key_type: string;
push_dir: boolean;
dir: string;
description: string;
}

Loading…
Cancel
Save