Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/components/hosts/HostsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ import { useAllFolders } from "@/hooks/useAllFolders";
import { SnippetPickerPanel } from "./SnippetPickerPanel";
import { getHostDeleteTargetIds, shouldUseBulkHostContextMenu } from "./hostSelection";
import { buildTeamVaultTransferPlan, type TransferOperation } from "@/services/teamVaultPermissions";
import { keepCachedOnUploadFailure } from "@/services/secretRouting";
import { reportUploadFailure } from "@/services/secretRouting";
import { moveKeyToVault, moveIdentityToVault } from "@/services/vaultObjectSecrets";
import { saveHostFromForm, type HostFormSecrets } from "@/services/hostForm";
import { descendantFolders, foldersOutsideSubtree, itemsInFolderSubtree, newFolderData, folderItemCounter } from "@/utils/folderTree";
Expand Down Expand Up @@ -649,15 +649,15 @@ export default function HostsPage() {
getSecret(`key:${key.id}:private`),
getSecret(`key:${key.id}:public`),
]);
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(keepCachedOnUploadFailure("HostsPage: copy key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(keepCachedOnUploadFailure("HostsPage: copy key to vault"));
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(reportUploadFailure("HostsPage: copy key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(reportUploadFailure("HostsPage: copy key to vault"));
newKeyId = newKey.id;
}

if (identityNeedsCopy) {
const newIdentity = await useIdentityStore.getState().saveIdentity(copyingRulesOf({ name: identity.name, username: identity.username, key_id: newKeyId, tags: identity.tags, vault_id: vaultId }, identity.id));
const pwd = await getSecret(`identity:${identity.id}:password`);
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(keepCachedOnUploadFailure("HostsPage: copy identity to vault"));
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(reportUploadFailure("HostsPage: copy identity to vault"));
newIdentityId = newIdentity.id;
}

Expand Down Expand Up @@ -772,10 +772,10 @@ export default function HostsPage() {
getSecret(`key:${key.id}:public`),
]);
if (priv) {
await storeSecret(`key:${newKey.id}:private`, priv).catch(keepCachedOnUploadFailure("HostsPage: copy folder key"));
await storeSecret(`key:${newKey.id}:private`, priv).catch(reportUploadFailure("HostsPage: copy folder key"));
}
if (pub) {
await storeSecret(`key:${newKey.id}:public`, pub).catch(keepCachedOnUploadFailure("HostsPage: copy folder key"));
await storeSecret(`key:${newKey.id}:public`, pub).catch(reportUploadFailure("HostsPage: copy folder key"));
}
keyIdMap.set(key.id, newKey.id);
}
Expand All @@ -787,7 +787,7 @@ export default function HostsPage() {
const newIdentity = await useIdentityStore.getState().saveIdentity(copyingRulesOf({ name: identity.name, username: identity.username, key_id: newKeyId, tags: identity.tags, vault_id: vaultId }, identity.id));
const pwd = await getSecret(`identity:${identity.id}:password`);
if (pwd) {
await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(keepCachedOnUploadFailure("HostsPage: copy folder identity"));
await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(reportUploadFailure("HostsPage: copy folder identity"));
}
identityIdMap.set(identity.id, newIdentity.id);
}
Expand Down
24 changes: 12 additions & 12 deletions src/components/keychain/KeychainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import type { Folder, Identity, IdentityFormData, SshKey, SshKeyFormData } from
import { SidePanelLayout } from "@/components/shared/SidePanelLayout";
import { useSyncedFormKey } from "@/hooks/useSyncedFormKey";
import { buildTeamVaultTransferPlan, type TransferOperation } from "@/services/teamVaultPermissions";
import { keepCachedOnUploadFailure } from "@/services/secretRouting";
import { reportUploadFailure } from "@/services/secretRouting";
import { moveKeyToVault, moveIdentityToVault } from "@/services/vaultObjectSecrets";
import { usePageClipboard } from "@/hooks/usePageClipboard";
import { vaultClipboardBase } from "@/utils/vaultClipboardBase";
Expand Down Expand Up @@ -558,9 +558,9 @@ export default function KeychainPage() {
getSecret(`key:${key.id}:public`),
getSecret(`key:${key.id}:passphrase`),
]);
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(keepCachedOnUploadFailure("KeychainPage: copy key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(keepCachedOnUploadFailure("KeychainPage: copy key to vault"));
if (pass) await storeSecret(`key:${newKey.id}:passphrase`, pass).catch(keepCachedOnUploadFailure("KeychainPage: copy key to vault"));
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(reportUploadFailure("KeychainPage: copy key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(reportUploadFailure("KeychainPage: copy key to vault"));
if (pass) await storeSecret(`key:${newKey.id}:passphrase`, pass).catch(reportUploadFailure("KeychainPage: copy key to vault"));
} catch (err) { setError(describeError(err, t)); }
};

Expand Down Expand Up @@ -608,14 +608,14 @@ export default function KeychainPage() {
getSecret(`key:${key.id}:private`),
getSecret(`key:${key.id}:public`),
]);
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(keepCachedOnUploadFailure("KeychainPage: copy identity's key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(keepCachedOnUploadFailure("KeychainPage: copy identity's key to vault"));
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(reportUploadFailure("KeychainPage: copy identity's key to vault"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(reportUploadFailure("KeychainPage: copy identity's key to vault"));
newKeyId = newKey.id;
}

const newIdentity = await saveIdentity(copyingRulesOf({ name: identity.name, username: identity.username, key_id: newKeyId, tags: identity.tags, vault_id: vaultId }, identity.id));
const pwd = await getSecret(`identity:${identity.id}:password`);
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(keepCachedOnUploadFailure("KeychainPage: copy identity to vault"));
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(reportUploadFailure("KeychainPage: copy identity to vault"));
} catch (err) { setError(describeError(err, t)); }
},
});
Expand Down Expand Up @@ -700,15 +700,15 @@ export default function KeychainPage() {
getSecret(`key:${key.id}:private`),
getSecret(`key:${key.id}:public`),
]);
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(keepCachedOnUploadFailure("KeychainPage: copy folder key"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(keepCachedOnUploadFailure("KeychainPage: copy folder key"));
if (priv) await storeSecret(`key:${newKey.id}:private`, priv).catch(reportUploadFailure("KeychainPage: copy folder key"));
if (pub) await storeSecret(`key:${newKey.id}:public`, pub).catch(reportUploadFailure("KeychainPage: copy folder key"));
keyIdMap.set(key.id, newKey.id);
}
for (const identity of treeIdentities) {
const newKeyId = identity.key_id ? (keyIdMap.get(identity.key_id) ?? identity.key_id) : undefined;
const newIdentity = await useIdentityStore.getState().saveIdentity(copyingRulesOf({ name: identity.name, username: identity.username, key_id: newKeyId, tags: identity.tags, vault_id: vaultId }, identity.id));
const pwd = await getSecret(`identity:${identity.id}:password`);
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(keepCachedOnUploadFailure("KeychainPage: copy folder identity"));
if (pwd) await storeSecret(`identity:${newIdentity.id}:password`, pwd).catch(reportUploadFailure("KeychainPage: copy folder identity"));
}
} catch (err) { setError(describeError(err, t)); }
},
Expand Down Expand Up @@ -741,7 +741,7 @@ export default function KeychainPage() {
const value = await getSecret(`key:${key.id}:${part}`);
if (!value) continue;
const localKey = `key:${newKey.id}:${part}`;
await storeSecret(localKey, value).catch(keepCachedOnUploadFailure("duplicateKeyInto"));
await storeSecret(localKey, value).catch(reportUploadFailure("duplicateKeyInto"));
}
return newKey;
}
Expand All @@ -765,7 +765,7 @@ export default function KeychainPage() {
const pwd = await getSecret(`identity:${identity.id}:password`);
if (pwd) {
const localKey = `identity:${newIdentity.id}:password`;
await storeSecret(localKey, pwd).catch(keepCachedOnUploadFailure("duplicateIdentityInto"));
await storeSecret(localKey, pwd).catch(reportUploadFailure("duplicateIdentityInto"));
}
return newIdentity;
}
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/cs/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "Přesunuto, ale přihlašovací údaje se zatím nepodařilo nahrát. Zůstávají na tomto zařízení a pokus o nahrání se zopakuje při příštím načtení trezoru: {{error}}",
"failedToSaveTeamSecret": "Týmové tajemství se nepodařilo uložit: {{status}}",
"serverLacksTeamSecretType": "Tento server Voltius je příliš starý na to, aby toto uložil do týmového trezoru. Požádejte jeho správce o aktualizaci serveru a pak uložte znovu.",
"teamSecretRefused": "Týmový trezor tuto hodnotu nepřijal, takže nebyla uložena: {{error}}",
"teamSecretUploadPending": "Zatím nenahráno do týmového trezoru. Hodnota zůstane uložena do zavření aplikace Voltius a pokus o nahrání se zopakuje při příštím načtení trezoru: {{error}}",
"failedToLoadServerCapabilities": "Nepodařilo se ověřit, co server podporuje ({{status}})",
"keyFetchFailed": "Načtení klíče se nezdařilo: {{error}}",
"failedToUploadVaultKeys": "Klíče trezoru se nepodařilo nahrát: {{status}}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "Moved, but its credentials could not be uploaded yet. They stay on this device and are retried the next time the vault loads: {{error}}",
"failedToSaveTeamSecret": "Failed to save team secret: {{status}}",
"serverLacksTeamSecretType": "This Voltius server is too old to store this in a team vault. Ask its administrator to update the server, then save again.",
"teamSecretRefused": "The team vault did not accept this, so it was not saved: {{error}}",
"teamSecretUploadPending": "Not uploaded to the team vault yet. It is kept until Voltius closes and retried the next time the vault loads: {{error}}",
"failedToLoadServerCapabilities": "Couldn't check what the server supports ({{status}})",
"keyFetchFailed": "Key fetch failed: {{error}}",
"failedToUploadVaultKeys": "Failed to upload vault keys: {{status}}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "Déplacé, mais ses identifiants n'ont pas encore pu être envoyés. Ils restent sur cet appareil et seront renvoyés au prochain chargement du coffre : {{error}}",
"failedToSaveTeamSecret": "Échec de l'enregistrement du secret d'équipe : {{status}}",
"serverLacksTeamSecretType": "Ce serveur Voltius est trop ancien pour stocker cet élément dans un coffre d'équipe. Demandez à son administrateur de mettre le serveur à jour, puis enregistrez à nouveau.",
"teamSecretRefused": "Le coffre d'équipe n'a pas accepté cet élément, il n'a donc pas été enregistré : {{error}}",
"teamSecretUploadPending": "Pas encore envoyé au coffre d'équipe. L'élément est conservé jusqu'à la fermeture de Voltius et renvoyé au prochain chargement du coffre : {{error}}",
"failedToLoadServerCapabilities": "Impossible de vérifier ce que le serveur prend en charge ({{status}})",
"keyFetchFailed": "Échec de la récupération de la clé : {{error}}",
"failedToUploadVaultKeys": "Échec de l'envoi des clés de coffre : {{status}}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/ru/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "Перемещено, но учётные данные пока не удалось отправить. Они остаются на этом устройстве и будут отправлены повторно при следующей загрузке хранилища: {{error}}",
"failedToSaveTeamSecret": "Не удалось сохранить секрет команды: {{status}}",
"serverLacksTeamSecretType": "Этот сервер Voltius слишком старый, чтобы хранить это в командном хранилище. Попросите администратора обновить сервер, затем сохраните снова.",
"teamSecretRefused": "Командное хранилище не приняло это значение, поэтому оно не сохранено: {{error}}",
"teamSecretUploadPending": "Пока не отправлено в командное хранилище. Значение хранится до закрытия Voltius и будет отправлено повторно при следующей загрузке хранилища: {{error}}",
"failedToLoadServerCapabilities": "Не удалось проверить, что поддерживает сервер ({{status}})",
"keyFetchFailed": "Не удалось получить ключ: {{error}}",
"failedToUploadVaultKeys": "Не удалось загрузить ключи хранилища: {{status}}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/tr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "Taşındı, ancak kimlik bilgileri henüz yüklenemedi. Bu cihazda kalıyor ve kasa bir sonraki yüklendiğinde yeniden denenecek: {{error}}",
"failedToSaveTeamSecret": "Ekibin gizli bilgisi kaydedilemedi: {{status}}",
"serverLacksTeamSecretType": "Bu Voltius sunucusu, bunu bir ekip kasasında saklamak için çok eski. Yöneticisinden sunucuyu güncellemesini isteyin, ardından yeniden kaydedin.",
"teamSecretRefused": "Ekip kasası bunu kabul etmedi, bu yüzden kaydedilmedi: {{error}}",
"teamSecretUploadPending": "Henüz ekip kasasına yüklenmedi. Voltius kapanana kadar saklanıyor ve kasa bir sonraki yüklendiğinde yeniden denenecek: {{error}}",
"failedToLoadServerCapabilities": "Sunucunun neleri desteklediği denetlenemedi ({{status}})",
"keyFetchFailed": "Anahtar alınamadı: {{error}}",
"failedToUploadVaultKeys": "Kasa anahtarları yüklenemedi: {{status}}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"secretsUploadPending": "已移动,但其凭据暂时无法上传。它们会保留在此设备上,并在下次加载保险库时重试:{{error}}",
"failedToSaveTeamSecret": "保存团队密钥失败:{{status}}",
"serverLacksTeamSecretType": "此 Voltius 服务器版本过旧,无法在团队保险库中存储此内容。请让管理员更新服务器,然后重新保存。",
"teamSecretRefused": "团队保险库未接受此内容,因此未保存:{{error}}",
"teamSecretUploadPending": "尚未上传到团队保险库。它会保留到 Voltius 关闭为止,并在下次加载保险库时重试:{{error}}",
"failedToLoadServerCapabilities": "无法检查服务器支持的功能({{status}})",
"keyFetchFailed": "获取密钥失败:{{error}}",
"failedToUploadVaultKeys": "上传保险库密钥失败:{{status}}",
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/domains/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { moveFolderTreeToVault } from "@/utils/folderMove";
import { snippetToForm } from "@/utils/snippetForm";
import { ruleToForm } from "@/utils/portForwardingForm";
import { getSecret, storeSecret } from "@/services/vault";
import { keepCachedOnUploadFailure } from "@/services/secretRouting";
import { reportUploadFailure } from "@/services/secretRouting";
import { moveKeyToVault, moveIdentityToVault } from "@/services/vaultObjectSecrets";
import { duplicateConnection, moveConnectionToVault } from "@/services/connectionDuplicate";
import { copyingRulesOf } from "@/services/ruleSetIntent";
Expand Down Expand Up @@ -203,7 +203,7 @@ function resolveTab(

const copySecret = async (from: string, to: string): Promise<void> => {
const value = await getSecret(from).catch(() => null);
if (value) await storeSecret(to, value).catch(keepCachedOnUploadFailure("copySecret"));
if (value) await storeSecret(to, value).catch(reportUploadFailure("copySecret"));
};

interface DuplicateOpts {
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { addKeyToHost } from "@/services/keyExport";
import { isValidSshPublicKey } from "@/services/sshPublicKey";
import type { Connection, TerminalSession } from "@/types";
import { storePluginSecret, getPluginSecret, deletePluginSecret, storeSecret, deleteLocalSecret } from "@/services/vault";
import { keepCachedOnUploadFailure } from "@/services/secretRouting";
import { reportUploadFailure } from "@/services/secretRouting";
import { appFetch } from "@/services/http";
import { sseFetch } from "@/services/sseFetch";
import { registerLxcExecSession } from "@/services/proxmox";
Expand Down Expand Up @@ -1019,8 +1019,8 @@ function createPluginAPI(manifest: PluginManifest): PluginAPI {
throw new Error("publicKey is not a valid SSH public key");
}
const key = await keyService.saveKey({ name: data.name, key_type: data.key_type, tags: data.tags ?? [] });
await storeSecret(`key:${key.id}:private`, privateKey).catch(keepCachedOnUploadFailure("plugin: keys.create"));
if (publicKey) await storeSecret(`key:${key.id}:public`, publicKey).catch(keepCachedOnUploadFailure("plugin: keys.create"));
await storeSecret(`key:${key.id}:private`, privateKey).catch(reportUploadFailure("plugin: keys.create"));
if (publicKey) await storeSecret(`key:${key.id}:public`, publicKey).catch(reportUploadFailure("plugin: keys.create"));
return key as PluginKey;
},
async delete(keyId) {
Expand Down
Loading
Loading