From f24b1a8cd8eea8fba703b9e725dce81cc2b1f3cf Mon Sep 17 00:00:00 2001 From: Rohan Chaturvedi Date: Tue, 14 May 2024 20:13:12 +0530 Subject: [PATCH] feat: improve credential management dialog (#254) * feat: misc improvements to credential management dialog * fix: padding --- .../syncing/ProviderCredentialCard.tsx | 4 +- .../syncing/UpdateProviderCredentials.tsx | 85 +++++++++++-------- frontend/package.json | 2 + frontend/yarn.lock | 5 ++ 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/frontend/components/syncing/ProviderCredentialCard.tsx b/frontend/components/syncing/ProviderCredentialCard.tsx index bcf1f90e..0c1382ae 100644 --- a/frontend/components/syncing/ProviderCredentialCard.tsx +++ b/frontend/components/syncing/ProviderCredentialCard.tsx @@ -99,12 +99,12 @@ export const ProviderCredentialCard = (props: { credential: ProviderCredentialsT -
+ {/*
-
+
*/} diff --git a/frontend/components/syncing/UpdateProviderCredentials.tsx b/frontend/components/syncing/UpdateProviderCredentials.tsx index 9507eebc..676caf31 100644 --- a/frontend/components/syncing/UpdateProviderCredentials.tsx +++ b/frontend/components/syncing/UpdateProviderCredentials.tsx @@ -1,7 +1,7 @@ import { ProviderCredentialsType } from '@/apollo/graphql' import { Button } from '@/components/common/Button' -import { useContext, useState } from 'react' -import { FaCheck, FaEdit, FaTimes } from 'react-icons/fa' +import { useContext, useEffect, useState } from 'react' +import { FaCheck } from 'react-icons/fa' import GetServerKey from '@/graphql/queries/syncing/getServerKey.gql' import UpdateProviderCreds from '@/graphql/mutations/syncing/updateProviderCreds.gql' @@ -13,6 +13,8 @@ import { organisationContext } from '@/contexts/organisationContext' import { userIsAdmin } from '@/utils/permissions' import { ProviderIcon } from './ProviderIcon' import { AWSRegionPicker } from './AWS/AWSRegionPicker' +import { DeleteProviderCredentialDialog } from './DeleteProviderCredentialDialog' +import { isEqual } from 'lodash' interface CredentialState { [key: string]: string @@ -29,15 +31,27 @@ export const UpdateProviderCredentials = (props: { credential: ProviderCredentia const [credentials, setCredentials] = useState( JSON.parse(credential.credentials) ) - const [allowEdit, setAllowEdit] = useState(false) - const credentialsUpdated = true + const [credentialsUpdated, setCredentialsUpdated] = useState(false) + + useEffect(() => { + const credsAreEqual = isEqual(credentials, JSON.parse(credential.credentials)) + const nameIsEqual = isEqual(name, credential.name) + + setCredentialsUpdated(!credsAreEqual || !nameIsEqual) + }, [credentials, credential.credentials, credential.name, name]) const handleCredentialChange = (key: string, value: string) => { + //setCredentialsUpdated(true) setCredentials({ ...credentials, [key]: value }) } - const handleUpdateCredentials = async () => { + const handleNameChange = (newName: string) => { + //setCredentialsUpdated(true) + setName(newName) + } + + const handleSaveUpdatedCredentials = async () => { const encryptedCredentials = JSON.stringify( await encryptProviderCredentials(credential.provider!, credentials, data.serverPublicKey) ) @@ -49,52 +63,31 @@ export const UpdateProviderCredentials = (props: { credential: ProviderCredentia credentials: encryptedCredentials, }, }) - - setAllowEdit(false) + setCredentialsUpdated(false) toast.success('Saved credentials') } const activeUserIsAdmin = organisation ? userIsAdmin(organisation.role!) : false + const allowEdit = activeUserIsAdmin + + const isCredentialSecret = (credential: string) => + !/(?:addr|host)/i.test(credential.toLowerCase()) + return ( -
+
{' '} {credential.provider?.name}{' '} Credentials
- {activeUserIsAdmin && ( -
- {allowEdit ? ( -
- {' '} - -
- ) : ( - - )} -
- )}
setName(value)} + setValue={(value) => handleNameChange(value)} label="Name" readOnly={!allowEdit} disabled={!allowEdit} @@ -109,15 +102,37 @@ export const UpdateProviderCredentials = (props: { credential: ProviderCredentia setValue={(value) => handleCredentialChange(credential, value)} label={credential.replace(/_/g, ' ').toUpperCase()} required - secret={true} + secret={isCredentialSecret(credential)} readOnly={!allowEdit} disabled={!allowEdit} /> ))} + {credential.provider?.optionalCredentials.map((credential: string) => ( + handleCredentialChange(credential, value)} + label={credential.replace(/_/g, ' ').toUpperCase()} + secret={true} + readOnly={!allowEdit} + disabled={!allowEdit} + /> + ))} + {credential.provider?.id === 'aws' && ( handleCredentialChange('region', region)} /> )} +
+ + +
) } diff --git a/frontend/package.json b/frontend/package.json index 64a155da..ba4e84bf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -32,6 +32,7 @@ "jsonwebtoken": "^9.0.2", "jspdf": "^2.5.1", "libsodium-wrappers-sumo": "^0.7.13", + "lodash": "^4.17.21", "next": "^14.2.3", "next-auth": "^4.24.5", "nextjs-toploader": "^1.6.4", @@ -54,6 +55,7 @@ "@types/jest": "^29.5.11", "@types/jsonwebtoken": "^9.0.5", "@types/libsodium-wrappers-sumo": "^0.7.8", + "@types/lodash": "^4.17.1", "@types/react-icons": "^3.0.0", "@types/zxcvbn": "^4.4.4", "@typescript-eslint/eslint-plugin": "^6.19.1", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 89bf9847..86068571 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2318,6 +2318,11 @@ version "0.7.10" resolved "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz" +"@types/lodash@^4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.1.tgz#0fabfcf2f2127ef73b119d98452bd317c4a17eb8" + integrity sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q== + "@types/node@*": version "20.5.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.1.tgz#178d58ee7e4834152b0e8b4d30cbfab578b9bb30"