Skip to content

Commit

Permalink
feat: improve credential management dialog (#254)
Browse files Browse the repository at this point in the history
* feat: misc improvements to credential management dialog

* fix: padding
  • Loading branch information
rohan-chaturvedi authored May 14, 2024
1 parent ac09473 commit f24b1a8
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 37 deletions.
4 changes: 2 additions & 2 deletions frontend/components/syncing/ProviderCredentialCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ export const ProviderCredentialCard = (props: { credential: ProviderCredentialsT

<UpdateProviderCredentials credential={credential} />

<div className="flex justify-end">
{/* <div className="flex justify-end">
<DeleteProviderCredentialDialog
credential={credential}
orgId={organisation!.id}
/>
</div>
</div> */}
</Dialog.Panel>
</Transition.Child>
</div>
Expand Down
85 changes: 50 additions & 35 deletions frontend/components/syncing/UpdateProviderCredentials.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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
Expand All @@ -29,15 +31,27 @@ export const UpdateProviderCredentials = (props: { credential: ProviderCredentia
const [credentials, setCredentials] = useState<CredentialState>(
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)
)
Expand All @@ -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 (
<div className="space-y-4 w-full py-4">
<div className="space-y-4 w-full pt-4">
<div className="text-black dark:text-white font-semibold text-xl flex justify-between">
<div className="flex items-center gap-2">
{' '}
<ProviderIcon providerId={credential.provider?.id!} /> {credential.provider?.name}{' '}
Credentials
</div>
{activeUserIsAdmin && (
<div>
{allowEdit ? (
<div className="flex items-center gap-2">
<Button
disabled={!credentialsUpdated}
variant="primary"
onClick={handleUpdateCredentials}
>
<FaCheck /> Save
</Button>{' '}
<Button
variant={credentialsUpdated ? 'danger' : 'secondary'}
onClick={() => setAllowEdit(false)}
>
<FaTimes /> {credentialsUpdated ? 'Discard' : 'Cancel'}
</Button>
</div>
) : (
<Button variant="outline" onClick={() => setAllowEdit(true)}>
<FaEdit /> Edit
</Button>
)}
</div>
)}
</div>

<Input
required
value={name}
setValue={(value) => setName(value)}
setValue={(value) => handleNameChange(value)}
label="Name"
readOnly={!allowEdit}
disabled={!allowEdit}
Expand All @@ -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) => (
<Input
key={credential}
value={credentials[credential]}
setValue={(value) => handleCredentialChange(credential, value)}
label={credential.replace(/_/g, ' ').toUpperCase()}
secret={true}
readOnly={!allowEdit}
disabled={!allowEdit}
/>
))}

{credential.provider?.id === 'aws' && (
<AWSRegionPicker onChange={(region) => handleCredentialChange('region', region)} />
)}
<div className="flex justify-between pt-6">
<DeleteProviderCredentialDialog credential={credential} orgId={organisation!.id} />
<Button
disabled={!credentialsUpdated}
variant="primary"
onClick={handleSaveUpdatedCredentials}
>
<FaCheck /> Save
</Button>
</div>
</div>
)
}
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
5 changes: 5 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit f24b1a8

Please sign in to comment.