Add offline mode support with PIN configuration and management
- Introduce `OfflinePinSetup` component for users to configure secure offline access. - Add new `AIUsageContext` and extend `OfflineProvider` for offline-related state management. - Implement offline login functionality in `electron/main.ts` with PIN verification and fallback support. - Enhance IPC handlers to manage offline mode data, PIN setup, and synchronization. - Update localization files (`en.json`, `fr.json`) with offline mode and PIN-related strings. - Add `bcrypt` and `@types/bcrypt` dependencies for secure PIN hashing and validation. - Refactor login and session management to handle offline mode scenarios with improved error handling and flow.
This commit is contained in:
@@ -12,6 +12,7 @@ import './ipc/user.ipc.js';
|
||||
import './ipc/chapter.ipc.js';
|
||||
import './ipc/character.ipc.js';
|
||||
import './ipc/location.ipc.js';
|
||||
import './ipc/offline.ipc.js';
|
||||
|
||||
// Fix pour __dirname en ES modules
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -152,6 +153,7 @@ ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
|
||||
const storage = getSecureStorage();
|
||||
storage.set('userId', userId);
|
||||
storage.set('lastUserId', userId); // Save for offline mode
|
||||
|
||||
try {
|
||||
const { getUserEncryptionKey, setUserEncryptionKey, hasUserEncryptionKey } = await import('./database/keyManager.js');
|
||||
@@ -192,11 +194,11 @@ ipcMain.handle('init-user', async (_event, userId: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Save userId to disk now that we have everything
|
||||
// Save userId and lastUserId to disk now that we have everything
|
||||
// This is the ONLY additional save after login
|
||||
if (safeStorage.isEncryptionAvailable()) {
|
||||
storage.save();
|
||||
console.log('[InitUser] User ID saved to disk (encrypted)');
|
||||
console.log('[InitUser] User ID and lastUserId saved to disk (encrypted)');
|
||||
} else {
|
||||
console.error('[InitUser] WARNING: Cannot save user ID - encryption not available');
|
||||
}
|
||||
@@ -441,17 +443,53 @@ app.whenReady().then(() => {
|
||||
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);
|
||||
if (token) {
|
||||
console.log('[Startup] Token value:', token.substring(0, 20) + '...');
|
||||
}
|
||||
console.log('[Startup] Offline mode:', offlineMode);
|
||||
console.log('[Startup] Has PIN:', hasPin);
|
||||
|
||||
if (token) {
|
||||
// Token existe, ouvrir la fenêtre principale
|
||||
createMainWindow();
|
||||
} else if (offlineMode && hasPin && lastUserId) {
|
||||
// Mode offline activé avec PIN, ouvrir login offline
|
||||
console.log('[Startup] Opening offline login page');
|
||||
loginWindow = new BrowserWindow({
|
||||
width: 500,
|
||||
height: 900,
|
||||
resizable: false,
|
||||
...(process.platform !== 'darwin' && { icon: iconPath }),
|
||||
webPreferences: {
|
||||
preload: preloadPath,
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
},
|
||||
frame: true,
|
||||
show: false,
|
||||
});
|
||||
|
||||
if (isDev) {
|
||||
const devPort = process.env.PORT || '4000';
|
||||
loginWindow.loadURL(`http://localhost:${devPort}/login/offline`);
|
||||
loginWindow.webContents.openDevTools();
|
||||
} else {
|
||||
loginWindow.loadURL('app://./login/offline/index.html');
|
||||
}
|
||||
|
||||
loginWindow.once('ready-to-show', () => {
|
||||
loginWindow?.show();
|
||||
});
|
||||
|
||||
loginWindow.on('closed', () => {
|
||||
loginWindow = null;
|
||||
});
|
||||
} else {
|
||||
// Pas de token, ouvrir la fenêtre de login
|
||||
// Pas de token ou pas de mode offline, ouvrir la fenêtre de login normale
|
||||
createLoginWindow();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user