Add multi-language support and new repository methods for book synchronization
- Extend repository methods to handle API requests for fetching books, chapters, characters, and other entities with multilingual support (`lang: 'fr' | 'en'`). - Add `uploadBookForSync` logic to consolidate and decrypt book data for synchronization. - Refactor schema migration logic to remove console logs and streamline table recreation. - Enhance error handling across database repositories and IPC methods.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import {app, BrowserWindow, ipcMain, nativeImage, protocol, safeStorage, shell} from 'electron';
|
||||
import {app, BrowserWindow, ipcMain, IpcMainInvokeEvent, nativeImage, protocol, safeStorage, shell} from 'electron';
|
||||
import * as path from 'path';
|
||||
import {fileURLToPath} from 'url';
|
||||
import * as fs from 'fs';
|
||||
@@ -152,13 +152,13 @@ ipcMain.handle('set-lang', (_event, lang: 'fr' | 'en') => {
|
||||
});
|
||||
|
||||
// IPC Handler pour initialiser l'utilisateur après récupération depuis le serveur
|
||||
ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
ipcMain.handle('init-user', async (_event:IpcMainInvokeEvent, userId: string) => {
|
||||
const storage:SecureStorage = getSecureStorage();
|
||||
storage.set('userId', userId);
|
||||
storage.set('lastUserId', userId);
|
||||
|
||||
try {
|
||||
let encryptionKey: string | null = null;
|
||||
let encryptionKey: string | null;
|
||||
|
||||
if (!hasUserEncryptionKey(userId)) {
|
||||
encryptionKey = generateUserEncryptionKey(userId);
|
||||
@@ -170,14 +170,12 @@ ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
setUserEncryptionKey(userId, encryptionKey);
|
||||
|
||||
const savedKey:string = getUserEncryptionKey(userId);
|
||||
console.log('[InitUser] Key verification after save:', savedKey ? `${savedKey.substring(0, 10)}...` : 'UNDEFINED');
|
||||
|
||||
if (!savedKey) {
|
||||
throw new Error('Failed to save encryption key');
|
||||
}
|
||||
} else {
|
||||
encryptionKey = getUserEncryptionKey(userId);
|
||||
console.log('[InitUser] Using existing encryption key:', encryptionKey ? `${encryptionKey.substring(0, 10)}...` : 'UNDEFINED');
|
||||
|
||||
if (!encryptionKey) {
|
||||
console.error('[InitUser] CRITICAL: Existing key is undefined, regenerating');
|
||||
@@ -189,14 +187,15 @@ ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
|
||||
if (safeStorage.isEncryptionAvailable()) {
|
||||
storage.save();
|
||||
console.log('[InitUser] User ID and lastUserId saved to disk (encrypted)');
|
||||
} else {
|
||||
console.error('[InitUser] WARNING: Cannot save user ID - encryption not available');
|
||||
return {
|
||||
success: false,
|
||||
error: 'Encryption is not available on this system'
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true, keyCreated: !hasUserEncryptionKey(userId) };
|
||||
} catch (error) {
|
||||
console.error('[InitUser] Error managing encryption key:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
@@ -205,7 +204,6 @@ ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
});
|
||||
|
||||
ipcMain.on('login-success', async (_event, token: string) => {
|
||||
console.log('[Login] Received token, setting in storage');
|
||||
const storage = getSecureStorage();
|
||||
storage.set('authToken', token);
|
||||
|
||||
@@ -215,7 +213,7 @@ ipcMain.on('login-success', async (_event, token: string) => {
|
||||
|
||||
createMainWindow();
|
||||
|
||||
setTimeout(async () => {
|
||||
setTimeout(async ():Promise<void> => {
|
||||
try {
|
||||
if (safeStorage.isEncryptionAvailable()) {
|
||||
storage.save();
|
||||
@@ -294,7 +292,6 @@ ipcMain.handle('db:user:sync', async (_event, data: SyncUserData): Promise<boole
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[DB] Failed to sync user:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
@@ -307,7 +304,6 @@ ipcMain.handle('generate-encryption-key', async (_event, userId: string) => {
|
||||
const key:string = generateUserEncryptionKey(userId);
|
||||
return { success: true, key };
|
||||
} catch (error) {
|
||||
console.error('Failed to generate encryption key:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
@@ -341,7 +337,6 @@ ipcMain.handle('db-initialize', (_event, userId: string, encryptionKey: string)
|
||||
db.initialize(userId, encryptionKey);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize database:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
@@ -349,9 +344,9 @@ ipcMain.handle('db-initialize', (_event, userId: string, encryptionKey: string)
|
||||
}
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
app.whenReady().then(():void => {
|
||||
if (!isDev) {
|
||||
const outPath = path.join(process.resourcesPath, 'app.asar.unpacked/out');
|
||||
const outPath:string = path.join(process.resourcesPath, 'app.asar.unpacked/out');
|
||||
|
||||
protocol.handle('app', async (request) => {
|
||||
let filePath:string = request.url.replace('app://', '').replace(/^\.\//, '');
|
||||
@@ -394,17 +389,8 @@ app.whenReady().then(() => {
|
||||
}
|
||||
|
||||
// Vérifier si un token existe (OS-encrypted storage)
|
||||
const storage = getSecureStorage();
|
||||
const token = storage.get('authToken');
|
||||
const userId = storage.get('userId');
|
||||
const offlineMode = storage.get<boolean>('offlineMode', false);
|
||||
const lastUserId = storage.get<string>('lastUserId');
|
||||
const hasPin = !!storage.get<string>(`pin-${lastUserId}`);
|
||||
|
||||
console.log('[Startup] Token exists:', !!token);
|
||||
console.log('[Startup] UserId exists:', !!userId);
|
||||
console.log('[Startup] Offline mode:', offlineMode);
|
||||
console.log('[Startup] Has PIN:', hasPin);
|
||||
const storage: SecureStorage = getSecureStorage();
|
||||
const token: string | null = storage.get('authToken');
|
||||
|
||||
if (token) {
|
||||
createMainWindow();
|
||||
@@ -412,10 +398,10 @@ app.whenReady().then(() => {
|
||||
createLoginWindow();
|
||||
}
|
||||
|
||||
app.on('activate', () => {
|
||||
app.on('activate', ():void => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
const storage = getSecureStorage();
|
||||
const token = storage.get('authToken');
|
||||
const storage: SecureStorage = getSecureStorage();
|
||||
const token: string | null = storage.get('authToken');
|
||||
if (token) {
|
||||
createMainWindow();
|
||||
} else {
|
||||
@@ -425,7 +411,6 @@ app.whenReady().then(() => {
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
// Quitter l'application quand toutes les fenêtres sont fermées
|
||||
app.on('window-all-closed', ():void => {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user