mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-19 15:18:02 -04:00
Refactor storeEncryptedDatabase method to separate metadata set (#771)
This commit is contained in:
@@ -49,11 +49,9 @@ export const DbProvider: React.FC<{ children: React.ReactNode }> = ({ children }
|
||||
vaultRevisionNumber: vaultResponse.vault.currentRevisionNumber,
|
||||
};
|
||||
|
||||
// Initialize the SQLite client with both database and metadata
|
||||
await sqliteClient.storeEncryptedDatabase(
|
||||
vaultResponse.vault.blob,
|
||||
metadata
|
||||
);
|
||||
// Store the encrypted database and metadata (metadata is stored in plain text in UserDefaults)
|
||||
await sqliteClient.storeEncryptedDatabase(vaultResponse.vault.blob);
|
||||
await sqliteClient.storeMetadata(JSON.stringify(metadata));
|
||||
|
||||
// Initialize the database in the native module
|
||||
await unlockVault();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 70;
|
||||
objectVersion = 60;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -208,7 +208,7 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
CEE9098F2DA548C7008D568F /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
|
||||
CEE9098F2DA548C7008D568F /* Exceptions for "Autofill" folder in "Autofill" target */ = {
|
||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||
membershipExceptions = (
|
||||
Info.plist,
|
||||
@@ -218,11 +218,62 @@
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
CEE480882DBE86DC00F4A367 /* VaultStoreKit */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = VaultStoreKit; sourceTree = "<group>"; };
|
||||
CEE480972DBE86DD00F4A367 /* VaultStoreKitTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = VaultStoreKitTests; sourceTree = "<group>"; };
|
||||
CEE4816B2DBE8AC800F4A367 /* VaultUI */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = VaultUI; sourceTree = "<group>"; };
|
||||
CEE482AB2DBE8EFE00F4A367 /* VaultModels */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = VaultModels; sourceTree = "<group>"; };
|
||||
CEE909812DA548C7008D568F /* Autofill */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (CEE9098F2DA548C7008D568F /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Autofill; sourceTree = "<group>"; };
|
||||
CEE480882DBE86DC00F4A367 /* VaultStoreKit */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
explicitFileTypes = {
|
||||
};
|
||||
explicitFolders = (
|
||||
);
|
||||
path = VaultStoreKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CEE480972DBE86DD00F4A367 /* VaultStoreKitTests */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
explicitFileTypes = {
|
||||
};
|
||||
explicitFolders = (
|
||||
);
|
||||
path = VaultStoreKitTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CEE4816B2DBE8AC800F4A367 /* VaultUI */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
explicitFileTypes = {
|
||||
};
|
||||
explicitFolders = (
|
||||
);
|
||||
path = VaultUI;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CEE482AB2DBE8EFE00F4A367 /* VaultModels */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
explicitFileTypes = {
|
||||
};
|
||||
explicitFolders = (
|
||||
);
|
||||
path = VaultModels;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CEE909812DA548C7008D568F /* Autofill */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
CEE9098F2DA548C7008D568F /* Exceptions for "Autofill" folder in "Autofill" target */,
|
||||
);
|
||||
explicitFileTypes = {
|
||||
};
|
||||
explicitFolders = (
|
||||
);
|
||||
path = Autofill;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -1204,7 +1255,10 @@
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "$(inherited) ";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||
@@ -1259,7 +1313,10 @@
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = "$(inherited) ";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
USE_HERMES = true;
|
||||
|
||||
@@ -12,10 +12,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTNativeVaultManager : NSObject <NativeVaultManagerSpec>
|
||||
|
||||
- (void)getEncryptedDatabase:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
||||
- (void)getCurrentVaultRevisionNumber:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
||||
- (void)setCurrentVaultRevisionNumber:(double)revisionNumber resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -96,8 +96,12 @@
|
||||
[vaultManager setAutoLockTimeout:timeout resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
- (void)storeDatabase:(NSString *)base64EncryptedDb metadata:(NSString *)metadata resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
[vaultManager storeDatabase:base64EncryptedDb metadata:metadata resolver:resolve rejecter:reject];
|
||||
- (void)storeDatabase:(NSString *)base64EncryptedDb resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
[vaultManager storeDatabase:base64EncryptedDb resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
- (void)storeMetadata:(NSString *)metadata resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
[vaultManager storeMetadata:metadata resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
- (void)storeEncryptionKey:(NSString *)base64EncryptionKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
|
||||
@@ -19,17 +19,28 @@ public class VaultManager: NSObject {
|
||||
|
||||
@objc
|
||||
func storeDatabase(_ base64EncryptedDb: String,
|
||||
metadata: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
do {
|
||||
try vaultStore.storeEncryptedDatabase(base64EncryptedDb, metadata: metadata)
|
||||
try vaultStore.storeEncryptedDatabase(base64EncryptedDb)
|
||||
resolve(nil)
|
||||
} catch {
|
||||
reject("DB_ERROR", "Failed to store database: \(error.localizedDescription)", error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func storeMetadata(_ metadata: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
do {
|
||||
try vaultStore.storeMetadata(metadata)
|
||||
resolve(nil)
|
||||
} catch {
|
||||
reject("METADATA_ERROR", "Failed to store metadata: \(error.localizedDescription)", error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func setAuthMethods(_ authMethods: [String],
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
|
||||
@@ -237,14 +237,15 @@ public class VaultStore {
|
||||
}
|
||||
|
||||
// Store the encrypted database (base64 encoded) in the app's documents directory
|
||||
// and metadata in UserDefaults
|
||||
// TODO: refactor metadata save and retrieve calls to separate calls for better clarity throughout
|
||||
// full call chain?
|
||||
public func storeEncryptedDatabase(_ base64EncryptedDb: String, metadata: String) throws {
|
||||
// Store the encrypted database (base64 encoded) in the app's documents directory
|
||||
public func storeEncryptedDatabase(_ base64EncryptedDb: String) throws {
|
||||
try base64EncryptedDb.write(to: getEncryptedDbPath(), atomically: true, encoding: .utf8)
|
||||
}
|
||||
|
||||
// Store metadata in UserDefaults
|
||||
// Store metadata in UserDefaults
|
||||
// Metadata is stored in plain text in UserDefaults. The metadata consists of the following:
|
||||
// - public and private email domains
|
||||
// - vault revision number
|
||||
public func storeMetadata(_ metadata: String) throws {
|
||||
userDefaults.set(metadata, forKey: vaultMetadataKey)
|
||||
userDefaults.synchronize()
|
||||
}
|
||||
@@ -742,7 +743,8 @@ public class VaultStore {
|
||||
let encryptedBase64String = encryptedBase64Data.base64EncodedString()
|
||||
|
||||
// Persist the encrypted base64 string.
|
||||
try storeEncryptedDatabase(encryptedBase64String, metadata: getVaultMetadata()!)
|
||||
try storeEncryptedDatabase(encryptedBase64String)
|
||||
try storeMetadata(getVaultMetadata()!)
|
||||
|
||||
// Cleanup
|
||||
try FileManager.default.removeItem(at: tempDbPath)
|
||||
|
||||
@@ -29,8 +29,19 @@ final class VaultStoreKitTests: XCTestCase {
|
||||
|
||||
// Load and store the encrypted database
|
||||
let encryptedDb = try loadTestDatabase()
|
||||
// TODO: get metadata via vault generation and pass it here so we have all info we need for all tests.
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb, metadata: "")
|
||||
|
||||
// Store the database
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb)
|
||||
|
||||
// Store metadata with example domains
|
||||
let metadata = """
|
||||
{
|
||||
"publicEmailDomains": ["spamok.com", "spamok.nl"],
|
||||
"privateEmailDomains": ["aliasvault.net", "main.aliasvault.net"],
|
||||
"vaultRevisionNumber": 1
|
||||
}
|
||||
"""
|
||||
try vaultStore.storeMetadata(metadata)
|
||||
|
||||
// Unlock the vault (which loads, decrypts and opens the database in memory)
|
||||
try vaultStore.unlockVault()
|
||||
@@ -45,8 +56,17 @@ final class VaultStoreKitTests: XCTestCase {
|
||||
|
||||
// Load and store the encrypted database
|
||||
let encryptedDb = try loadTestDatabase()
|
||||
// TODO: get metadata via vault generation and pass it here so we have all info we need for all tests.
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb, metadata: "")
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb)
|
||||
|
||||
// Store metadata with example domains
|
||||
let metadata = """
|
||||
{
|
||||
"publicEmailDomains": ["spamok.com", "spamok.nl"],
|
||||
"privateEmailDomains": ["aliasvault.net", "main.aliasvault.net"],
|
||||
"vaultRevisionNumber": 1
|
||||
}
|
||||
"""
|
||||
try vaultStore.storeMetadata(metadata)
|
||||
|
||||
// Unlock the vault (which loads, decrypts and opens the database in memory)
|
||||
try vaultStore.unlockVault()
|
||||
@@ -75,7 +95,17 @@ final class VaultStoreKitTests: XCTestCase {
|
||||
|
||||
// Load and store the encrypted database
|
||||
let encryptedDb = try loadTestDatabase()
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb, metadata: "")
|
||||
try vaultStore.storeEncryptedDatabase(encryptedDb)
|
||||
|
||||
// Store metadata with example domains
|
||||
let metadata = """
|
||||
{
|
||||
"publicEmailDomains": ["spamok.com", "spamok.nl"],
|
||||
"privateEmailDomains": ["aliasvault.net", "main.aliasvault.net"],
|
||||
"vaultRevisionNumber": 1
|
||||
}
|
||||
"""
|
||||
try vaultStore.storeMetadata(metadata)
|
||||
|
||||
// Unlock the vault (which loads, decrypts and opens the database in memory)
|
||||
try vaultStore.unlockVault()
|
||||
|
||||
@@ -13,7 +13,8 @@ export interface Spec extends TurboModule {
|
||||
unlockVault(): Promise<boolean>;
|
||||
|
||||
// Database operations
|
||||
storeDatabase(base64EncryptedDb: string, metadata: string): Promise<void>;
|
||||
storeDatabase(base64EncryptedDb: string): Promise<void>;
|
||||
storeMetadata(metadata: string): Promise<void>;
|
||||
setAuthMethods(authMethods: string[]): Promise<void>;
|
||||
storeEncryptionKey(base64EncryptionKey: string): Promise<void>;
|
||||
getEncryptedDatabase(): Promise<string | null>;
|
||||
|
||||
@@ -16,16 +16,31 @@ class SqliteClient {
|
||||
/**
|
||||
* Store the encrypted database via the native code implementation.
|
||||
*/
|
||||
async storeEncryptedDatabase(base64EncryptedDb: string, metadata: VaultMetadata): Promise<void> {
|
||||
async storeEncryptedDatabase(base64EncryptedDb: string): Promise<void> {
|
||||
try {
|
||||
const metadataJson = JSON.stringify(metadata);
|
||||
await NativeVaultManager.storeDatabase(base64EncryptedDb, metadataJson);
|
||||
await NativeVaultManager.storeDatabase(base64EncryptedDb);
|
||||
} catch (error) {
|
||||
console.error('Error initializing SQLite database:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the vault metadata via the native code implementation.
|
||||
*
|
||||
* Metadata is stored in plain text in UserDefaults. The metadata consists of the following:
|
||||
* - public and private email domains
|
||||
* - vault revision number
|
||||
*/
|
||||
async storeMetadata(metadata: string): Promise<void> {
|
||||
try {
|
||||
await NativeVaultManager.storeMetadata(metadata);
|
||||
} catch (error) {
|
||||
console.error('Error storing vault metadata:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the vault metadata from native storage
|
||||
* @returns The parsed VaultMetadata object
|
||||
|
||||
Reference in New Issue
Block a user