Ability to sync environments to folder (#207)

This commit is contained in:
Gregory Schier
2025-05-08 14:10:07 -07:00
committed by GitHub
parent 77cdea2f9f
commit 94d4227bc1
54 changed files with 710 additions and 425 deletions

View File

@@ -29,15 +29,41 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
const workspace = useAtomValue(activeWorkspaceAtom);
const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom);
const [key, setKey] = useState<{ key: string | null; error: string | null } | null>(null);
if (workspace == null || workspaceMeta == null) {
useEffect(() => {
if (workspaceMeta == null) {
return;
}
if (workspaceMeta?.encryptionKey == null) {
setKey({ key: null, error: null });
return;
}
revealWorkspaceKey(workspaceMeta.workspaceId).then(
(key) => {
setKey({ key, error: null });
},
(err) => {
setKey({ key: null, error: `${err}` });
},
);
}, [setKey, workspaceMeta, workspaceMeta?.encryptionKey]);
if (key == null || workspace == null || workspaceMeta == null) {
return null;
}
if (workspace.encryptionKeyChallenge && workspaceMeta.encryptionKey == null) {
// Prompt for key if it doesn't exist or could not be decrypted
if (
key.error != null ||
(workspace.encryptionKeyChallenge && workspaceMeta.encryptionKey == null)
) {
return (
<EnterWorkspaceKey
workspaceMeta={workspaceMeta}
error={key.error}
onEnabled={() => {
onDone?.();
onEnabledEncryption?.();
@@ -46,12 +72,13 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
);
}
if (workspaceMeta.encryptionKey) {
// Show the key if it exists
if (workspaceMeta.encryptionKey && key.key != null) {
const keyRevealer = (
<KeyRevealer
disableLabel={justEnabledEncryption}
defaultShow={justEnabledEncryption}
workspaceId={workspaceMeta.workspaceId}
encryptionKey={key.key}
/>
);
return (
@@ -63,10 +90,13 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
)}
{keyRevealer}
{onDone && (
<Button color="secondary" onClick={() => {
<Button
color="secondary"
onClick={() => {
onDone();
onEnabledEncryption?.();
}}>
}}
>
Done
</Button>
)}
@@ -74,6 +104,7 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
);
}
// Show button to enable encryption
return (
<div className="mb-auto flex flex-col-reverse">
<Button
@@ -107,17 +138,23 @@ const setWorkspaceKeyMut = createFastMutation({
function EnterWorkspaceKey({
workspaceMeta,
onEnabled,
error,
}: {
workspaceMeta: WorkspaceMeta;
onEnabled?: () => void;
error?: string | null;
}) {
const [key, setKey] = useState<string>('');
return (
<VStack space={4}>
<Banner color="info">
This workspace contains encrypted values but no key is configured. Please enter the
workspace key to access the encrypted data.
</Banner>
<VStack space={4} className="w-full">
{error ? (
<Banner color="danger">{error}</Banner>
) : (
<Banner color="info">
This workspace contains encrypted values but no key is configured. Please enter the
workspace key to access the encrypted data.
</Banner>
)}
<HStack
as="form"
alignItems="end"
@@ -149,23 +186,16 @@ function EnterWorkspaceKey({
}
function KeyRevealer({
workspaceId,
defaultShow = false,
disableLabel = false,
encryptionKey,
}: {
workspaceId: string;
defaultShow?: boolean;
disableLabel?: boolean;
encryptionKey: string;
}) {
const [key, setKey] = useState<string | null>(null);
const [show, setShow] = useStateWithDeps<boolean>(defaultShow, [defaultShow]);
useEffect(() => {
revealWorkspaceKey(workspaceId).then(setKey);
}, [setKey, workspaceId]);
if (key == null) return null;
return (
<div
className={classNames(
@@ -180,10 +210,10 @@ function KeyRevealer({
<IconTooltip iconSize="sm" size="lg" content={helpAfterEncryption} />
</span>
)}
{key && <HighlightedKey keyText={key} show={show} />}
{encryptionKey && <HighlightedKey keyText={encryptionKey} show={show} />}
</VStack>
<HStack>
{key && <CopyIconButton text={key} title="Copy workspace key" />}
{encryptionKey && <CopyIconButton text={encryptionKey} title="Copy workspace key" />}
<IconButton
title={show ? 'Hide' : 'Reveal' + 'workspace key'}
icon={show ? 'eye_closed' : 'eye'}