mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-04-03 22:44:49 -04:00
Refactor to separate SQL queries from repository files (#1695)
This commit is contained in:
92
apps/browser-extension/src/utils/db/queries/FolderQueries.ts
Normal file
92
apps/browser-extension/src/utils/db/queries/FolderQueries.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* SQL query constants for Folder operations.
|
||||
* Centralizes all folder-related queries to avoid duplication.
|
||||
*/
|
||||
export class FolderQueries {
|
||||
/**
|
||||
* Get all active folders.
|
||||
*/
|
||||
public static readonly GET_ALL = `
|
||||
SELECT Id, Name, ParentFolderId, Weight
|
||||
FROM Folders
|
||||
WHERE IsDeleted = 0
|
||||
ORDER BY Weight, Name`;
|
||||
|
||||
/**
|
||||
* Get folder by ID.
|
||||
*/
|
||||
public static readonly GET_BY_ID = `
|
||||
SELECT Id, Name, ParentFolderId
|
||||
FROM Folders
|
||||
WHERE Id = ? AND IsDeleted = 0`;
|
||||
|
||||
/**
|
||||
* Insert a new folder.
|
||||
*/
|
||||
public static readonly INSERT = `
|
||||
INSERT INTO Folders (Id, Name, ParentFolderId, Weight, IsDeleted, CreatedAt, UpdatedAt)
|
||||
VALUES (?, ?, ?, 0, 0, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Update folder name.
|
||||
*/
|
||||
public static readonly UPDATE_NAME = `
|
||||
UPDATE Folders
|
||||
SET Name = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
|
||||
/**
|
||||
* Soft delete folder.
|
||||
*/
|
||||
public static readonly SOFT_DELETE = `
|
||||
UPDATE Folders
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
|
||||
/**
|
||||
* Clear folder reference from items.
|
||||
*/
|
||||
public static readonly CLEAR_ITEMS_FOLDER = `
|
||||
UPDATE Items
|
||||
SET FolderId = NULL,
|
||||
UpdatedAt = ?
|
||||
WHERE FolderId = ?`;
|
||||
|
||||
/**
|
||||
* Trash items in folder.
|
||||
*/
|
||||
public static readonly TRASH_ITEMS_IN_FOLDER = `
|
||||
UPDATE Items
|
||||
SET DeletedAt = ?,
|
||||
UpdatedAt = ?,
|
||||
FolderId = NULL
|
||||
WHERE FolderId = ? AND IsDeleted = 0 AND DeletedAt IS NULL`;
|
||||
|
||||
/**
|
||||
* Get all child folder IDs (direct children only).
|
||||
*/
|
||||
public static readonly GET_CHILD_FOLDER_IDS = `
|
||||
SELECT Id
|
||||
FROM Folders
|
||||
WHERE ParentFolderId = ? AND IsDeleted = 0`;
|
||||
|
||||
/**
|
||||
* Update parent folder for child folders.
|
||||
*/
|
||||
public static readonly UPDATE_PARENT_FOLDER = `
|
||||
UPDATE Folders
|
||||
SET ParentFolderId = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE ParentFolderId = ?`;
|
||||
|
||||
/**
|
||||
* Move item to folder.
|
||||
*/
|
||||
public static readonly MOVE_ITEM = `
|
||||
UPDATE Items
|
||||
SET FolderId = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
}
|
||||
@@ -265,6 +265,14 @@ export class ItemQueries {
|
||||
AND fv.IsDeleted = 0
|
||||
AND i.IsDeleted = 0
|
||||
AND i.DeletedAt IS NULL`;
|
||||
|
||||
/**
|
||||
* Get item-level fields for change detection during updates.
|
||||
*/
|
||||
public static readonly GET_ITEM_FIELDS = `
|
||||
SELECT Name, ItemType, FolderId, LogoId
|
||||
FROM Items
|
||||
WHERE Id = ?`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,3 +416,63 @@ export class FieldHistoryQueries {
|
||||
SET IsDeleted = 1, UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL query constants for TotpCode operations.
|
||||
*/
|
||||
export class TotpCodeQueries {
|
||||
/**
|
||||
* Get existing TOTP codes for an item.
|
||||
*/
|
||||
public static readonly GET_BY_ITEM_ID = `
|
||||
SELECT Id, Name, SecretKey
|
||||
FROM TotpCodes
|
||||
WHERE ItemId = ? AND IsDeleted = 0`;
|
||||
|
||||
/**
|
||||
* Insert a new TOTP code.
|
||||
*/
|
||||
public static readonly INSERT = `
|
||||
INSERT INTO TotpCodes (Id, Name, SecretKey, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Update an existing TOTP code.
|
||||
*/
|
||||
public static readonly UPDATE = `
|
||||
UPDATE TotpCodes
|
||||
SET Name = ?,
|
||||
SecretKey = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
|
||||
/**
|
||||
* Soft delete a TOTP code.
|
||||
*/
|
||||
public static readonly SOFT_DELETE = `
|
||||
UPDATE TotpCodes
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL query constants for Attachment operations.
|
||||
*/
|
||||
export class AttachmentQueries {
|
||||
/**
|
||||
* Insert a new attachment.
|
||||
*/
|
||||
public static readonly INSERT = `
|
||||
INSERT INTO Attachments (Id, Filename, Blob, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Soft delete an attachment.
|
||||
*/
|
||||
public static readonly SOFT_DELETE = `
|
||||
UPDATE Attachments
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
}
|
||||
|
||||
33
apps/browser-extension/src/utils/db/queries/LogoQueries.ts
Normal file
33
apps/browser-extension/src/utils/db/queries/LogoQueries.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* SQL query constants for Logo operations.
|
||||
* Centralizes all logo-related queries to avoid duplication.
|
||||
*/
|
||||
export class LogoQueries {
|
||||
/**
|
||||
* Check if logo exists for source.
|
||||
*/
|
||||
public static readonly GET_ID_FOR_SOURCE = `
|
||||
SELECT Id FROM Logos
|
||||
WHERE Source = ? AND IsDeleted = 0
|
||||
LIMIT 1`;
|
||||
|
||||
/**
|
||||
* Insert new logo.
|
||||
*/
|
||||
public static readonly INSERT = `
|
||||
INSERT INTO Logos (Id, Source, FileData, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Count items using a logo.
|
||||
*/
|
||||
public static readonly COUNT_USAGE = `
|
||||
SELECT COUNT(*) as count FROM Items
|
||||
WHERE LogoId = ? AND IsDeleted = 0`;
|
||||
|
||||
/**
|
||||
* Hard delete logo.
|
||||
*/
|
||||
public static readonly HARD_DELETE = `
|
||||
DELETE FROM Logos WHERE Id = ?`;
|
||||
}
|
||||
155
apps/browser-extension/src/utils/db/queries/PasskeyQueries.ts
Normal file
155
apps/browser-extension/src/utils/db/queries/PasskeyQueries.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import { FieldKey } from '@/utils/dist/core/models/vault';
|
||||
|
||||
/**
|
||||
* SQL query constants for Passkey operations.
|
||||
* Centralizes all passkey-related queries to avoid duplication.
|
||||
*/
|
||||
export class PasskeyQueries {
|
||||
/**
|
||||
* Base SELECT for passkeys with item information.
|
||||
*/
|
||||
public static readonly BASE_SELECT_WITH_ITEM = `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id`;
|
||||
|
||||
/**
|
||||
* Base SELECT for passkeys without item information.
|
||||
*/
|
||||
public static readonly BASE_SELECT = `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted
|
||||
FROM Passkeys p`;
|
||||
|
||||
/**
|
||||
* Get passkeys by relying party ID.
|
||||
*/
|
||||
public static readonly GET_BY_RP_ID = `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id
|
||||
WHERE p.RpId = ? AND p.IsDeleted = 0
|
||||
AND i.IsDeleted = 0 AND i.DeletedAt IS NULL
|
||||
ORDER BY p.CreatedAt DESC`;
|
||||
|
||||
/**
|
||||
* Get passkey by ID with item information.
|
||||
*/
|
||||
public static readonly GET_BY_ID_WITH_ITEM = `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id
|
||||
WHERE p.Id = ? AND p.IsDeleted = 0
|
||||
AND i.IsDeleted = 0 AND i.DeletedAt IS NULL`;
|
||||
|
||||
/**
|
||||
* Get passkeys by item ID.
|
||||
*/
|
||||
public static readonly GET_BY_ITEM_ID = `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted
|
||||
FROM Passkeys p
|
||||
WHERE p.ItemId = ? AND p.IsDeleted = 0
|
||||
ORDER BY p.CreatedAt DESC`;
|
||||
|
||||
/**
|
||||
* Insert a new passkey.
|
||||
*/
|
||||
public static readonly INSERT = `
|
||||
INSERT INTO Passkeys (
|
||||
Id, ItemId, RpId, UserHandle, PublicKey, PrivateKey,
|
||||
PrfKey, DisplayName, AdditionalData, CreatedAt, UpdatedAt, IsDeleted
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Update passkey display name.
|
||||
*/
|
||||
public static readonly UPDATE_DISPLAY_NAME = `
|
||||
UPDATE Passkeys
|
||||
SET DisplayName = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
|
||||
/**
|
||||
* Soft delete passkey by ID.
|
||||
*/
|
||||
public static readonly SOFT_DELETE = `
|
||||
UPDATE Passkeys
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`;
|
||||
|
||||
/**
|
||||
* Soft delete passkeys by item ID.
|
||||
*/
|
||||
public static readonly SOFT_DELETE_BY_ITEM = `
|
||||
UPDATE Passkeys
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE ItemId = ?`;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* SQL query constants for Settings operations.
|
||||
* Centralizes all settings-related queries to avoid duplication.
|
||||
*/
|
||||
export class SettingsQueries {
|
||||
/**
|
||||
* Get setting by key.
|
||||
*/
|
||||
public static readonly GET_SETTING = `
|
||||
SELECT s.Value
|
||||
FROM Settings s
|
||||
WHERE s.Key = ?`;
|
||||
|
||||
/**
|
||||
* Check if a setting exists.
|
||||
*/
|
||||
public static readonly COUNT_BY_KEY = `
|
||||
SELECT COUNT(*) as count
|
||||
FROM Settings
|
||||
WHERE Key = ?`;
|
||||
|
||||
/**
|
||||
* Update an existing setting.
|
||||
*/
|
||||
public static readonly UPDATE_SETTING = `
|
||||
UPDATE Settings
|
||||
SET Value = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Key = ?`;
|
||||
|
||||
/**
|
||||
* Insert a new setting.
|
||||
*/
|
||||
public static readonly INSERT_SETTING = `
|
||||
INSERT INTO Settings (Key, Value, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?)`;
|
||||
|
||||
/**
|
||||
* Get all encryption keys.
|
||||
*/
|
||||
public static readonly GET_ENCRYPTION_KEYS = `
|
||||
SELECT
|
||||
x.PublicKey,
|
||||
x.PrivateKey,
|
||||
x.IsPrimary
|
||||
FROM EncryptionKeys x`;
|
||||
|
||||
/**
|
||||
* Get TOTP codes for an item.
|
||||
*/
|
||||
public static readonly GET_TOTP_FOR_ITEM = `
|
||||
SELECT
|
||||
Id,
|
||||
Name,
|
||||
SecretKey,
|
||||
ItemId
|
||||
FROM TotpCodes
|
||||
WHERE ItemId = ? AND IsDeleted = 0`;
|
||||
|
||||
/**
|
||||
* Get attachments for an item.
|
||||
*/
|
||||
public static readonly GET_ATTACHMENTS_FOR_ITEM = `
|
||||
SELECT
|
||||
Id,
|
||||
Filename,
|
||||
Blob,
|
||||
ItemId,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
IsDeleted
|
||||
FROM Attachments
|
||||
WHERE ItemId = ? AND IsDeleted = 0`;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BaseRepository } from '../BaseRepository';
|
||||
import { FolderQueries } from '../queries/FolderQueries';
|
||||
|
||||
/**
|
||||
* Folder entity type.
|
||||
@@ -10,98 +11,6 @@ export type Folder = {
|
||||
Weight: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL query constants for Folder operations.
|
||||
*/
|
||||
const FolderQueries = {
|
||||
/**
|
||||
* Get all active folders.
|
||||
*/
|
||||
GET_ALL: `
|
||||
SELECT Id, Name, ParentFolderId, Weight
|
||||
FROM Folders
|
||||
WHERE IsDeleted = 0
|
||||
ORDER BY Weight, Name`,
|
||||
|
||||
/**
|
||||
* Get folder by ID.
|
||||
*/
|
||||
GET_BY_ID: `
|
||||
SELECT Id, Name, ParentFolderId
|
||||
FROM Folders
|
||||
WHERE Id = ? AND IsDeleted = 0`,
|
||||
|
||||
/**
|
||||
* Insert a new folder.
|
||||
*/
|
||||
INSERT: `
|
||||
INSERT INTO Folders (Id, Name, ParentFolderId, Weight, IsDeleted, CreatedAt, UpdatedAt)
|
||||
VALUES (?, ?, ?, 0, 0, ?, ?)`,
|
||||
|
||||
/**
|
||||
* Update folder name.
|
||||
*/
|
||||
UPDATE_NAME: `
|
||||
UPDATE Folders
|
||||
SET Name = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`,
|
||||
|
||||
/**
|
||||
* Soft delete folder.
|
||||
*/
|
||||
SOFT_DELETE: `
|
||||
UPDATE Folders
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`,
|
||||
|
||||
/**
|
||||
* Clear folder reference from items.
|
||||
*/
|
||||
CLEAR_ITEMS_FOLDER: `
|
||||
UPDATE Items
|
||||
SET FolderId = NULL,
|
||||
UpdatedAt = ?
|
||||
WHERE FolderId = ?`,
|
||||
|
||||
/**
|
||||
* Trash items in folder.
|
||||
*/
|
||||
TRASH_ITEMS_IN_FOLDER: `
|
||||
UPDATE Items
|
||||
SET DeletedAt = ?,
|
||||
UpdatedAt = ?,
|
||||
FolderId = NULL
|
||||
WHERE FolderId = ? AND IsDeleted = 0 AND DeletedAt IS NULL`,
|
||||
|
||||
/**
|
||||
* Get all child folder IDs (direct children only).
|
||||
*/
|
||||
GET_CHILD_FOLDER_IDS: `
|
||||
SELECT Id
|
||||
FROM Folders
|
||||
WHERE ParentFolderId = ? AND IsDeleted = 0`,
|
||||
|
||||
/**
|
||||
* Update parent folder for child folders.
|
||||
*/
|
||||
UPDATE_PARENT_FOLDER: `
|
||||
UPDATE Folders
|
||||
SET ParentFolderId = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE ParentFolderId = ?`,
|
||||
|
||||
/**
|
||||
* Move item to folder.
|
||||
*/
|
||||
MOVE_ITEM: `
|
||||
UPDATE Items
|
||||
SET FolderId = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`
|
||||
};
|
||||
|
||||
/**
|
||||
* Repository for Folder CRUD operations.
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,9 @@ import {
|
||||
ItemQueries,
|
||||
FieldValueQueries,
|
||||
FieldDefinitionQueries,
|
||||
FieldHistoryQueries
|
||||
FieldHistoryQueries,
|
||||
TotpCodeQueries,
|
||||
AttachmentQueries
|
||||
} from '../queries/ItemQueries';
|
||||
|
||||
import type { LogoRepository } from './LogoRepository';
|
||||
@@ -183,7 +185,7 @@ export class ItemRepository extends BaseRepository {
|
||||
ItemType: number;
|
||||
FolderId: string | null;
|
||||
LogoId: string | null;
|
||||
}>(`SELECT Name, ItemType, FolderId, LogoId FROM Items WHERE Id = ?`, [item.Id])[0];
|
||||
}>(ItemQueries.GET_ITEM_FIELDS, [item.Id])[0];
|
||||
|
||||
if (existing) {
|
||||
const nameChanged = (item.Name ?? null) !== existing.Name;
|
||||
@@ -754,8 +756,7 @@ export class ItemRepository extends BaseRepository {
|
||||
private insertTotpCodes(itemId: string, totpCodes: TotpCode[], currentDateTime: string): void {
|
||||
for (const totpCode of totpCodes) {
|
||||
this.client.executeUpdate(
|
||||
`INSERT INTO TotpCodes (Id, Name, SecretKey, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
TotpCodeQueries.INSERT,
|
||||
[
|
||||
totpCode.Id || this.generateId(),
|
||||
totpCode.Name,
|
||||
@@ -783,7 +784,7 @@ export class ItemRepository extends BaseRepository {
|
||||
Id: string;
|
||||
Name: string;
|
||||
SecretKey: string;
|
||||
}>(`SELECT Id, Name, SecretKey FROM TotpCodes WHERE ItemId = ? AND IsDeleted = 0`, [itemId]);
|
||||
}>(TotpCodeQueries.GET_BY_ITEM_ID, [itemId]);
|
||||
|
||||
const existingByIdMap = new Map(existingTotpCodes.map(tc => [tc.Id, tc]));
|
||||
|
||||
@@ -793,7 +794,7 @@ export class ItemRepository extends BaseRepository {
|
||||
if (totpCode.IsDeleted) {
|
||||
if (wasOriginal) {
|
||||
this.client.executeUpdate(
|
||||
`UPDATE TotpCodes SET IsDeleted = 1, UpdatedAt = ? WHERE Id = ?`,
|
||||
TotpCodeQueries.SOFT_DELETE,
|
||||
[currentDateTime, totpCode.Id]
|
||||
);
|
||||
}
|
||||
@@ -802,14 +803,13 @@ export class ItemRepository extends BaseRepository {
|
||||
const existing = existingByIdMap.get(totpCode.Id);
|
||||
if (existing && (existing.Name !== totpCode.Name || existing.SecretKey !== totpCode.SecretKey)) {
|
||||
this.client.executeUpdate(
|
||||
`UPDATE TotpCodes SET Name = ?, SecretKey = ?, UpdatedAt = ? WHERE Id = ?`,
|
||||
TotpCodeQueries.UPDATE,
|
||||
[totpCode.Name, totpCode.SecretKey, currentDateTime, totpCode.Id]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.client.executeUpdate(
|
||||
`INSERT INTO TotpCodes (Id, Name, SecretKey, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
TotpCodeQueries.INSERT,
|
||||
[
|
||||
totpCode.Id || this.generateId(),
|
||||
totpCode.Name,
|
||||
@@ -834,8 +834,7 @@ export class ItemRepository extends BaseRepository {
|
||||
: new Uint8Array(attachment.Blob);
|
||||
|
||||
this.client.executeUpdate(
|
||||
`INSERT INTO Attachments (Id, Filename, Blob, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
AttachmentQueries.INSERT,
|
||||
[
|
||||
attachment.Id || this.generateId(),
|
||||
attachment.Filename,
|
||||
@@ -865,7 +864,7 @@ export class ItemRepository extends BaseRepository {
|
||||
for (const originalId of originalIds) {
|
||||
if (!currentAttachmentIds.has(originalId)) {
|
||||
this.client.executeUpdate(
|
||||
`UPDATE Attachments SET IsDeleted = 1, UpdatedAt = ? WHERE Id = ?`,
|
||||
AttachmentQueries.SOFT_DELETE,
|
||||
[currentDateTime, originalId]
|
||||
);
|
||||
}
|
||||
@@ -878,7 +877,7 @@ export class ItemRepository extends BaseRepository {
|
||||
if (attachment.IsDeleted) {
|
||||
if (wasOriginal) {
|
||||
this.client.executeUpdate(
|
||||
`UPDATE Attachments SET IsDeleted = 1, UpdatedAt = ? WHERE Id = ?`,
|
||||
AttachmentQueries.SOFT_DELETE,
|
||||
[currentDateTime, attachment.Id]
|
||||
);
|
||||
}
|
||||
@@ -888,8 +887,7 @@ export class ItemRepository extends BaseRepository {
|
||||
: new Uint8Array(attachment.Blob);
|
||||
|
||||
this.client.executeUpdate(
|
||||
`INSERT INTO Attachments (Id, Filename, Blob, ItemId, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
AttachmentQueries.INSERT,
|
||||
[
|
||||
attachment.Id || this.generateId(),
|
||||
attachment.Filename,
|
||||
|
||||
@@ -1,37 +1,5 @@
|
||||
import { BaseRepository } from '../BaseRepository';
|
||||
|
||||
/**
|
||||
* SQL query constants for Logo operations.
|
||||
*/
|
||||
const LogoQueries = {
|
||||
/**
|
||||
* Check if logo exists for source.
|
||||
*/
|
||||
GET_ID_FOR_SOURCE: `
|
||||
SELECT Id FROM Logos
|
||||
WHERE Source = ? AND IsDeleted = 0
|
||||
LIMIT 1`,
|
||||
|
||||
/**
|
||||
* Insert new logo.
|
||||
*/
|
||||
INSERT: `
|
||||
INSERT INTO Logos (Id, Source, FileData, CreatedAt, UpdatedAt, IsDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
|
||||
/**
|
||||
* Count items using a logo.
|
||||
*/
|
||||
COUNT_USAGE: `
|
||||
SELECT COUNT(*) as count FROM Items
|
||||
WHERE LogoId = ? AND IsDeleted = 0`,
|
||||
|
||||
/**
|
||||
* Hard delete logo.
|
||||
*/
|
||||
HARD_DELETE: `
|
||||
DELETE FROM Logos WHERE Id = ?`
|
||||
};
|
||||
import { LogoQueries } from '../queries/LogoQueries';
|
||||
|
||||
/**
|
||||
* Repository for Logo management operations.
|
||||
|
||||
@@ -1,161 +1,8 @@
|
||||
import type { Passkey } from '@/utils/dist/core/models/vault';
|
||||
import { FieldKey } from '@/utils/dist/core/models/vault';
|
||||
|
||||
import { BaseRepository } from '../BaseRepository';
|
||||
import { PasskeyMapper, type PasskeyRow, type PasskeyWithItemRow, type PasskeyWithItem } from '../mappers/PasskeyMapper';
|
||||
|
||||
/**
|
||||
* SQL query constants for Passkey operations.
|
||||
*/
|
||||
const PasskeyQueries = {
|
||||
/**
|
||||
* Base SELECT for passkeys with item information.
|
||||
*/
|
||||
BASE_SELECT_WITH_ITEM: `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id`,
|
||||
|
||||
/**
|
||||
* Base SELECT for passkeys without item information.
|
||||
*/
|
||||
BASE_SELECT: `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted
|
||||
FROM Passkeys p`,
|
||||
|
||||
/**
|
||||
* Get passkeys by relying party ID.
|
||||
*/
|
||||
GET_BY_RP_ID: `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id
|
||||
WHERE p.RpId = ? AND p.IsDeleted = 0
|
||||
AND i.IsDeleted = 0 AND i.DeletedAt IS NULL
|
||||
ORDER BY p.CreatedAt DESC`,
|
||||
|
||||
/**
|
||||
* Get passkey by ID with item information.
|
||||
*/
|
||||
GET_BY_ID_WITH_ITEM: `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted,
|
||||
i.Name as ServiceName,
|
||||
(SELECT fv.Value FROM FieldValues fv WHERE fv.ItemId = i.Id AND fv.FieldKey = '${FieldKey.LoginUsername}' AND fv.IsDeleted = 0 LIMIT 1) as Username
|
||||
FROM Passkeys p
|
||||
INNER JOIN Items i ON p.ItemId = i.Id
|
||||
WHERE p.Id = ? AND p.IsDeleted = 0
|
||||
AND i.IsDeleted = 0 AND i.DeletedAt IS NULL`,
|
||||
|
||||
/**
|
||||
* Get passkeys by item ID.
|
||||
*/
|
||||
GET_BY_ITEM_ID: `
|
||||
SELECT
|
||||
p.Id,
|
||||
p.ItemId,
|
||||
p.RpId,
|
||||
p.UserHandle,
|
||||
p.PublicKey,
|
||||
p.PrivateKey,
|
||||
p.DisplayName,
|
||||
p.PrfKey,
|
||||
p.AdditionalData,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.IsDeleted
|
||||
FROM Passkeys p
|
||||
WHERE p.ItemId = ? AND p.IsDeleted = 0
|
||||
ORDER BY p.CreatedAt DESC`,
|
||||
|
||||
/**
|
||||
* Insert a new passkey.
|
||||
*/
|
||||
INSERT: `
|
||||
INSERT INTO Passkeys (
|
||||
Id, ItemId, RpId, UserHandle, PublicKey, PrivateKey,
|
||||
PrfKey, DisplayName, AdditionalData, CreatedAt, UpdatedAt, IsDeleted
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
|
||||
/**
|
||||
* Update passkey display name.
|
||||
*/
|
||||
UPDATE_DISPLAY_NAME: `
|
||||
UPDATE Passkeys
|
||||
SET DisplayName = ?,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`,
|
||||
|
||||
/**
|
||||
* Soft delete passkey by ID.
|
||||
*/
|
||||
SOFT_DELETE: `
|
||||
UPDATE Passkeys
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE Id = ?`,
|
||||
|
||||
/**
|
||||
* Soft delete passkeys by item ID.
|
||||
*/
|
||||
SOFT_DELETE_BY_ITEM: `
|
||||
UPDATE Passkeys
|
||||
SET IsDeleted = 1,
|
||||
UpdatedAt = ?
|
||||
WHERE ItemId = ?`
|
||||
};
|
||||
import { PasskeyQueries } from '../queries/PasskeyQueries';
|
||||
|
||||
/**
|
||||
* Repository for Passkey CRUD operations.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { EncryptionKey, PasswordSettings, TotpCode, Attachment } from '@/utils/dist/core/models/vault';
|
||||
|
||||
import { BaseRepository } from '../BaseRepository';
|
||||
import { SettingsQueries } from '../queries/SettingsQueries';
|
||||
|
||||
/**
|
||||
* Sort order options for credentials list.
|
||||
@@ -8,56 +9,6 @@ import { BaseRepository } from '../BaseRepository';
|
||||
*/
|
||||
export type CredentialSortOrder = 'OldestFirst' | 'NewestFirst' | 'Alphabetical';
|
||||
|
||||
/**
|
||||
* SQL query constants for Settings and related operations.
|
||||
*/
|
||||
const SettingsQueries = {
|
||||
/**
|
||||
* Get setting by key.
|
||||
*/
|
||||
GET_SETTING: `
|
||||
SELECT s.Value
|
||||
FROM Settings s
|
||||
WHERE s.Key = ?`,
|
||||
|
||||
/**
|
||||
* Get all encryption keys.
|
||||
*/
|
||||
GET_ENCRYPTION_KEYS: `
|
||||
SELECT
|
||||
x.PublicKey,
|
||||
x.PrivateKey,
|
||||
x.IsPrimary
|
||||
FROM EncryptionKeys x`,
|
||||
|
||||
/**
|
||||
* Get TOTP codes for an item.
|
||||
*/
|
||||
GET_TOTP_FOR_ITEM: `
|
||||
SELECT
|
||||
Id,
|
||||
Name,
|
||||
SecretKey,
|
||||
ItemId
|
||||
FROM TotpCodes
|
||||
WHERE ItemId = ? AND IsDeleted = 0`,
|
||||
|
||||
/**
|
||||
* Get attachments for an item.
|
||||
*/
|
||||
GET_ATTACHMENTS_FOR_ITEM: `
|
||||
SELECT
|
||||
Id,
|
||||
Filename,
|
||||
Blob,
|
||||
ItemId,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
IsDeleted
|
||||
FROM Attachments
|
||||
WHERE ItemId = ? AND IsDeleted = 0`
|
||||
};
|
||||
|
||||
/**
|
||||
* Repository for Settings and auxiliary data operations.
|
||||
*/
|
||||
@@ -220,19 +171,19 @@ export class SettingsRepository extends BaseRepository {
|
||||
|
||||
// Check if setting exists
|
||||
const results = this.client.executeQuery<{ count: number }>(
|
||||
`SELECT COUNT(*) as count FROM Settings WHERE Key = ?`,
|
||||
SettingsQueries.COUNT_BY_KEY,
|
||||
[key]
|
||||
);
|
||||
const exists = results[0]?.count > 0;
|
||||
|
||||
if (exists) {
|
||||
this.client.executeUpdate(
|
||||
`UPDATE Settings SET Value = ?, UpdatedAt = ? WHERE Key = ?`,
|
||||
SettingsQueries.UPDATE_SETTING,
|
||||
[value, now, key]
|
||||
);
|
||||
} else {
|
||||
this.client.executeUpdate(
|
||||
`INSERT INTO Settings (Key, Value, CreatedAt, UpdatedAt, IsDeleted) VALUES (?, ?, ?, ?, ?)`,
|
||||
SettingsQueries.INSERT_SETTING,
|
||||
[key, value, now, now, 0]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user