From eda0fb4d4ef13a30e5c67b6fc99ab30d42131d44 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 11 Apr 2025 16:41:15 +0200 Subject: [PATCH] Make sqlite work (#771) --- mobile-app/app/(tabs)/_layout.tsx | 19 +++++++-- mobile-app/utils/SqliteClient.tsx | 67 ++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/mobile-app/app/(tabs)/_layout.tsx b/mobile-app/app/(tabs)/_layout.tsx index cfbc1e236..f43f0fdeb 100644 --- a/mobile-app/app/(tabs)/_layout.tsx +++ b/mobile-app/app/(tabs)/_layout.tsx @@ -7,9 +7,15 @@ import { IconSymbol } from '@/components/ui/IconSymbol'; import TabBarBackground from '@/components/ui/TabBarBackground'; import { Colors } from '@/constants/Colors'; import { useColorScheme } from '@/hooks/useColorScheme'; +import { useAuth } from '@/context/AuthContext'; export default function TabLayout() { const colorScheme = useColorScheme(); + const { isLoggedIn, isInitialized } = useAuth(); + + if (!isInitialized) { + return null; + } return ( , }} /> + , + }} + /> ); } diff --git a/mobile-app/utils/SqliteClient.tsx b/mobile-app/utils/SqliteClient.tsx index f98b82cae..a07304a46 100644 --- a/mobile-app/utils/SqliteClient.tsx +++ b/mobile-app/utils/SqliteClient.tsx @@ -1,4 +1,5 @@ import * as SQLite from 'expo-sqlite'; +import * as FileSystem from 'expo-file-system'; import { Credential } from './types/Credential'; import { EncryptionKey } from './types/EncryptionKey'; import { TotpCode } from './types/TotpCode'; @@ -30,25 +31,51 @@ class SqliteClient { */ public async initializeFromBase64(base64String: string): Promise { try { - // Open the database - this.db = SQLite.openDatabaseSync('aliasvault.db'); + // For in-memory database, we need to create a temporary file first + const tempFileUri = `${FileSystem.documentDirectory}SQLite/temp.db`; + console.log('Writing database to temporary file'); + await FileSystem.writeAsStringAsync(tempFileUri, base64String, { + encoding: FileSystem.EncodingType.Base64, + }); - // Convert base64 to Uint8Array - const binaryString = atob(base64String); - const bytes = new Uint8Array(binaryString.length); - for (let i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i); + console.log('Database written to temporary file'); + console.log('tempFileUri', tempFileUri); + + // Open the database in memory + console.log('Opening database from file'); + this.db = SQLite.openDatabaseSync('temp.db'); + + console.log('Database opened from file'); + + // TODO: Finish implementation of in-memory database as we don't want to persist the database to the file system. + + // Attach in-memory db + /*await this.executeUpdate(`ATTACH DATABASE ':memory:' AS target`); + await this.executeUpdate('BEGIN TRANSACTION'); + + console.log('Executing query to get tables'); + + // Copy all tables from source to memory + const tables = await this.executeQuery<{ name: string }>( + "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" + ); + + console.log('Tables copied'); + + for (const table of tables) { + await this.executeUpdate(`CREATE TABLE ${table.name} AS SELECT * FROM target.${table.name}`); } + + await this.executeUpdate('COMMIT'); + await this.executeUpdate('DETACH DATABASE source'); + + // Clean up the temporary file + await FileSystem.deleteAsync(tempFileUri);*/ - // Import the database + // Setup database pragmas to configure the database. await this.executeUpdate('PRAGMA journal_mode = WAL'); await this.executeUpdate('PRAGMA synchronous = NORMAL'); await this.executeUpdate('PRAGMA foreign_keys = ON'); - - // TODO: Implement database import from bytes - // This is a complex operation that would require writing the bytes to a file - // and then importing that file into the SQLite database - console.warn('Database import from base64 not yet implemented'); } catch (error) { console.error('Error initializing SQLite database:', error); throw error; @@ -84,10 +111,20 @@ class SqliteClient { } try { - const results = await this.db!.getAllAsync( + console.log('Executing query:', query); + + // First do query to get all tables + const tables = await this.db.getAllAsync( + "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" + ); + + console.log('Tables:', tables); + + const results = await this.db.getAllAsync( query, ...params ); + console.log('Results:', results); return results as T[]; } catch (error) { console.error('Error executing query:', error); @@ -104,7 +141,7 @@ class SqliteClient { } try { - const result = await this.db!.runAsync( + const result = await this.db.runAsync( query, ...params );