Skip to content

Commit

Permalink
fix: misc cleanup for secret history optimization (#411)
Browse files Browse the repository at this point in the history
* fix: misc cleanup

* fix: improve created by display

* fix: restore button alignment

* fix: misc styling

* fix: add timestamp to title

* feat: close history dialog on restore
  • Loading branch information
rohan-chaturvedi authored Dec 10, 2024
1 parent 0ee083a commit 2fbd42e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 27 deletions.
52 changes: 38 additions & 14 deletions frontend/components/environments/secrets/HistoryDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { relativeTimeFromDates } from '@/utils/time'
import clsx from 'clsx'
import { GetSecretHistory } from '@/graphql/queries/secrets/getSecretHistory.gql'
import { useState, Fragment, useEffect, useContext } from 'react'
import { FaHistory, FaTimes, FaKey } from 'react-icons/fa'
import { FaHistory, FaKey, FaRobot, FaTimes } from 'react-icons/fa'
import { SecretPropertyDiffs } from './SecretPropertyDiffs'
import { Button } from '../../common/Button'
import { Dialog, Transition } from '@headlessui/react'
Expand Down Expand Up @@ -86,23 +86,21 @@ export const HistoryDialog = ({

const { publicKey, privateKey } = await envKeyring(seed)

console.log('decrupting', data.secrets[0].id)

const decryptedSecret = await decryptSecretHistory(data.secrets[0], {
privateKey,
publicKey,
salt: '',
})

setClientSecret(decryptedSecret)
console.log('Decrypted secret:', decryptedSecret)
}
} catch (error) {
console.error('Error fetching or decrypting secret history:', error)
}
}

if (keyring && isOpen) fetchAndDecryptHistory()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [keyring, isOpen, secret, getHistory])

const getEventTypeColor = (eventType: ApiSecretEventEventTypeChoices) => {
Expand All @@ -119,6 +117,32 @@ export const HistoryDialog = ({
if (eventType === ApiSecretEventEventTypeChoices.D) return 'Deleted'
}

const eventCreatedBy = (log: SecretEventType) => {
if (log.user)
return (
<div className="flex items-center gap-1 text-sm">
<Avatar imagePath={log.user?.avatarUrl!} size="sm" />
{log.user.fullName || log.user.email}
</div>
)
else if (log.serviceToken)
return (
<div className="flex items-center gap-1 text-sm">
<FaKey /> {log.serviceToken ? log.serviceToken.name : 'Service token'}
</div>
)
else if (log.serviceAccount)
return (
<div className="flex items-center gap-1 text-sm">
<div className="rounded-full flex items-center bg-neutral-500/40 justify-center size-6">
<FaRobot className=" text-zinc-900 dark:text-zinc-100" />
</div>{' '}
{log.serviceAccount.name}
{log.serviceAccountToken && ` (${log.serviceAccountToken.name})`}
</div>
)
}

const secretHistory = clientSecret?.history

return (
Expand Down Expand Up @@ -193,17 +217,16 @@ export const HistoryDialog = ({
<div className="text-zinc-800 dark:text-zinc-200 font-semibold">
{getEventTypeText(historyItem!.eventType)}
</div>
<div className="text-neutral-500 text-sm">
<div
className="text-neutral-500 text-sm"
title={new Date(historyItem!.timestamp).toLocaleTimeString()}
>
{relativeTimeFromDates(new Date(historyItem!.timestamp))}
</div>{' '}
<div className="text-sm flex items-center gap-2 text-neutral-500">
{historyItem!.user && (
<div className="flex items-center gap-1 text-sm">
by{' '}
<Avatar imagePath={historyItem!.user.avatarUrl!} size="sm" />
{historyItem?.user.fullName || historyItem?.user.email}
</div>
)}
</div>
<span className="text-neutral-500 text-sm">by</span>

<div className="text-zinc-900 dark:text-zinc-100">
{eventCreatedBy(historyItem!)}
</div>
</div>
{index > 0 && (
Expand All @@ -212,6 +235,7 @@ export const HistoryDialog = ({
historyItem={historyItem!}
index={index}
handlePropertyChange={handlePropertyChange}
onRestore={closeModal}
/>
)}
</div>
Expand Down
34 changes: 21 additions & 13 deletions frontend/components/environments/secrets/SecretPropertyDiffs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import { FaRedoAlt, FaUndoAlt } from 'react-icons/fa'
import { Button } from '../../common/Button'
import { Tag } from '../Tag'

export const SecretPropertyDiffs = (props: {
export const SecretPropertyDiffs = ({
secret,
historyItem,
index,
handlePropertyChange,
onRestore,
}: {
secret: SecretType
historyItem: SecretEventType
index: number
handlePropertyChange: Function
onRestore: Function
}) => {
const { secret, historyItem, index, handlePropertyChange } = props

const previousItem = secret.history![index - 1]!

const getAddedTags = () => {
Expand All @@ -30,6 +35,7 @@ export const SecretPropertyDiffs = (props: {

const handleRestoreValue = (value: string) => {
handlePropertyChange(secret.id, 'value', value)
onRestore()
}

return (
Expand All @@ -51,19 +57,21 @@ export const SecretPropertyDiffs = (props: {
<div className="flex items-center gap-2">
<span className="text-neutral-500 mr-2">VALUE:</span>
</div>
<div className="flex flex-col">
<div className="flex flex-col w-full">
<div className="flex-1 items-end gap-4 justify-between bg-red-200 dark:bg-red-950">
<div>
<s className=" text-red-500 ph-no-capture">{previousItem.value}</s>
</div>
<Button
variant="outline"
onClick={() => handleRestoreValue(previousItem.value)}
title="Restore this value"
>
<FaRedoAlt className="shrink-0" />
<span className="font-sans text-xs">Restore</span>
</Button>
<div className="flex items-center justify-end p-1">
<Button
variant="outline"
onClick={() => handleRestoreValue(previousItem.value)}
title="Restore this value"
>
<FaRedoAlt className="shrink-0 text-2xs" />
<span className="font-sans text-2xs">Restore</span>
</Button>
</div>
</div>
<span className="bg-emerald-100 dark:bg-emerald-950 text-emerald-500 ph-no-capture">
{historyItem!.value}
Expand All @@ -83,7 +91,7 @@ export const SecretPropertyDiffs = (props: {
</span>
</div>
)}

{historyItem!.path !== previousItem.path && (
<div className="pl-3 font-mono break-all">
<span className="text-neutral-500 mr-2">PATH:</span>
Expand Down

0 comments on commit 2fbd42e

Please sign in to comment.