mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: add export and import functionality for Bitwarden and NodeWarden formats
- Implemented export formats for Bitwarden (JSON, encrypted JSON, ZIP) and NodeWarden (JSON). - Added support for attachments in ciphers and introduced new types for handling attachments. - Enhanced import formats to include Bitwarden ZIP and NodeWarden JSON. - Updated internationalization strings for attachment-related features. - Improved UI styles for attachment management and import summary display.
This commit is contained in:
+15
-1
@@ -1,6 +1,6 @@
|
||||
import { Env, Cipher, Folder, CipherType } from '../types';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { errorResponse } from '../utils/response';
|
||||
import { errorResponse, jsonResponse } from '../utils/response';
|
||||
import { generateUUID } from '../utils/uuid';
|
||||
import { LIMITS } from '../config/limits';
|
||||
import { normalizeCipherLoginForCompatibility } from './ciphers';
|
||||
@@ -8,6 +8,7 @@ import { normalizeCipherLoginForCompatibility } from './ciphers';
|
||||
// Bitwarden client import request format
|
||||
interface CiphersImportRequest {
|
||||
ciphers: Array<{
|
||||
id?: string | null;
|
||||
type: number;
|
||||
name?: string | null;
|
||||
notes?: string | null;
|
||||
@@ -90,6 +91,8 @@ async function runBatchInChunks(db: D1Database, statements: D1PreparedStatement[
|
||||
// POST /api/ciphers/import - Bitwarden client import endpoint
|
||||
export async function handleCiphersImport(request: Request, env: Env, userId: string): Promise<Response> {
|
||||
const storage = new StorageService(env.DB);
|
||||
const url = new URL(request.url);
|
||||
const returnCipherMap = url.searchParams.get('returnCipherMap') === '1';
|
||||
|
||||
let importData: CiphersImportRequest;
|
||||
try {
|
||||
@@ -151,9 +154,12 @@ export async function handleCiphersImport(request: Request, env: Env, userId: st
|
||||
|
||||
// Create ciphers
|
||||
const cipherRows: Cipher[] = [];
|
||||
const cipherMapRows: Array<{ index: number; sourceId: string | null; id: string }> = [];
|
||||
for (let i = 0; i < ciphers.length; i++) {
|
||||
const c = ciphers[i];
|
||||
const folderId = cipherFolderMap.get(i) || null;
|
||||
const sourceIdRaw = String(c?.id ?? '').trim();
|
||||
const sourceId = sourceIdRaw || null;
|
||||
|
||||
const cipher: Cipher = {
|
||||
...c,
|
||||
@@ -229,6 +235,7 @@ export async function handleCiphersImport(request: Request, env: Env, userId: st
|
||||
cipher.login = normalizeCipherLoginForCompatibility(cipher.login);
|
||||
|
||||
cipherRows.push(cipher);
|
||||
cipherMapRows.push({ index: i, sourceId, id: cipher.id });
|
||||
}
|
||||
|
||||
if (cipherRows.length > 0) {
|
||||
@@ -263,5 +270,12 @@ export async function handleCiphersImport(request: Request, env: Env, userId: st
|
||||
// Update revision date
|
||||
await storage.updateRevisionDate(userId);
|
||||
|
||||
if (returnCipherMap) {
|
||||
return jsonResponse({
|
||||
object: 'import-result',
|
||||
cipherMap: cipherMapRows,
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(null, { status: 200 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user