From 03fdc67ac0ad31bb52cae1332d1b7af469f5f241 Mon Sep 17 00:00:00 2001 From: vitshev Date: Thu, 6 Feb 2025 12:09:20 +0100 Subject: [PATCH] fix(ManageTokens): manage tokens does not work for http [#953] --- .../ManageTokensPasswordModal.tsx | 64 ++++++++++++++----- .../password-strategies.ts | 32 ++++++++++ packages/ui/src/ui/utils/sha256.ts | 4 ++ 3 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/password-strategies.ts diff --git a/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/ManageTokensPasswordModal.tsx b/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/ManageTokensPasswordModal.tsx index c64f707a1..74b0df98a 100644 --- a/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/ManageTokensPasswordModal.tsx +++ b/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/ManageTokensPasswordModal.tsx @@ -1,8 +1,8 @@ -import axios from 'axios'; import * as React from 'react'; import {useSelector} from 'react-redux'; -import {Alert, Dialog} from '@gravity-ui/uikit'; -import {sha256} from '../../../utils/sha256'; +import {Alert, Dialog, Link} from '@gravity-ui/uikit'; +import {isCryptoSubtleAvailable} from '../../../utils/sha256'; +import {createPasswordStrategy} from './password-strategies'; import {YTDFDialog, makeErrorFields} from '../../../components/Dialog'; import {getCurrentUserName, getSettingsCluster} from '../../../store/selectors/global'; import {YTError} from '../../../../@types/types'; @@ -31,6 +31,7 @@ const PasswordModal = (props: PasswordModalProps) => { headerProps={{ title: 'Authentication', @@ -41,26 +42,43 @@ const PasswordModal = (props: PasswordModalProps) => { initialValues={{}} onAdd={async (data) => { setError(undefined); - - const password = data.getState().values.password; - - return sha256(password).then((password_sha256) => { - axios - .post(`/api/yt/${ytAuthCluster}/login`, { - username, - password, - }) - .then(() => props.handleConfirm(password_sha256)) - .catch((error) => setError(error?.response?.data || error)); - }); + const {password, sha256_password} = data.getState().values; + + const strategy = createPasswordStrategy( + username, + ytAuthCluster, + isCryptoSubtleAvailable(), + ); + + return strategy(sha256_password || password) + .then((hashedPassword) => { + props.handleConfirm(hashedPassword); + }) + .catch(setError); }} fields={[ { name: 'error-block', type: 'block', extras: { - children: ( + children: isCryptoSubtleAvailable() ? ( + ) : ( + + + crypto.subtle + {' '} + is not available from your browser, so SHA-256 hash + cannot be generated. Please generate the hash of + your password by self. + + } + /> ), }, }, @@ -70,6 +88,20 @@ const PasswordModal = (props: PasswordModalProps) => { required: true, caption: 'Password', extras: () => ({type: 'password'}), + visibilityCondition: { + when: '', + isActive: () => isCryptoSubtleAvailable(), + }, + }, + { + name: 'sha256_password', + type: 'text', + required: true, + caption: 'Password Hash (SHA-256)', + visibilityCondition: { + when: '', + isActive: () => !isCryptoSubtleAvailable(), + }, }, ...makeErrorFields([error]), ]} diff --git a/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/password-strategies.ts b/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/password-strategies.ts new file mode 100644 index 000000000..2e44dae98 --- /dev/null +++ b/packages/ui/src/ui/containers/ManageTokens/ManageTokensPasswordModal/password-strategies.ts @@ -0,0 +1,32 @@ +import axios from 'axios'; +import {sha256} from '../../../utils/sha256'; + +type PasswordStrategy = (password: string) => Promise; + +const regularPasswordStrategy = (username: string, ytAuthCluster: string) => { + return async (password: string): Promise => { + const hashedPassword = await sha256(password); + await axios.post(`/api/yt/${ytAuthCluster}/login`, { + username, + password, + }); + + return hashedPassword; + }; +}; + +const sha256PasswordStrategy = () => { + return async (sha256Password: string): Promise => { + return sha256Password; + }; +}; + +export function createPasswordStrategy( + username: string, + ytAuthCluster: string, + isSha256Mode: boolean, +): PasswordStrategy { + return isSha256Mode + ? regularPasswordStrategy(username, ytAuthCluster) + : sha256PasswordStrategy(); +} diff --git a/packages/ui/src/ui/utils/sha256.ts b/packages/ui/src/ui/utils/sha256.ts index 03b0e582e..d90e67d90 100644 --- a/packages/ui/src/ui/utils/sha256.ts +++ b/packages/ui/src/ui/utils/sha256.ts @@ -3,3 +3,7 @@ export async function sha256(str: string) { return [...new Uint8Array(buf)].map((x) => ('00' + x.toString(16)).slice(-2)).join(''); } + +export const isCryptoSubtleAvailable = () => { + return Boolean(crypto?.subtle?.digest); +};