Add option to disable encryption when key is forgotten (#371)

This commit is contained in:
Gregory Schier
2026-01-26 15:40:02 -08:00
committed by GitHub
parent 4e15ac10a6
commit 8969748c3c
5 changed files with 87 additions and 1 deletions

View File

@@ -100,6 +100,15 @@ pub(crate) async fn cmd_set_workspace_key<R: Runtime>(
Ok(())
}
#[command]
pub(crate) async fn cmd_disable_encryption<R: Runtime>(
window: WebviewWindow<R>,
workspace_id: &str,
) -> Result<()> {
window.crypto().disable_encryption(workspace_id)?;
Ok(())
}
#[command]
pub(crate) fn cmd_default_headers() -> Vec<HttpRequestHeader> {
default_headers()

View File

@@ -1722,6 +1722,7 @@ pub fn run() {
// Migrated commands
crate::commands::cmd_decrypt_template,
crate::commands::cmd_default_headers,
crate::commands::cmd_disable_encryption,
crate::commands::cmd_enable_encryption,
crate::commands::cmd_get_themes,
crate::commands::cmd_reveal_workspace_key,

View File

@@ -11,3 +11,7 @@ export function revealWorkspaceKey(workspaceId: string) {
export function setWorkspaceKey(args: { workspaceId: string; key: string }) {
return invoke<void>('cmd_set_workspace_key', args);
}
export function disableEncryption(workspaceId: string) {
return invoke<void>('cmd_disable_encryption', { workspaceId });
}

View File

@@ -115,6 +115,35 @@ impl EncryptionManager {
self.set_workspace_key(workspace_id, &wkey)
}
pub fn disable_encryption(&self, workspace_id: &str) -> Result<()> {
info!("Disabling encryption for {workspace_id}");
self.query_manager.with_tx::<(), Error>(|tx| {
let workspace = tx.get_workspace(workspace_id)?;
let workspace_meta = tx.get_or_create_workspace_meta(workspace_id)?;
// Clear encryption challenge on workspace
tx.upsert_workspace(
&Workspace { encryption_key_challenge: None, ..workspace },
&UpdateSource::Background,
)?;
// Clear encryption key on workspace meta
tx.upsert_workspace_meta(
&WorkspaceMeta { encryption_key: None, ..workspace_meta },
&UpdateSource::Background,
)?;
Ok(())
})?;
// Remove from cache
let mut cache = self.cached_workspace_keys.lock().unwrap();
cache.remove(workspace_id);
Ok(())
}
fn get_workspace_key(&self, workspace_id: &str) -> Result<WorkspaceKey> {
{
let cache = self.cached_workspace_keys.lock().unwrap();

View File

@@ -1,4 +1,9 @@
import { enableEncryption, revealWorkspaceKey, setWorkspaceKey } from '@yaakapp-internal/crypto';
import {
disableEncryption,
enableEncryption,
revealWorkspaceKey,
setWorkspaceKey,
} from '@yaakapp-internal/crypto';
import type { WorkspaceMeta } from '@yaakapp-internal/models';
import classNames from 'classnames';
import { useAtomValue } from 'jotai';
@@ -6,6 +11,7 @@ import { useEffect, useState } from 'react';
import { activeWorkspaceAtom, activeWorkspaceMetaAtom } from '../hooks/useActiveWorkspace';
import { createFastMutation } from '../hooks/useFastMutation';
import { useStateWithDeps } from '../hooks/useStateWithDeps';
import { showConfirm } from '../lib/confirm';
import { CopyIconButton } from './CopyIconButton';
import { Banner } from './core/Banner';
import type { ButtonProps } from './core/Button';
@@ -69,6 +75,9 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
onDone?.();
onEnabledEncryption?.();
}}
onDisabled={() => {
onDone?.();
}}
/>
);
}
@@ -109,6 +118,7 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
return (
<div className="mb-auto flex flex-col-reverse">
<Button
className="mt-3"
color={expanded ? 'info' : 'secondary'}
size={size}
onClick={async () => {
@@ -149,13 +159,39 @@ const setWorkspaceKeyMut = createFastMutation({
function EnterWorkspaceKey({
workspaceMeta,
onEnabled,
onDisabled,
error,
}: {
workspaceMeta: WorkspaceMeta;
onEnabled?: () => void;
onDisabled?: () => void;
error?: string | null;
}) {
const [key, setKey] = useState<string>('');
const handleForgotKey = async () => {
const confirmed = await showConfirm({
id: 'disable-encryption',
title: 'Disable Encryption',
color: 'danger',
confirmText: 'Disable Encryption',
description: (
<>
This will disable encryption for this workspace. Any previously encrypted values will fail
to decrypt and will need to be re-entered manually.
<br />
<br />
This action cannot be undone.
</>
),
});
if (confirmed) {
await disableEncryption(workspaceMeta.workspaceId);
onDisabled?.();
}
};
return (
<VStack space={4} className="w-full">
{error ? (
@@ -192,6 +228,13 @@ function EnterWorkspaceKey({
Submit
</Button>
</HStack>
<button
type="button"
onClick={handleForgotKey}
className="text-text-subtlest text-sm hover:text-text-subtle"
>
Forgot your key?
</button>
</VStack>
);
}