mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: enhance cipher data handling by expanding CipherRow interface and updating database queries
This commit is contained in:
@@ -4,17 +4,59 @@ type SafeBind = (stmt: D1PreparedStatement, ...values: any[]) => D1PreparedState
|
|||||||
type SqlChunkSize = (fixedBindCount: number) => number;
|
type SqlChunkSize = (fixedBindCount: number) => number;
|
||||||
type UpdateRevisionDate = (userId: string) => Promise<string>;
|
type UpdateRevisionDate = (userId: string) => Promise<string>;
|
||||||
|
|
||||||
export async function getCipher(db: D1Database, id: string): Promise<Cipher | null> {
|
interface CipherRow {
|
||||||
const row = await db.prepare('SELECT data FROM ciphers WHERE id = ?').bind(id).first<{ data: string }>();
|
id: string;
|
||||||
|
user_id: string;
|
||||||
|
type: number | null;
|
||||||
|
folder_id: string | null;
|
||||||
|
name: string | null;
|
||||||
|
notes: string | null;
|
||||||
|
favorite: number | null;
|
||||||
|
data: string;
|
||||||
|
reprompt: number | null;
|
||||||
|
key: string | null;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
deleted_at: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCipherRow(row: CipherRow | null | undefined): Cipher | null {
|
||||||
if (!row?.data) return null;
|
if (!row?.data) return null;
|
||||||
try {
|
try {
|
||||||
return JSON.parse(row.data) as Cipher;
|
const parsed = JSON.parse(row.data) as Cipher;
|
||||||
|
return {
|
||||||
|
...parsed,
|
||||||
|
id: row.id,
|
||||||
|
userId: row.user_id,
|
||||||
|
type: Number(row.type) || Number(parsed.type) || 1,
|
||||||
|
folderId: row.folder_id ?? parsed.folderId ?? null,
|
||||||
|
name: row.name ?? parsed.name ?? null,
|
||||||
|
notes: row.notes ?? parsed.notes ?? null,
|
||||||
|
favorite: row.favorite != null ? !!row.favorite : !!parsed.favorite,
|
||||||
|
reprompt: row.reprompt ?? parsed.reprompt ?? 0,
|
||||||
|
key: row.key ?? parsed.key ?? null,
|
||||||
|
createdAt: row.created_at,
|
||||||
|
updatedAt: row.updated_at,
|
||||||
|
deletedAt: row.deleted_at ?? null,
|
||||||
|
};
|
||||||
} catch {
|
} catch {
|
||||||
console.error('Corrupted cipher data, id:', id);
|
console.error('Corrupted cipher data, id:', row.id);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectCipherColumns(): string {
|
||||||
|
return 'id, user_id, type, folder_id, name, notes, favorite, data, reprompt, key, created_at, updated_at, deleted_at';
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getCipher(db: D1Database, id: string): Promise<Cipher | null> {
|
||||||
|
const row = await db
|
||||||
|
.prepare(`SELECT ${selectCipherColumns()} FROM ciphers WHERE id = ?`)
|
||||||
|
.bind(id)
|
||||||
|
.first<CipherRow>();
|
||||||
|
return parseCipherRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
export async function saveCipher(db: D1Database, safeBind: SafeBind, cipher: Cipher): Promise<void> {
|
export async function saveCipher(db: D1Database, safeBind: SafeBind, cipher: Cipher): Promise<void> {
|
||||||
const data = JSON.stringify(cipher);
|
const data = JSON.stringify(cipher);
|
||||||
const stmt = db.prepare(
|
const stmt = db.prepare(
|
||||||
@@ -129,13 +171,13 @@ export async function bulkDeleteCiphers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getAllCiphers(db: D1Database, userId: string): Promise<Cipher[]> {
|
export async function getAllCiphers(db: D1Database, userId: string): Promise<Cipher[]> {
|
||||||
const res = await db.prepare('SELECT data FROM ciphers WHERE user_id = ? ORDER BY updated_at DESC').bind(userId).all<{ data: string }>();
|
const res = await db
|
||||||
return (res.results || []).flatMap((r) => {
|
.prepare(`SELECT ${selectCipherColumns()} FROM ciphers WHERE user_id = ? ORDER BY updated_at DESC`)
|
||||||
try {
|
.bind(userId)
|
||||||
return [JSON.parse(r.data) as Cipher];
|
.all<CipherRow>();
|
||||||
} catch {
|
return (res.results || []).flatMap((row) => {
|
||||||
return [];
|
const cipher = parseCipherRow(row);
|
||||||
}
|
return cipher ? [cipher] : [];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,20 +191,17 @@ export async function getCiphersPage(
|
|||||||
const whereDeleted = includeDeleted ? '' : 'AND deleted_at IS NULL';
|
const whereDeleted = includeDeleted ? '' : 'AND deleted_at IS NULL';
|
||||||
const res = await db
|
const res = await db
|
||||||
.prepare(
|
.prepare(
|
||||||
`SELECT data FROM ciphers
|
`SELECT ${selectCipherColumns()} FROM ciphers
|
||||||
WHERE user_id = ?
|
WHERE user_id = ?
|
||||||
${whereDeleted}
|
${whereDeleted}
|
||||||
ORDER BY updated_at DESC
|
ORDER BY updated_at DESC
|
||||||
LIMIT ? OFFSET ?`
|
LIMIT ? OFFSET ?`
|
||||||
)
|
)
|
||||||
.bind(userId, limit, offset)
|
.bind(userId, limit, offset)
|
||||||
.all<{ data: string }>();
|
.all<CipherRow>();
|
||||||
return (res.results || []).flatMap((r) => {
|
return (res.results || []).flatMap((row) => {
|
||||||
try {
|
const cipher = parseCipherRow(row);
|
||||||
return [JSON.parse(r.data) as Cipher];
|
return cipher ? [cipher] : [];
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,15 +220,12 @@ export async function getCiphersByIds(
|
|||||||
for (let i = 0; i < uniqueIds.length; i += chunkSize) {
|
for (let i = 0; i < uniqueIds.length; i += chunkSize) {
|
||||||
const chunk = uniqueIds.slice(i, i + chunkSize);
|
const chunk = uniqueIds.slice(i, i + chunkSize);
|
||||||
const placeholders = chunk.map(() => '?').join(',');
|
const placeholders = chunk.map(() => '?').join(',');
|
||||||
const stmt = db.prepare(`SELECT data FROM ciphers WHERE user_id = ? AND id IN (${placeholders})`);
|
const stmt = db.prepare(`SELECT ${selectCipherColumns()} FROM ciphers WHERE user_id = ? AND id IN (${placeholders})`);
|
||||||
const res = await stmt.bind(userId, ...chunk).all<{ data: string }>();
|
const res = await stmt.bind(userId, ...chunk).all<CipherRow>();
|
||||||
out.push(
|
out.push(
|
||||||
...(res.results || []).flatMap((r) => {
|
...(res.results || []).flatMap((row) => {
|
||||||
try {
|
const cipher = parseCipherRow(row);
|
||||||
return [JSON.parse(r.data) as Cipher];
|
return cipher ? [cipher] : [];
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user