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",