Fixed dashboard for the corner case of purely personal secrets

This commit is contained in:
Vladyslav Matsiiako
2023-02-19 12:02:30 -08:00
parent b6bbfc08ad
commit 0062df58a2
6 changed files with 79 additions and 60 deletions
@@ -13,6 +13,7 @@ export interface SecretDataProps {
value: string | undefined; value: string | undefined;
valueOverride: string | undefined; valueOverride: string | undefined;
id: string; id: string;
idOverride?: string;
comment: string; comment: string;
tags: Tag[]; tags: Tag[];
} }
@@ -99,8 +99,8 @@ const DashboardInputField = ({
/> />
</div> </div>
)} )}
{!error && <div className={`absolute right-0 top-0 text-red z-50 ${ {!error && <div className={`absolute right-0 top-0 text-red z-50 bg-mineshaft-800 group-hover:bg-mineshaft-700 ${
overrideEnabled ? 'visible group-hover:bg-mineshaft-700' : 'invisible group-hover:visible bg-mineshaft-700' overrideEnabled ? 'visible' : 'invisible group-hover:visible'
} cursor-pointer duration-0 h-10 flex items-center px-2`}> } cursor-pointer duration-0 h-10 flex items-center px-2`}>
<button type="button" onClick={() => { <button type="button" onClick={() => {
if (modifyValueOverride) { if (modifyValueOverride) {
@@ -55,7 +55,7 @@ const colorsText = [
/** /**
* This component represent a single row for an environemnt variable on the dashboard * This component represent a single row for an environemnt variable on the dashboard
* @param {object} obj * @param {object} obj
* @param {String[]} obj.keyPair - data related to the environment variable (id, pos, key, value, public/private) * @param {SecretDataProps[]} obj.keyPair - data related to the environment variable (id, pos, key, value, public/private)
* @param {function} obj.modifyKey - modify the key of a certain environment variable * @param {function} obj.modifyKey - modify the key of a certain environment variable
* @param {function} obj.modifyValue - modify the value of a certain environment variable * @param {function} obj.modifyValue - modify the value of a certain environment variable
* @param {function} obj.modifyValueOverride - modify the value of a certain environment variable if it is overriden * @param {function} obj.modifyValueOverride - modify the value of a certain environment variable if it is overriden
@@ -108,7 +108,7 @@ const KeyPair = ({
isCapitalized = {isCapitalized} isCapitalized = {isCapitalized}
onChangeHandler={modifyKey} onChangeHandler={modifyKey}
type="varName" type="varName"
id={keyPair.id} id={keyPair.id ? keyPair.id : (keyPair.idOverride || '')}
value={keyPair.key} value={keyPair.key}
isDuplicate={isDuplicate} isDuplicate={isDuplicate}
overrideEnabled={keyPair.valueOverride !== undefined} overrideEnabled={keyPair.valueOverride !== undefined}
@@ -124,7 +124,7 @@ const KeyPair = ({
<DashboardInputField <DashboardInputField
onChangeHandler={keyPair.valueOverride !== undefined ? modifyValueOverride : modifyValue} onChangeHandler={keyPair.valueOverride !== undefined ? modifyValueOverride : modifyValue}
type="value" type="value"
id={keyPair.id} id={keyPair.id ? keyPair.id : (keyPair.idOverride || '')}
value={keyPair.valueOverride !== undefined ? keyPair.valueOverride : keyPair.value} value={keyPair.valueOverride !== undefined ? keyPair.valueOverride : keyPair.value}
blurred={isBlurred} blurred={isBlurred}
overrideEnabled={keyPair.valueOverride !== undefined} overrideEnabled={keyPair.valueOverride !== undefined}
@@ -137,7 +137,7 @@ const KeyPair = ({
<DashboardInputField <DashboardInputField
onChangeHandler={modifyComment} onChangeHandler={modifyComment}
type="comment" type="comment"
id={keyPair.id} id={keyPair.id ? keyPair.id : (keyPair.idOverride || '')}
value={keyPair.comment} value={keyPair.comment}
isDuplicate={isDuplicate} isDuplicate={isDuplicate}
isSideBarOpen={keyPair.id === sidebarSecretId} isSideBarOpen={keyPair.id === sidebarSecretId}
@@ -153,7 +153,7 @@ const KeyPair = ({
</div> </div>
))} ))}
<AddTagsMenu allTags={tags} currentTags={keyPair.tags} modifyTags={modifyTags} id={keyPair.id} /> <AddTagsMenu allTags={tags} currentTags={keyPair.tags} modifyTags={modifyTags} id={keyPair.id ? keyPair.id : (keyPair.idOverride || '')} />
</div> </div>
</div> </div>
<div <div
@@ -93,7 +93,7 @@ export default function Navbar() {
}; };
return ( return (
<div className="flex flex-row justify-between w-full bg-bunker text-white border-b border-mineshaft-500 z-[61]"> <div className="flex flex-row justify-between w-full bg-bunker text-white border-b border-mineshaft-500 z-[71]">
<div className="m-auto flex justify-start items-center mx-4"> <div className="m-auto flex justify-start items-center mx-4">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<div className="flex justify-center py-4"> <div className="flex justify-center py-4">
@@ -166,7 +166,7 @@ export default function Navbar() {
leaveFrom="transform opacity-100 scale-100" leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95" leaveTo="transform opacity-0 scale-95"
> >
<Menu.Items className="absolute right-0 mt-0.5 w-64 origin-top-right divide-y divide-gray-700 rounded-md bg-bunker border border-mineshaft-700 shadow-lg ring-1 ring-black z-[65] ring-opacity-5 focus:outline-none"> <Menu.Items className="absolute right-0 mt-0.5 w-64 origin-top-right divide-y divide-gray-700 rounded-md bg-bunker border border-mineshaft-700 shadow-lg ring-1 ring-black z-[999] ring-opacity-5 focus:outline-none">
<div className="px-1 py-1 z-[100]"> <div className="px-1 py-1 z-[100]">
<div className="text-gray-400 self-start ml-2 mt-2 text-xs font-semibold tracking-wide"> <div className="text-gray-400 self-start ml-2 mt-2 text-xs font-semibold tracking-wide">
{t('nav:user.signed-in-as')} {t('nav:user.signed-in-as')}
@@ -102,7 +102,9 @@ const PITRecoverySidebar = ({ toggleSidebar, setSnapshotData, chosenSnapshot }:
}); });
} }
const decryptedSecretVersions = secretSnapshotData.secretVersions.map( const decryptedSecretVersions = secretSnapshotData.secretVersions.filter(
(sv: EncrypetedSecretVersionListProps) => (sv.type !== undefined && sv.environment !== undefined)
).map(
(encryptedSecretVersion: EncrypetedSecretVersionListProps, pos: number) => ({ (encryptedSecretVersion: EncrypetedSecretVersionListProps, pos: number) => ({
id: encryptedSecretVersion._id, id: encryptedSecretVersion._id,
pos, pos,
@@ -125,10 +127,13 @@ const PITRecoverySidebar = ({ toggleSidebar, setSnapshotData, chosenSnapshot }:
); );
const secretKeys = [ const secretKeys = [
...new Set(decryptedSecretVersions.map((secret: SecretDataProps) => secret.key)) ...new Set(decryptedSecretVersions.filter((dsv: any) => dsv.type !== undefined || dsv.environemnt !== undefined)
.map((secret: SecretDataProps) => secret.key))
]; ];
const result = secretKeys.map((key, index) => ({ const result = secretKeys.map((key, index) => (decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'shared'
)[0]?.id ? {
id: decryptedSecretVersions.filter( id: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'shared' (secret: SecretDataProps) => secret.key === key && secret.type === 'shared'
)[0].id, )[0].id,
@@ -146,6 +151,24 @@ const PITRecoverySidebar = ({ toggleSidebar, setSnapshotData, chosenSnapshot }:
valueOverride: decryptedSecretVersions.filter( valueOverride: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'personal' (secret: SecretDataProps) => secret.key === key && secret.type === 'personal'
)[0]?.value )[0]?.value
} : {
id: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'personal'
)[0].id,
pos: index,
key,
environment: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'personal'
)[0].environment,
tags: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'personal'
)[0].tags,
value: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'shared'
)[0]?.value,
valueOverride: decryptedSecretVersions.filter(
(secret: SecretDataProps) => secret.key === key && secret.type === 'personal'
)[0]?.value
})); }));
setSnapshotData({ setSnapshotData({
@@ -161,7 +184,7 @@ const PITRecoverySidebar = ({ toggleSidebar, setSnapshotData, chosenSnapshot }:
<div <div
className={`absolute border-l border-mineshaft-500 w-full min-w-sm max-w-sm ${ className={`absolute border-l border-mineshaft-500 w-full min-w-sm max-w-sm ${
isLoading ? 'bg-bunker-800' : 'bg-bunker' isLoading ? 'bg-bunker-800' : 'bg-bunker'
} fixed h-full right-0 z-[70] shadow-xl flex flex-col justify-between sticky top-0`} } fixed h-full right-0 z-[40] shadow-xl flex flex-col justify-between sticky top-0`}
> >
{isLoading ? ( {isLoading ? (
<div className="flex items-center justify-center h-full mb-8"> <div className="flex items-center justify-center h-full mb-8">
+42 -47
View File
@@ -332,27 +332,27 @@ export default function Dashboard() {
}; };
const modifyValue = (value: string, id: string) => { const modifyValue = (value: string, id: string) => {
setData((oldData) => oldData?.map((e) => (e.id === id ? { ...e, value } : e))); setData((oldData) => oldData?.map((e) => ((e.id ? e.id : e.idOverride) === id ? { ...e, value } : e)));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}; };
const modifyValueOverride = (valueOverride: string | undefined, id: string) => { const modifyValueOverride = (valueOverride: string | undefined, id: string) => {
setData((oldData) => oldData?.map((e) => (e.id === id ? { ...e, valueOverride } : e))); setData((oldData) => oldData?.map((e) => ((e.id ? e.id : e.idOverride) === id ? { ...e, valueOverride } : e)));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}; };
const modifyKey = (key: string, id: string) => { const modifyKey = (key: string, id: string) => {
setData((oldData) => oldData?.map((e) => (e.id === id ? { ...e, key } : e))); setData((oldData) => oldData?.map((e) => ((e.id ? e.id : e.idOverride) === id ? { ...e, key } : e)));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}; };
const modifyComment = (comment: string, id: string) => { const modifyComment = (comment: string, id: string) => {
setData((oldData) => oldData?.map((e) => (e.id === id ? { ...e, comment } : e))); setData((oldData) => oldData?.map((e) => ((e.id ? e.id : e.idOverride) === id ? { ...e, comment } : e)));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}; };
const modifyTags = (tags: Tag[], id: string) => { const modifyTags = (tags: Tag[], id: string) => {
setData((oldData) => oldData?.map((e) => (e.id === id ? { ...e, tags } : e))); setData((oldData) => oldData?.map((e) => ((e.id ? e.id : e.idOverride) === id ? { ...e, tags } : e)));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}; };
@@ -444,7 +444,8 @@ export default function Dashboard() {
initialData! initialData!
.filter( .filter(
(initDataPoint) => (initDataPoint) =>
newData!.map((dataPoint) => dataPoint.id).includes(initDataPoint.id) && newData!.filter((dataPoint) => dataPoint.id)
.map((dataPoint) => dataPoint.id).includes(initDataPoint.id) &&
(newData!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0].value !== (newData!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0].value !==
initDataPoint.value || initDataPoint.value ||
newData!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0].key !== newData!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0].key !==
@@ -477,7 +478,7 @@ export default function Dashboard() {
const overridesToBeAdded = newOverrides! const overridesToBeAdded = newOverrides!
.filter( .filter(
(newDataPoint) => (newDataPoint) =>
!initOverrides.map((initDataPoint) => initDataPoint.id).includes(newDataPoint.id) !initOverrides.map((initDataPoint) => initDataPoint.idOverride).includes(newDataPoint.idOverride)
) )
.map((override) => ({ .map((override) => ({
pos: override.pos, pos: override.pos,
@@ -496,18 +497,21 @@ export default function Dashboard() {
initOverrides initOverrides
.filter( .filter(
(initDataPoint) => (initDataPoint) =>
newOverrides!.map((dataPoint) => dataPoint.id).includes(initDataPoint.id) && newOverrides!.map((dataPoint) => dataPoint.idOverride)
(newOverrides!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0] .includes(initDataPoint.idOverride) &&
(newOverrides!.filter((dataPoint) => dataPoint.idOverride === initDataPoint.idOverride)[0]
.valueOverride !== initDataPoint.valueOverride || .valueOverride !== initDataPoint.valueOverride ||
newOverrides!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0].key !== newOverrides!.filter((dataPoint) => dataPoint.idOverride === initDataPoint.idOverride)[0].key !==
initDataPoint.key || initDataPoint.key ||
newOverrides!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0] (newOverrides!.filter((dataPoint) => dataPoint.idOverride === initDataPoint.idOverride)[0]
.comment !== initDataPoint.comment || .comment || '') !== (initDataPoint.comment || '')
JSON.stringify(newOverrides!.filter((dataPoint) => dataPoint.id === initDataPoint.id)[0]?.tags) !== ||
JSON.stringify(initDataPoint?.tags)) (JSON.stringify(newOverrides!.filter((dataPoint) => dataPoint.idOverride === initDataPoint.idOverride)[0]?.tags) || '') !==
(JSON.stringify(initDataPoint?.tags) || '')
)
) )
.map((secret) => secret.id) .map((secret) => secret.idOverride)
.includes(newDataPoint.id) .includes(newDataPoint.idOverride)
) )
.map((override) => ({ .map((override) => ({
pos: override.pos, pos: override.pos,
@@ -665,7 +669,7 @@ export default function Dashboard() {
idOverride: tempDecryptedSecrets.filter( idOverride: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'personal' (secret) => secret.key === key && secret.type === 'personal'
)[0]?.id, )[0]?.id,
pos: (newData?.filter(dp => !dp.id.includes('-'))?.length ?? 0) + index, pos: (newData?.filter(dp => !dp.id?.includes('-'))?.length ?? 0) + index,
key, key,
value: tempDecryptedSecrets.filter( value: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'shared' (secret) => secret.key === key && secret.type === 'shared'
@@ -681,8 +685,8 @@ export default function Dashboard() {
)[0]?.tags )[0]?.tags
})); }));
setInitialData(structuredClone(newData?.filter(dp => !dp.id.includes('-')).concat(formattedNewDecryptedKeys.filter(dk => dk.id)))); setInitialData(structuredClone(newData?.filter(dp => !dp.id?.includes('-')).concat(formattedNewDecryptedKeys.filter(dk => dk.id))));
setData(structuredClone(newData?.filter(dp => !dp.id.includes('-')).concat(formattedNewDecryptedKeys.filter(dk => dk.id)))) setData(structuredClone(newData?.filter(dp => !dp.id?.includes('-')).concat(formattedNewDecryptedKeys.filter(dk => dk.id))))
} else { } else {
setInitialData(structuredClone(newData)); setInitialData(structuredClone(newData));
} }
@@ -882,17 +886,24 @@ export default function Dashboard() {
comment: '', comment: '',
tags: sv.tags tags: sv.tags
})); }));
setData(rolledBackSecrets);
// Perform the rollback globally // Perform the rollback globally
performSecretRollback({ workspaceId, version: snapshotData.version }); const result = await performSecretRollback({ workspaceId, version: snapshotData.version });
if (result === undefined) {
setSnapshotData(undefined); createNotification({
createNotification({ text: `Something went wrong during the rollback.`,
text: `Rollback has been performed successfully.`, type: 'error'
type: 'success' });
}); } else {
setHasUnsavedChanges(false); setData(rolledBackSecrets);
createNotification({
text: `Successfully rolled back secrets.`,
type: 'success'
});
setSnapshotData(undefined);
setHasUnsavedChanges(false);
togglePITSidebar(false);
}
}} }}
color="primary" color="primary"
size="md" size="md"
@@ -975,7 +986,7 @@ export default function Dashboard() {
alt="infisical loading indicator" alt="infisical loading indicator"
/> />
</div> </div>
) : data?.length !== 0 ? ( ) : (data?.length !== 0 || snapshotData?.secretVersions) ? (
<div className="flex flex-col w-full mt-1"> <div className="flex flex-col w-full mt-1">
<div <div
onScroll={onSecretsAreaScroll} onScroll={onSecretsAreaScroll}
@@ -1038,7 +1049,7 @@ export default function Dashboard() {
|| row.tags?.map(tag => tag.name).join(" ")?.toUpperCase().includes(searchKeys.toUpperCase()) || row.tags?.map(tag => tag.name).join(" ")?.toUpperCase().includes(searchKeys.toUpperCase())
|| row.comment?.toUpperCase().includes(searchKeys.toUpperCase())) || row.comment?.toUpperCase().includes(searchKeys.toUpperCase()))
.filter((row) => !sharedToHide.includes(row.id)) .filter((row) => !sharedToHide.includes(row.id))
.filter((row) => row.value !== undefined) // .filter((row) => row.value !== undefined)
.map((keyPair) => ( .map((keyPair) => (
<KeyPair <KeyPair
isCapitalized={autoCapitalization} isCapitalized={autoCapitalization}
@@ -1066,22 +1077,6 @@ export default function Dashboard() {
?.sort((a, b) => a.key.localeCompare(b.key)) ?.sort((a, b) => a.key.localeCompare(b.key))
.filter((row) => row.environment === selectedSnapshotEnv?.slug) .filter((row) => row.environment === selectedSnapshotEnv?.slug)
.filter((row) => row.key.toUpperCase().includes(searchKeys.toUpperCase())) .filter((row) => row.key.toUpperCase().includes(searchKeys.toUpperCase()))
.filter(
(row) =>
!snapshotData.secretVersions
?.filter((secretVersion) =>
snapshotData.secretVersions
?.map((item) => item.key)
.filter(
(item, index) =>
index !==
snapshotData.secretVersions?.map((i) => i.key).indexOf(item)
)
.includes(secretVersion.key)
)
?.map((item) => item.id)
.includes(row.id)
)
.map((keyPair) => ( .map((keyPair) => (
<KeyPair <KeyPair
isCapitalized={autoCapitalization} isCapitalized={autoCapitalization}