You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/10/24 01:48:17 UTC

[apisix-dashboard] branch master updated: feat(SSL): added SSL (#596)

This is an automated email from the ASF dual-hosted git repository.

juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 62ce9e2  feat(SSL): added SSL (#596)
62ce9e2 is described below

commit 62ce9e2e7a650c9935aa51e34fdeec5d38067062
Author: 琚致远 <ju...@apache.org>
AuthorDate: Sat Oct 24 09:48:10 2020 +0800

    feat(SSL): added SSL (#596)
    
    * feat(SSL): added SSL
    
    * feat: added sni search
    
    * feat: update i18n
---
 src/helpers.tsx                                    | 11 ++--
 src/locales/en-US/component.ts                     | 17 -------
 src/locales/zh-CN/component.ts                     | 17 -------
 src/pages/SSL/Create.tsx                           |  9 +---
 src/pages/SSL/List.tsx                             | 59 ++++------------------
 src/pages/SSL/components/CertificateForm/index.tsx |  6 +--
 src/pages/SSL/locales/en-US.ts                     |  3 +-
 src/pages/SSL/locales/zh-CN.ts                     |  5 +-
 src/pages/SSL/service.ts                           | 46 +++++------------
 src/pages/SSL/typing.d.ts                          | 28 ++++------
 10 files changed, 44 insertions(+), 157 deletions(-)

diff --git a/src/helpers.tsx b/src/helpers.tsx
index 096c85c..6956bff 100644
--- a/src/helpers.tsx
+++ b/src/helpers.tsx
@@ -34,12 +34,11 @@ export const getMenuData = (): MenuDataItem[] => {
       path: '/routes/list',
       icon: <IconFont type="iconroute" />,
     },
-    // NOTE: disable SSL module in v2.0
-    // {
-    //   name: 'ssl',
-    //   path: '/ssl/list',
-    //   icon: <IconFont type="iconSSLshuzizhengshu" />,
-    // },
+    {
+      name: 'ssl',
+      path: '/ssl/list',
+      icon: <IconFont type="iconSSLshuzizhengshu" />,
+    },
     {
       name: 'upstream',
       path: '/upstream/list',
diff --git a/src/locales/en-US/component.ts b/src/locales/en-US/component.ts
index 12a9fc8..1864cef 100644
--- a/src/locales/en-US/component.ts
+++ b/src/locales/en-US/component.ts
@@ -59,21 +59,4 @@ export default {
   // User component
   'component.user.loginByPassword': 'Username & Password',
   'component.user.login': 'Login',
-  'component.user.username': 'Username',
-  'component.user.password': 'Password',
-  'component.user.rememberMe': 'Remember Me',
-  'component.user.inputUsername': 'Please input username!',
-  'component.user.inputPassword': 'Please input password!',
-  'component.user.wrongUsernameOrPassword': 'Wrong account or password!',
-  // SSL Module
-  'component.ssl.removeSSLItemModalContent': 'You are going to remove this item!',
-  'component.ssl.removeSSLItemModalTitle': 'SSL Remove Alert',
-  'component.ssl.fetchSSLListSuccess': 'Fetch SSL list successfully',
-  'component.ssl.removeSSLSuccess': 'Remove target SSL successfully',
-  'component.ssl.fieldSNIInvalid': 'Please check SNI',
-  'component.ssl.fieldKeyInvalid': 'Please check Key',
-  'component.ssl.fieldCertInvalid': 'Please check Cert',
-  'component.ssl.invalidKey': 'Invalid Key',
-  'component.ssl.fieldKeyTooShort': 'Key is too short, 128 characters at least.',
-  'component.ssl.fieldCertTooShort': 'Cert is too short, 128 characters at least.',
 };
diff --git a/src/locales/zh-CN/component.ts b/src/locales/zh-CN/component.ts
index e807c15..a074362 100644
--- a/src/locales/zh-CN/component.ts
+++ b/src/locales/zh-CN/component.ts
@@ -55,21 +55,4 @@ export default {
   // User component
   'component.user.loginByPassword': '账号密码登录',
   'component.user.login': '登录',
-  'component.user.username': '账号',
-  'component.user.password': '密码',
-  'component.user.rememberMe': '自动登录',
-  'component.user.inputUsername': '请输入账号!',
-  'component.user.inputPassword': '请输入密码!',
-  'component.user.wrongUsernameOrPassword': '账号或密码错误!',
-  // SSL Module
-  'component.ssl.removeSSLItemModalContent': '确定要删除该项吗?',
-  'component.ssl.removeSSLItemModalTitle': '删除 SSL',
-  'component.ssl.fetchSSLListSuccess': '获取 SSL 列表成功',
-  'component.ssl.removeSSLSuccess': '删除 SSL 成功',
-  'component.ssl.fieldSNIInvalid': '请检查 SNI 值',
-  'component.ssl.fieldKeyInvalid': '请检查 Key 值',
-  'component.ssl.fieldCertInvalid': '请检查 Cert 值',
-  'component.ssl.invalidKey': '非法的 Key',
-  'component.ssl.fieldKeyTooShort': 'Key 值过短,至少需要128位!',
-  'component.ssl.fieldCertTooShort': 'Cert 值过短,至少需要128位!',
 };
diff --git a/src/pages/SSL/Create.tsx b/src/pages/SSL/Create.tsx
index 01b64a2..395bff1 100644
--- a/src/pages/SSL/Create.tsx
+++ b/src/pages/SSL/Create.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 import React, { useState } from 'react';
-import { Card, Steps, notification, Form } from 'antd';
+import { Card, Steps, Form } from 'antd';
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
 import moment from 'moment';
 import { history, useIntl } from 'umi';
@@ -48,13 +48,6 @@ const Page: React.FC = (props) => {
           expireTime: moment.unix(Number(data.validity_end)).format('YYYY-MM-DD HH:mm:ss'),
         });
         setStep(2);
-      })
-      .catch(() => {
-        notification.warning({
-          message: `${formatMessage({ id: 'component.global.pleaseCheck' })}${formatMessage({
-            id: 'page.ssl.form.itemLabel.cert',
-          })}`,
-        });
       });
   };
 
diff --git a/src/pages/SSL/List.tsx b/src/pages/SSL/List.tsx
index 7517c1c..c69c314 100644
--- a/src/pages/SSL/List.tsx
+++ b/src/pages/SSL/List.tsx
@@ -14,43 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, { useRef, useState } from 'react';
+import React, { useRef } from 'react';
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
 import ProTable, { ProColumns, ActionType } from '@ant-design/pro-table';
-import { Button, Switch, Popconfirm, notification, Tag, Input } from 'antd';
+import { Button, Popconfirm, notification, Tag } from 'antd';
 import { useIntl, history } from 'umi';
 import { PlusOutlined } from '@ant-design/icons';
 import moment from 'moment';
 
-import { fetchList as fetchSSLList, remove as removeSSL, switchEnable } from '@/pages/SSL/service';
+import { fetchList, remove as removeSSL } from '@/pages/SSL/service';
 
 const Page: React.FC = () => {
-  const [search, setSearch] = useState('');
-
   const tableRef = useRef<ActionType>();
   const { formatMessage } = useIntl();
 
-  const onEnableChange = (id: string, checked: boolean) => {
-    switchEnable(id, checked)
-      .then(() => {
-        notification.success({
-          message: formatMessage({
-            id: 'page.ssl.notification.updateCertEnableStatusSuccessfully',
-          }),
-        });
-      })
-      .catch(() => {
-        /* eslint-disable no-unused-expressions */
-        tableRef.current?.reload();
-      });
-  };
-
-  const columns: ProColumns<SSLModule.ResSSL>[] = [
+  const columns: ProColumns<SSLModule.ResponseBody>[] = [
     {
       title: 'SNI',
       dataIndex: 'sni',
       render: (_, record) => {
-        return record.snis.map((sni) => (
+        return (record.snis || []).map((sni) => (
           <Tag color="geekblue" key={sni}>
             {sni}
           </Tag>
@@ -64,19 +47,6 @@ const Page: React.FC = () => {
       render: (text) => `${moment.unix(Number(text)).format('YYYY-MM-DD HH:mm:ss')}`,
     },
     {
-      title: formatMessage({ id: 'page.ssl.list.ifEnable' }),
-      dataIndex: 'status',
-      hideInSearch: true,
-      render: (text, record) => (
-        <Switch
-          defaultChecked={Number(text) === 1}
-          onChange={(checked: boolean) => {
-            onEnableChange(record.id, checked);
-          }}
-        />
-      ),
-    },
-    {
       title: formatMessage({ id: 'component.global.updateTime' }),
       dataIndex: 'update_time',
       hideInSearch: true,
@@ -97,7 +67,7 @@ const Page: React.FC = () => {
             {formatMessage({ id: 'component.global.edit' })}
           </Button>
           <Popconfirm
-            title={formatMessage({ id: 'component.global.delete' })}
+            title={formatMessage({ id: 'component.ssl.removeSSLItemModalContent' })}
             onConfirm={() =>
               removeSSL(record.id).then(() => {
                 notification.success({
@@ -111,7 +81,7 @@ const Page: React.FC = () => {
             okText={formatMessage({ id: 'component.global.confirm' })}
           >
             <Button type="primary" danger>
-              {formatMessage({ id: 'component.global.remove' })}
+              {formatMessage({ id: 'component.global.delete' })}
             </Button>
           </Popconfirm>
         </>
@@ -131,21 +101,12 @@ const Page: React.FC = () => {
         id: 'component.global.list',
       })}`}
     >
-      <ProTable<SSLModule.ResSSL>
-        search={false}
+      <ProTable<SSLModule.ResponseBody>
         rowKey="id"
         columns={columns}
         actionRef={tableRef}
-        request={(params) => fetchSSLList(params, search)}
-        toolBarRender={(action) => [
-          <Input.Search
-            placeholder={formatMessage({ id: 'component.global.pleaseEnter' })}
-            onSearch={(value) => {
-              setSearch(value);
-              action.setPageInfo({ page: 1 });
-              action.reload();
-            }}
-          />,
+        request={fetchList}
+        toolBarRender={() => [
           <Button type="primary" onClick={() => history.push(`/ssl/create`)}>
             <PlusOutlined />
             {formatMessage({ id: 'component.global.create' })}
diff --git a/src/pages/SSL/components/CertificateForm/index.tsx b/src/pages/SSL/components/CertificateForm/index.tsx
index a0a4b26..0e667eb 100644
--- a/src/pages/SSL/components/CertificateForm/index.tsx
+++ b/src/pages/SSL/components/CertificateForm/index.tsx
@@ -75,11 +75,7 @@ const CertificateForm: React.FC<CertificateFormProps> = ({ mode, form }) => {
           },
         ]}
       >
-        <Input.TextArea
-          rows={6}
-          disabled={mode !== 'EDIT'}
-          placeholder={formatMessage({ id: 'page.ssl.textAreaPlaceholder.cert' })}
-        />
+        <Input.TextArea rows={6} disabled={mode !== 'EDIT'} />
       </Form.Item>
       <Form.Item
         label={formatMessage({ id: 'page.ssl.form.itemLabel.privateKey' })}
diff --git a/src/pages/SSL/locales/en-US.ts b/src/pages/SSL/locales/en-US.ts
index c80b97d..884fbaa 100644
--- a/src/pages/SSL/locales/en-US.ts
+++ b/src/pages/SSL/locales/en-US.ts
@@ -22,7 +22,6 @@ export default {
   'page.ssl.form.itemLabel.privateKey': 'Private Key',
   'page.ssl.form.itemRuleMessage.privateKeyLength':
     'The Private Key requires at least 128 characters',
-  'page.ssl.textAreaPlaceholder.cert': 'Please enter the SSL Certificate Content',
 
   'page.ssl.button.uploadCert': 'Upload Certificate',
 
@@ -39,4 +38,6 @@ export default {
   'page.ssl.list.ifEnable': 'If Enable',
   'page.ssl.list.periodOfValidity': 'Period Of Validity',
   'page.ssl.steps.stepTitle.completeCertInfo': 'Complete Certificate Information',
+  'component.ssl.removeSSLSuccess': 'Remove target SSL successfully',
+  'component.ssl.removeSSLItemModalContent': 'You are going to remove this item!',
 };
diff --git a/src/pages/SSL/locales/zh-CN.ts b/src/pages/SSL/locales/zh-CN.ts
index 232c80a..88145df 100644
--- a/src/pages/SSL/locales/zh-CN.ts
+++ b/src/pages/SSL/locales/zh-CN.ts
@@ -16,11 +16,10 @@
  */
 export default {
   'page.ssl.form.itemLabel.expireTime': '过期时间',
-  'page.ssl.form.itemLabel.cert': '证书内容',
+  'page.ssl.form.itemLabel.cert': '证书',
   'page.ssl.form.itemRuleMessage.certValueLength': '证书内容至少需要128个字符',
   'page.ssl.form.itemLabel.privateKey': '私钥',
   'page.ssl.form.itemRuleMessage.privateKeyLength': '私钥 至少需要128个字符',
-  'page.ssl.textAreaPlaceholder.cert': '请填写SSL证书内容',
 
   'page.ssl.button.uploadCert': '上传证书',
 
@@ -35,4 +34,6 @@ export default {
   'page.ssl.list.ifEnable': '是否启用',
   'page.ssl.list.periodOfValidity': '有效期',
   'page.ssl.steps.stepTitle.completeCertInfo': '完善证书信息',
+  'component.ssl.removeSSLSuccess': '删除证书成功',
+  'component.ssl.removeSSLItemModalContent': '确定要删除该证书吗?',
 };
diff --git a/src/pages/SSL/service.ts b/src/pages/SSL/service.ts
index 5513b88..d526827 100644
--- a/src/pages/SSL/service.ts
+++ b/src/pages/SSL/service.ts
@@ -15,61 +15,41 @@
  * limitations under the License.
  */
 import { request } from 'umi';
-import querystring from 'querystring';
-import { identity, pickBy, omit } from 'lodash';
 
-export const fetchList = (
-  { current = 1, pageSize = 10, ...props }: SSLModule.FetchListParams,
-  search: string,
-) => {
-  const [expire_start, expire_end] = (props.expire_range || '').split(':');
-  let queryObj = omit(props, 'expire_range', '_timestamp');
-  queryObj = pickBy({ ...queryObj, expire_start, expire_end, sni: search }, identity);
-  const query = querystring.encode(queryObj);
-  return request<{ count: number; list: SSLModule.ResSSL[] }>(
-    `/ssl?page=${current}&page_size=${pageSize}&${query}`,
-  ).then((data) => {
+export const fetchList = ({ current = 1, pageSize = 10, ...res }) => {
+  return request<Res<ResListData<SSLModule.ResponseBody>>>('/ssl', {
+    params: {
+      page: current,
+      page_size: pageSize,
+      ...res,
+    },
+  }).then(({ data }) => {
     return {
-      total: data.count,
-      data: data.list.map((item) => ({
-        ...item,
-        sni: item.snis.join(';'),
-      })),
+      total: data.total_size,
+      data: data.rows,
     };
   });
 };
 
 export const remove = (id: string) =>
-  request(`/ssls/${id}`, {
+  request(`/ssl/${id}`, {
     method: 'DELETE',
   });
 
 export const create = (data: SSLModule.SSL) =>
-  request('/ssls', {
+  request('/ssl', {
     method: 'POST',
     data,
   });
 
-/**
- * 1. 校验证书是否匹配
- * 2. 解析公钥内容
- * */
 export const verifyKeyPaire = (cert = '', key = ''): Promise<SSLModule.VerifyKeyPaireProps> =>
   request('/check_ssl_cert', {
     method: 'POST',
     data: { cert, key },
   });
 
-export const switchEnable = (id: string, checked: boolean) =>
-  request(`/ssls/${id}`, {
-    method: 'PATCH',
-    data: {
-      status: Number(checked),
-    },
-  });
-
 export const update = (id: string, data: SSLModule.SSL) =>
-  request(`/ssls/${id}`, {
+  request(`/ssl/${id}`, {
     method: 'PUT',
     data,
   });
diff --git a/src/pages/SSL/typing.d.ts b/src/pages/SSL/typing.d.ts
index 652a436..985e305 100644
--- a/src/pages/SSL/typing.d.ts
+++ b/src/pages/SSL/typing.d.ts
@@ -21,17 +21,6 @@ declare namespace SSLModule {
     key: string;
   };
 
-  type ResSSL = {
-    id: string;
-    create_time: number;
-    update_time: number;
-    validity_start: number;
-    validity_end: number;
-    status: number;
-    snis: string[];
-    public_key: string;
-  };
-
   type UploadPublicSuccessData = {
     cert: string;
     publicKeyList: UploadFile[];
@@ -56,13 +45,14 @@ declare namespace SSLModule {
     };
   };
 
-  type FetchListParams = {
-    current?: number;
-    pageSize?: number;
-    sni?: string;
-    expire_range?: string;
-    expire_start?: number;
-    expire_end?: number;
-    status?: 0;
+  type ResponseBody = {
+    id: string;
+    cert: string;
+    create_time: number;
+    snis: string[];
+    status: number;
+    update_time: number;
+    validity_start: number;
+    validity_end: number;
   };
 }