Files
infisical/frontend/ee/components/SecretVersionList.tsx
T

104 lines
4.1 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { useTranslation } from "next-i18next";
import { faCircle, faDotCircle } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import getSecretVersions from 'ee/api/secrets/GetSecretVersions';
import { decryptAssymmetric, decryptSymmetric } from '~/components/utilities/cryptography/crypto';
import getLatestFileKey from '~/pages/api/workspace/getLatestFileKey';
interface DecryptedSecretVersionListProps {
createdAt: string;
value: string;
}
interface EncrypetedSecretVersionListProps {
createdAt: string;
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
}
/**
* @returns a list of versions for a specific secret
*/
const SecretVersionList = ({ secretId }: { secretId: string; }) => {
const router = useRouter();
const { t } = useTranslation();
const [secretVersions, setSecretVersions] = useState<DecryptedSecretVersionListProps[]>([{createdAt: "123", value: "124"}]);
useEffect(() => {
const getSecretVersionHistory = async () => {
try {
const encryptedSecretVersions = await getSecretVersions({ secretId, offset: 0, limit: 10});
const latestKey = await getLatestFileKey({ workspaceId: String(router.query.id) })
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
let decryptedLatestKey: string;
if (latestKey) {
// assymmetrically decrypt symmetric key with local private key
decryptedLatestKey = decryptAssymmetric({
ciphertext: latestKey.latestKey.encryptedKey,
nonce: latestKey.latestKey.nonce,
publicKey: latestKey.latestKey.sender.publicKey,
privateKey: String(PRIVATE_KEY)
});
}
const decryptedSecretVersions = encryptedSecretVersions.secretVersions.map((encryptedSecretVersion: EncrypetedSecretVersionListProps) => {
return {
createdAt: encryptedSecretVersion.createdAt,
value: decryptSymmetric({
ciphertext: encryptedSecretVersion.secretValueCiphertext,
iv: encryptedSecretVersion.secretValueIV,
tag: encryptedSecretVersion.secretValueTag,
key: decryptedLatestKey
})
}
})
setSecretVersions(decryptedSecretVersions);
} catch (error) {
console.log(error)
}
};
getSecretVersionHistory();
}, []);
return <div className='w-full h-52 px-4 mt-4 text-sm text-bunker-300 overflow-x-none'>
<p className=''>{t("dashboard:sidebar.version-history")}</p>
<div className='p-1 rounded-md bg-bunker-800 border border-mineshaft-500 overflow-x-none'>
<div className='h-48 overflow-y-auto overflow-x-none'>
{secretVersions?.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
.map((version: DecryptedSecretVersionListProps, index: number) =>
<div key={index} className='flex flex-row'>
<div className='pr-1 flex flex-col items-center'>
<div className='p-1'><FontAwesomeIcon icon={index == 0 ? faDotCircle : faCircle} /></div>
<div className='w-0 h-full border-l mt-1'></div>
</div>
<div className='flex flex-col w-full max-w-[calc(100%-2.3rem)]'>
<div className='pr-2 pt-1'>
{(new Date(version.createdAt)).toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})}
</div>
<div className=''><p className='break-words'><span className='py-0.5 px-1 rounded-md bg-primary-200/10 mr-1.5'>Value:</span>{version.value}</p></div>
{/* <div className=''><p className='break-words'><span className='py-0.5 px-1 rounded-md bg-primary-200/10 mr-1.5'>Updated by:</span>{version.user}</p></div> */}
</div>
</div>
)}
</div>
</div>
</div>
};
export default SecretVersionList;