mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
refactor: Remove unused APIs and data structures, optimize loading state component styles
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { hkdf } from '@/lib/crypto';
|
||||
import { t } from '@/lib/i18n';
|
||||
import type { Cipher, VaultDraft } from '@/lib/types';
|
||||
import type { VaultDraft } from '@/lib/types';
|
||||
import type { ImportResultSummary } from '@/components/ImportPage';
|
||||
|
||||
const SEND_KEY_SALT = 'bitwarden-send';
|
||||
@@ -26,7 +26,7 @@ export function looksLikeCipherString(value: string): boolean {
|
||||
return /^\d+\.[A-Za-z0-9+/=]+\|[A-Za-z0-9+/=]+(?:\|[A-Za-z0-9+/=]+)?$/.test(String(value || '').trim());
|
||||
}
|
||||
|
||||
export function asText(value: unknown): string {
|
||||
function asText(value: unknown): string {
|
||||
if (value === null || value === undefined) return '';
|
||||
return String(value);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ export function summarizeImportResult(
|
||||
};
|
||||
}
|
||||
|
||||
export function buildEmptyImportDraft(type: number): VaultDraft {
|
||||
function buildEmptyImportDraft(type: number): VaultDraft {
|
||||
return {
|
||||
type,
|
||||
favorite: false,
|
||||
@@ -279,6 +279,3 @@ export async function deriveSendKeyParts(sendKeyMaterial: Uint8Array): Promise<{
|
||||
return { enc: derived.slice(0, 32), mac: derived.slice(32, 64) };
|
||||
}
|
||||
|
||||
export function findCipherById(ciphers: Cipher[], id: string): Cipher | null {
|
||||
return ciphers.find((cipher) => cipher.id === id) || null;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { decryptStr, decryptBw } from './crypto';
|
||||
import type { Cipher } from './types';
|
||||
|
||||
function sameBytes(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.byteLength !== b.byteLength) return false;
|
||||
for (let i = 0; i < a.byteLength; i += 1) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function decryptField(
|
||||
value: string | null | undefined,
|
||||
enc: Uint8Array,
|
||||
|
||||
@@ -380,85 +380,6 @@ export async function buildPlainBitwardenJsonString(args: BuildPlainJsonArgs): P
|
||||
return JSON.stringify(doc, null, 2);
|
||||
}
|
||||
|
||||
export async function buildBitwardenCsvString(args: BuildPlainJsonArgs): Promise<string> {
|
||||
const doc = await buildPlainBitwardenJsonDocument(args);
|
||||
const folders = Array.isArray(doc.folders) ? (doc.folders as Array<Record<string, unknown>>) : [];
|
||||
const items = Array.isArray(doc.items) ? (doc.items as Array<Record<string, unknown>>) : [];
|
||||
|
||||
const folderNameById = new Map<string, string>();
|
||||
for (const folder of folders) {
|
||||
const id = normalizeString(folder.id);
|
||||
if (!id) continue;
|
||||
folderNameById.set(id, normalizeString(folder.name) || '');
|
||||
}
|
||||
|
||||
const header = [
|
||||
'folder',
|
||||
'favorite',
|
||||
'type',
|
||||
'name',
|
||||
'notes',
|
||||
'fields',
|
||||
'reprompt',
|
||||
'archivedDate',
|
||||
'login_uri',
|
||||
'login_username',
|
||||
'login_password',
|
||||
'login_totp',
|
||||
];
|
||||
|
||||
const rows: string[][] = [header];
|
||||
for (const item of items) {
|
||||
const type = normalizeNumber(item.type, 1);
|
||||
if (type !== 1 && type !== 2) continue;
|
||||
const folderId = normalizeString(item.folderId);
|
||||
const folderName = folderId ? folderNameById.get(folderId) || '' : '';
|
||||
const fields = Array.isArray(item.fields)
|
||||
? (item.fields as Array<Record<string, unknown>>)
|
||||
.map((field) => {
|
||||
const name = normalizeString(field.name) || '';
|
||||
const value = normalizeString(field.value) || '';
|
||||
if (!name && !value) return '';
|
||||
return `${name}: ${value}`;
|
||||
})
|
||||
.filter((line) => !!line)
|
||||
.join('\n')
|
||||
: '';
|
||||
|
||||
const login = isRecord(item.login) ? (item.login as Record<string, unknown>) : null;
|
||||
const loginUris = login && Array.isArray(login.uris)
|
||||
? (login.uris as Array<Record<string, unknown>>)
|
||||
.map((uri) => normalizeString(uri.uri) || '')
|
||||
.filter((uri) => !!uri)
|
||||
.join('\n')
|
||||
: '';
|
||||
|
||||
rows.push([
|
||||
folderName,
|
||||
item.favorite ? '1' : '',
|
||||
type === 1 ? 'login' : 'note',
|
||||
normalizeString(item.name) || '',
|
||||
normalizeString(item.notes) || '',
|
||||
fields,
|
||||
String(normalizeNumber(item.reprompt, 0)),
|
||||
normalizeString(item.archivedDate) || '',
|
||||
loginUris,
|
||||
normalizeString(login?.username) || '',
|
||||
normalizeString(login?.password) || '',
|
||||
normalizeString(login?.totp) || '',
|
||||
]);
|
||||
}
|
||||
|
||||
const escapeCsv = (value: string): string => {
|
||||
if (/[",\n\r]/.test(value)) {
|
||||
return `"${value.replace(/"/g, '""')}"`;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
return rows.map((row) => row.map((cell) => escapeCsv(String(cell || ''))).join(',')).join('\n');
|
||||
}
|
||||
|
||||
export async function buildAccountEncryptedBitwardenJsonString(args: BuildEncryptedJsonArgs): Promise<string> {
|
||||
const userEnc = base64ToBytes(args.userEncB64);
|
||||
const userMac = base64ToBytes(args.userMacB64);
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import { base64ToBytes, decryptBw, decryptStr, encryptBw } from './crypto';
|
||||
import { base64ToBytes, decryptBw, decryptStr } from './crypto';
|
||||
import { deriveSendKeyParts } from './app-support';
|
||||
import type { Cipher, Folder, Send } from './types';
|
||||
|
||||
export interface AttachmentRepairTask {
|
||||
cipherId: string;
|
||||
attachmentId: string;
|
||||
metadata: { fileName?: string; key?: string | null };
|
||||
}
|
||||
|
||||
export interface DecryptVaultCoreArgs {
|
||||
folders: Folder[];
|
||||
ciphers: Cipher[];
|
||||
@@ -18,7 +12,6 @@ export interface DecryptVaultCoreArgs {
|
||||
export interface DecryptVaultCoreResult {
|
||||
folders: Folder[];
|
||||
ciphers: Cipher[];
|
||||
attachmentRepairs: AttachmentRepairTask[];
|
||||
}
|
||||
|
||||
export interface DecryptSendsArgs {
|
||||
@@ -28,10 +21,6 @@ export interface DecryptSendsArgs {
|
||||
origin: string;
|
||||
}
|
||||
|
||||
function looksLikeCipherString(value: string): boolean {
|
||||
return /^\d+\.[A-Za-z0-9+/=]+\|[A-Za-z0-9+/=]+(?:\|[A-Za-z0-9+/=]+)?$/.test(String(value || '').trim());
|
||||
}
|
||||
|
||||
function sameBytes(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.byteLength !== b.byteLength) return false;
|
||||
for (let i = 0; i < a.byteLength; i += 1) {
|
||||
@@ -81,7 +70,6 @@ async function decryptFieldWithSource(
|
||||
export async function decryptVaultCore(args: DecryptVaultCoreArgs): Promise<DecryptVaultCoreResult> {
|
||||
const userEnc = base64ToBytes(args.symEncKeyB64);
|
||||
const userMac = base64ToBytes(args.symMacKeyB64);
|
||||
const attachmentRepairs: AttachmentRepairTask[] = [];
|
||||
|
||||
const folders = await Promise.all(
|
||||
args.folders.map(async (folder) => ({
|
||||
@@ -195,7 +183,6 @@ export async function decryptVaultCore(args: DecryptVaultCoreArgs): Promise<Decr
|
||||
if (Array.isArray(cipher.attachments)) {
|
||||
nextCipher.attachments = await Promise.all(
|
||||
cipher.attachments.map(async (attachment) => {
|
||||
const attachmentId = String(attachment?.id || '').trim();
|
||||
const fileNameResult = await decryptFieldWithSource(
|
||||
attachment.fileName || '',
|
||||
itemEnc,
|
||||
@@ -204,36 +191,6 @@ export async function decryptVaultCore(args: DecryptVaultCoreArgs): Promise<Decr
|
||||
userMac,
|
||||
!itemUsesUserKey
|
||||
);
|
||||
const metadata: { fileName?: string; key?: string | null } = {};
|
||||
|
||||
if (attachmentId && fileNameResult.source === 'user') {
|
||||
metadata.fileName = await encryptBw(new TextEncoder().encode(fileNameResult.text), itemEnc, itemMac);
|
||||
}
|
||||
|
||||
const attachmentKey = String(attachment?.key || '').trim();
|
||||
if (attachmentId && attachmentKey && looksLikeCipherString(attachmentKey) && !itemUsesUserKey) {
|
||||
try {
|
||||
await decryptBw(attachmentKey, itemEnc, itemMac);
|
||||
} catch {
|
||||
try {
|
||||
const rawAttachmentKey = await decryptBw(attachmentKey, userEnc, userMac);
|
||||
if (rawAttachmentKey.length >= 64) {
|
||||
metadata.key = await encryptBw(rawAttachmentKey, itemEnc, itemMac);
|
||||
}
|
||||
} catch {
|
||||
// Download path still supports legacy format.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attachmentId && Object.keys(metadata).length > 0) {
|
||||
attachmentRepairs.push({
|
||||
cipherId: cipher.id,
|
||||
attachmentId,
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...attachment,
|
||||
decFileName: fileNameResult.text,
|
||||
@@ -246,7 +203,7 @@ export async function decryptVaultCore(args: DecryptVaultCoreArgs): Promise<Decr
|
||||
})
|
||||
);
|
||||
|
||||
return { folders, ciphers, attachmentRepairs };
|
||||
return { folders, ciphers };
|
||||
}
|
||||
|
||||
export async function decryptSends(args: DecryptSendsArgs): Promise<Send[]> {
|
||||
|
||||
Reference in New Issue
Block a user