From edc3636ba04100e63c57cfc03f72247089cc575b Mon Sep 17 00:00:00 2001 From: Timofey Boyko Date: Fri, 8 Dec 2023 15:37:51 +0300 Subject: [PATCH] Client:PortalSettings:OAuth2: add reset client secret dialog --- packages/client/public/locales/en/OAuth.json | 4 +- .../ClientForm/ClientForm.types.ts | 6 +- .../ClientForm/components/ClientBlock.tsx | 2 +- .../ClientForm/components/InputGroup.tsx | 10 +- .../OAuth/sub-components/ClientForm/index.tsx | 156 ++++++++++-------- .../OAuth/sub-components/ResetDialog.tsx | 94 +++++++++++ packages/client/src/store/OAuthStore.ts | 24 +++ 7 files changed, 220 insertions(+), 76 deletions(-) create mode 100644 packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ResetDialog.tsx diff --git a/packages/client/public/locales/en/OAuth.json b/packages/client/public/locales/en/OAuth.json index 932636b8d7..5dc80db52c 100644 --- a/packages/client/public/locales/en/OAuth.json +++ b/packages/client/public/locales/en/OAuth.json @@ -18,7 +18,7 @@ "ClientHelpButton": "Credentials for using OAth 2.0 as your Authentication type.
Note: Any enterprise admin who knows the app's client ID will be able to retrieve information about the app including app name, authentication type, app scopes and redirect URI.", "CodeVerifier": "Code verifier", "DisableApplication": "Disable application", - "DisableApplicationDescription": "If you disable this application, all active consents will be revoked. If necessary, you can later enable the disabled application.
Note that all users will again be required to complete the consent screen.", + "DisableApplicationDescription": "If you disable this application, all active consents and authorization will be disabled. If necessary, you can later enable the disabled application.", "EditApp": "Edit application", "EnterDescription": "Enter description", "ErrorName": "Minimal name length:", @@ -43,7 +43,7 @@ "RegisterNewApp": "Register a new application", "Reset": "Reset", "ResetHeader": "Reset client secret", - "ResetDescription": "If you reset client secret, all active consents will be revoked. For apply next consent need use new client secret.
Note that all users will again be required to complete the consent screen.", + "ResetDescription": "If you reset client secret, all active consents and authorization will be revoked. For apply next consent need use new client secret. Note that all users will again be required to complete the consent screen.", "Revoke": "Revoke", "RevokeConsent": "Revoke consent", "RevokeConsentDescription": "Once you revoke the consent to use the ONLYOFFICE DocSpace auth data in the service {{name}}, ONLYOFFICE DocSpace will automatically stop logging into {{name}}. Your account in {{name}} will not be deleted.", diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/ClientForm.types.ts b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/ClientForm.types.ts index 7213b6758e..704518a24b 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/ClientForm.types.ts +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/ClientForm.types.ts @@ -52,9 +52,13 @@ export interface ClientFormProps { client: IClientReqDTO ) => Promise; - regenerateSecret?: (clientId: string) => Promise; + resetDialogVisible?: boolean; + setResetDialogVisible?: (value: boolean) => void; currentDeviceType?: DeviceUnionType; + + setClientSecretProps?: (value: string) => void; + clientSecretProps?: string; } export interface ClientStore { diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/ClientBlock.tsx b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/ClientBlock.tsx index 967971c0bf..f54f84a66f 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/ClientBlock.tsx +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/ClientBlock.tsx @@ -16,7 +16,7 @@ interface ClientBlockProps { idValue: string; secretValue: string; - onResetClick: () => Promise; + onResetClick: () => void; } const ClientBlock = ({ diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/InputGroup.tsx b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/InputGroup.tsx index 2686c18f35..7d390d289e 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/InputGroup.tsx +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/components/InputGroup.tsx @@ -25,7 +25,7 @@ interface InputGroupProps { helpButtonText?: string; buttonLabel?: string; - onButtonClick?: () => Promise; + onButtonClick?: () => void; withCopy?: boolean; onCopyClick?: (name: string) => void; @@ -66,15 +66,15 @@ const InputGroup = ({ }: InputGroupProps) => { const [isRequestRunning, setIsRequestRunning] = React.useState(false); - const onButtonClickAction = React.useCallback(async () => { + const onButtonClickAction = async () => { setIsRequestRunning(true); - await onButtonClick?.(); + onButtonClick?.(); setTimeout(() => { setIsRequestRunning(false); - }, 300); - }, [onButtonClick]); + }); + }; return ( diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/index.tsx b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/index.tsx index 25f01a316d..30a9903fcd 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/index.tsx +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ClientForm/index.tsx @@ -20,6 +20,7 @@ import { StyledContainer } from "./ClientForm.styled"; import { ClientFormProps, ClientStore } from "./ClientForm.types"; import ClientFormLoader from "./Loader"; +import ResetDialog from "../ResetDialog"; export function isValidUrl(url: string) { try { @@ -43,7 +44,11 @@ const ClientForm = ({ saveClient, updateClient, - regenerateSecret, + setResetDialogVisible, + resetDialogVisible, + + setClientSecretProps, + clientSecretProps, currentDeviceType, }: ClientFormProps) => { @@ -83,6 +88,13 @@ const ClientForm = ({ const isEdit = !!id; + React.useEffect(() => { + if (clientSecretProps) { + setClientSecret(clientSecretProps); + setClientSecretProps?.(""); + } + }, [clientSecretProps, setClientSecretProps]); + const onSaveClick = async () => { try { if (!id) { @@ -104,11 +116,11 @@ const ClientForm = ({ }; const onResetClick = React.useCallback(async () => { - if (!regenerateSecret) return; - const newSecret = await regenerateSecret(clientId); + if (!setResetDialogVisible) return; + setResetDialogVisible(true); - setClientSecret(newSecret); - }, [clientId, regenerateSecret]); + // setClientSecret(newSecret); + }, [clientId, setResetDialogVisible]); const onChangeForm = (name: string, value: string | boolean) => { setForm((val) => { @@ -374,70 +386,73 @@ const ClientForm = ({ const isValid = compareAndValidate(); return ( - - {isLoading ? ( - - ) : ( - <> - + + {isLoading ? ( + - {isEdit && ( - + - )} - - - - - - )} - + {isEdit && ( + + )} + + + + + + )} + + {resetDialogVisible && } + ); }; @@ -453,7 +468,11 @@ export default inject( saveClient, updateClient, - regenerateSecret, + setResetDialogVisible, + resetDialogVisible, + + setClientSecret, + clientSecret, } = oauthStore; const { currentDeviceType } = auth.settingsStore; @@ -467,8 +486,11 @@ export default inject( saveClient, updateClient, - regenerateSecret, + setResetDialogVisible, currentDeviceType, + resetDialogVisible, + setClientSecretProps: setClientSecret, + clientSecretProps: clientSecret, }; if (id) { diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ResetDialog.tsx b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ResetDialog.tsx new file mode 100644 index 0000000000..a34f5c727d --- /dev/null +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/OAuth/sub-components/ResetDialog.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { useParams } from "react-router-dom"; +import { inject, observer } from "mobx-react"; +import { useTranslation, Trans } from "react-i18next"; + +// @ts-ignore +import ModalDialog from "@docspace/components/modal-dialog"; +// @ts-ignore +import Button from "@docspace/components/button"; +// @ts-ignore +import toastr from "@docspace/components/toast/toastr"; + +// @ts-ignore +import { OAuthStoreProps } from "SRC_DIR/store/OAuthStore"; + +interface DisableClientDialog { + isVisible?: boolean; + onClose?: () => void; + onReset?: (id: string) => Promise; +} + +const DisableClientDialog = (props: DisableClientDialog) => { + const { id } = useParams(); + + const { t, ready } = useTranslation(["OAuth", "Common"]); + const { isVisible, onClose, onReset } = props; + + const [isRequestRunning, setIsRequestRunning] = React.useState(false); + + const onResetClick = async () => { + try { + setIsRequestRunning(true); + if (id) await onReset?.(id); + + setIsRequestRunning(true); + onClose?.(); + } catch (error) { + toastr.error(error); + onClose?.(); + } + }; + + return ( + + {t("ResetHeader")} + + + + +