You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by le...@apache.org on 2022/08/04 03:11:54 UTC

[inlong] branch master updated: [INLONG-5235][Dashboard] Support users to modify passwords and modify personal keys (#5344)

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

leezng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new c565545e0 [INLONG-5235][Dashboard] Support users to modify passwords and modify personal keys (#5344)
c565545e0 is described below

commit c565545e029faa64cff04c677e288562bcf35d71
Author: Lizhen <88...@users.noreply.github.com>
AuthorDate: Thu Aug 4 11:11:48 2022 +0800

    [INLONG-5235][Dashboard] Support users to modify passwords and modify personal keys (#5344)
---
 .../src/components/Layout/NavWidget/KeyModal.tsx   | 126 +++++++++++++++++++
 .../components/Layout/NavWidget/PasswordModal.tsx  | 138 +++++++++++++++++++++
 .../src/components/Layout/NavWidget/index.tsx      |  35 +++++-
 inlong-dashboard/src/locales/cn.json               |   6 +
 inlong-dashboard/src/locales/en.json               |   6 +
 5 files changed, 310 insertions(+), 1 deletion(-)

diff --git a/inlong-dashboard/src/components/Layout/NavWidget/KeyModal.tsx b/inlong-dashboard/src/components/Layout/NavWidget/KeyModal.tsx
new file mode 100644
index 000000000..5389cb579
--- /dev/null
+++ b/inlong-dashboard/src/components/Layout/NavWidget/KeyModal.tsx
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useState } from 'react';
+import { Modal, message } from 'antd';
+import { ModalProps } from 'antd/es/modal';
+import FormGenerator, { useForm } from '@/components/FormGenerator';
+import { useUpdateEffect, useRequest } from '@/hooks';
+import request from '@/utils/request';
+import { useTranslation } from 'react-i18next';
+
+export interface Props extends ModalProps {
+  id?: number;
+}
+
+const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
+  const { t } = useTranslation();
+  const [form] = useForm();
+  const [userId, setId] = useState(null);
+  const [userData, setData] = useState({
+    id: null,
+    name: '',
+    version: null,
+    accountType: null,
+    validDays: null,
+  }) as any;
+
+  const content = [
+    {
+      type: 'input',
+      label: 'SecretKey',
+      name: 'secretKey',
+      rules: [{ required: true }],
+    },
+    {
+      type: 'input',
+      label: 'PublicKey',
+      name: 'publicKey',
+      rules: [{ required: true }],
+    },
+    {
+      type: 'input',
+      label: 'PrivateKey',
+      name: 'privateKey',
+      rules: [{ required: true }],
+    },
+  ];
+
+  const { run: getData } = useRequest(
+    {
+      url: `/user/currentUser`,
+      method: 'post',
+    },
+    {
+      manual: true,
+      onSuccess: result => {
+        form.setFieldsValue(result);
+        setId(result.id);
+      },
+    },
+  );
+
+  const { run: getDays } = useRequest(
+    {
+      url: `/user/get/${userId}`,
+    },
+    {
+      manual: true,
+      onSuccess: result => {
+        setData({
+          id: result.id,
+          name: result.name,
+          version: result.version,
+          validDays: result.validDays,
+          accountType: result.accountType,
+        });
+      },
+    },
+  );
+
+  const onOk = async () => {
+    const values = await form.validateFields();
+    const data = { ...userData, ...values };
+    await request({
+      url: '/user/update',
+      method: 'POST',
+      data: data,
+    });
+    message.success(t('basic.OperatingSuccess'));
+    await modalProps?.onOk(data);
+  };
+
+  useUpdateEffect(() => {
+    if (modalProps.visible) {
+      getData();
+    }
+  }, [modalProps.visible]);
+
+  useUpdateEffect(() => {
+    if (userId !== null) {
+      getDays();
+    }
+  }, [userId]);
+
+  return (
+    <Modal {...modalProps} title={t('components.Layout.NavWidget.PersonalKey')} onOk={onOk}>
+      <FormGenerator content={content} form={form} useMaxWidth />
+    </Modal>
+  );
+};
+
+export default Comp;
diff --git a/inlong-dashboard/src/components/Layout/NavWidget/PasswordModal.tsx b/inlong-dashboard/src/components/Layout/NavWidget/PasswordModal.tsx
new file mode 100644
index 000000000..69201aaae
--- /dev/null
+++ b/inlong-dashboard/src/components/Layout/NavWidget/PasswordModal.tsx
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useState } from 'react';
+import { Modal, message } from 'antd';
+import { ModalProps } from 'antd/es/modal';
+import FormGenerator, { useForm } from '@/components/FormGenerator';
+import { useUpdateEffect, useRequest } from '@/hooks';
+import request from '@/utils/request';
+import { useTranslation } from 'react-i18next';
+
+export interface Props extends ModalProps {
+  id?: number;
+}
+
+const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
+  const { t } = useTranslation();
+  const [form] = useForm();
+  const [userId, setId] = useState(null);
+  const [userData, setData] = useState({
+    id: null,
+    name: '',
+    version: null,
+    accountType: null,
+    validDays: null,
+  }) as any;
+
+  const content = [
+    {
+      type: 'password',
+      label: t('components.Layout.NavWidget.Password'),
+      name: 'password',
+      rules: [{ required: true }],
+    },
+    {
+      type: 'password',
+      label: t('components.Layout.NavWidget.NewPassword'),
+      name: 'newPassword',
+      rules: [{ required: true }],
+    },
+    {
+      type: 'password',
+      label: t('components.Layout.NavWidget.ConfirmPassword'),
+      name: 'confirmPassword',
+      rules: [
+        { required: true },
+        ({ getFieldValue }) => ({
+          validator(_, val) {
+            if (val) {
+              const newPassword = getFieldValue(['newPassword']);
+              return newPassword === val
+                ? Promise.resolve()
+                : Promise.reject(new Error(t('components.Layout.NavWidget.Remind')));
+            }
+            return Promise.resolve();
+          },
+        }),
+      ],
+    },
+  ];
+
+  const { run: getData } = useRequest(
+    {
+      url: `/user/currentUser`,
+      method: 'post',
+    },
+    {
+      manual: true,
+      onSuccess: result => {
+        setId(result.id);
+      },
+    },
+  );
+
+  const { run: getDays } = useRequest(
+    {
+      url: `/user/get/${userId}`,
+    },
+    {
+      manual: true,
+      onSuccess: result => {
+        setData({
+          id: result.id,
+          name: result.name,
+          version: result.version,
+          validDays: result.validDays,
+          accountType: result.accountType,
+        });
+      },
+    },
+  );
+
+  const onOk = async () => {
+    const values = await form.validateFields();
+    const data = { ...userData, ...values };
+    await request({
+      url: '/user/update',
+      method: 'POST',
+      data: data,
+    });
+    message.success(t('basic.OperatingSuccess'));
+    await modalProps?.onOk(data);
+  };
+
+  useUpdateEffect(() => {
+    if (modalProps.visible) {
+      getData();
+    }
+  }, [modalProps.visible]);
+
+  useUpdateEffect(() => {
+    if (userId !== null) {
+      getDays();
+    }
+  }, [userId]);
+
+  return (
+    <Modal {...modalProps} title={t('components.Layout.NavWidget.EditPassword')} onOk={onOk}>
+      <FormGenerator content={content} form={form} useMaxWidth />
+    </Modal>
+  );
+};
+
+export default Comp;
diff --git a/inlong-dashboard/src/components/Layout/NavWidget/index.tsx b/inlong-dashboard/src/components/Layout/NavWidget/index.tsx
index 4a96a5b69..fb3d95101 100644
--- a/inlong-dashboard/src/components/Layout/NavWidget/index.tsx
+++ b/inlong-dashboard/src/components/Layout/NavWidget/index.tsx
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import React from 'react';
+import React, { useState } from 'react';
 import { Dropdown, Menu } from 'antd';
 import { useHistory, useSelector, useDispatch, useRequest } from '@/hooks';
 import { State } from '@/models';
@@ -25,6 +25,8 @@ import { useTranslation } from 'react-i18next';
 // import { FileTextOutlined } from '@/components/Icons';
 import LocaleSelect from './LocaleSelect';
 import styles from './index.module.less';
+import PasswordModal from './PasswordModal';
+import KeyModal from './KeyModal';
 
 const Comp: React.FC = () => {
   const { t } = useTranslation();
@@ -32,6 +34,14 @@ const Comp: React.FC = () => {
   const history = useHistory();
   const dispatch = useDispatch();
 
+  const [createModal, setCreateModal] = useState<Record<string, unknown>>({
+    visible: false,
+  });
+
+  const [keyModal, setKeyModal] = useState<Record<string, unknown>>({
+    visible: false,
+  });
+
   const { run: runLogout } = useRequest('/anno/logout', {
     manual: true,
     onSuccess: () => {
@@ -48,6 +58,12 @@ const Comp: React.FC = () => {
 
   const menu = (
     <Menu>
+      <Menu.Item onClick={() => setCreateModal({ visible: true })}>
+        {t('components.Layout.NavWidget.EditPassword')}
+      </Menu.Item>
+      <Menu.Item onClick={() => setKeyModal({ visible: true })}>
+        {t('components.Layout.NavWidget.PersonalKey')}
+      </Menu.Item>
       <Menu.Item onClick={runLogout}>{t('components.Layout.NavWidget.Logout')}</Menu.Item>
     </Menu>
   );
@@ -65,6 +81,23 @@ const Comp: React.FC = () => {
       <Dropdown overlay={menu} placement="bottomLeft">
         <span>{userName}</span>
       </Dropdown>
+      <PasswordModal
+        {...createModal}
+        visible={createModal.visible as boolean}
+        onCancel={() => setCreateModal({ visible: false })}
+        onOk={async () => {
+          runLogout();
+          setCreateModal({ visible: false });
+        }}
+      />
+      <KeyModal
+        {...keyModal}
+        visible={keyModal.visible as boolean}
+        onCancel={() => setKeyModal({ visible: false })}
+        onOk={async () => {
+          setKeyModal({ visible: false });
+        }}
+      />
     </div>
   );
 };
diff --git a/inlong-dashboard/src/locales/cn.json b/inlong-dashboard/src/locales/cn.json
index c8c292456..172e5fd7b 100644
--- a/inlong-dashboard/src/locales/cn.json
+++ b/inlong-dashboard/src/locales/cn.json
@@ -264,6 +264,12 @@
   "components.FormGenerator.plugins.PleaseInput": "请输入",
   "components.TextSwitch.Title": "高级选项",
   "components.Layout.NavWidget.Logout": "退出登录",
+  "components.Layout.NavWidget.EditPassword": "修改密码",
+  "components.Layout.NavWidget.PersonalKey": "个人密钥",
+  "components.Layout.NavWidget.Password": "旧密码",
+  "components.Layout.NavWidget.NewPassword": "新密码",
+  "components.Layout.NavWidget.ConfirmPassword": "确认密码",
+  "components.Layout.NavWidget.Remind": "密码不一致,请重新输入",
   "components.StaffSelect.Placeholder": "请输入关键字搜索",
   "configs.pagination.Total": "共{{total}}项",
   "pages.AccessCreate.Business.config.AccessScale": "接入规模",
diff --git a/inlong-dashboard/src/locales/en.json b/inlong-dashboard/src/locales/en.json
index be92cab2e..d94c18bba 100644
--- a/inlong-dashboard/src/locales/en.json
+++ b/inlong-dashboard/src/locales/en.json
@@ -264,6 +264,12 @@
   "components.FormGenerator.plugins.PleaseInput": "Please input",
   "components.TextSwitch.Title": "Advanced options",
   "components.Layout.NavWidget.Logout": "Logout",
+  "components.Layout.NavWidget.EditPassword": "EditPassword",
+  "components.Layout.NavWidget.PersonalKey": "PersonalKey",
+  "components.Layout.NavWidget.Password": "Old password",
+  "components.Layout.NavWidget.NewPassword": "New password",
+  "components.Layout.NavWidget.ConfirmPassword": "Confirm password",
+  "components.Layout.NavWidget.Remind": "Password does not match, please re-enter",
   "components.StaffSelect.Placeholder": "Please enter a keyword search",
   "configs.pagination.Total": "Total {{total}} items",
   "pages.AccessCreate.Business.config.AccessScale": "Access scale",