remove providerSettings firebaseRepository + minor refactor
This commit is contained in:
		
							parent
							
								
									ab23c10006
								
							
						
					
					
						commit
						8592d1c4ed
					
				@ -1,83 +0,0 @@
 | 
				
			|||||||
const { collection, doc, getDoc, getDocs, setDoc, deleteDoc, query, where } = require('firebase/firestore');
 | 
					 | 
				
			||||||
const { getFirestoreInstance: getFirestore } = require('../../services/firebaseClient');
 | 
					 | 
				
			||||||
const { createEncryptedConverter } = require('../firestoreConverter');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Create encrypted converter for provider settings
 | 
					 | 
				
			||||||
const providerSettingsConverter = createEncryptedConverter([
 | 
					 | 
				
			||||||
    'api_key', // Encrypt API keys
 | 
					 | 
				
			||||||
    'selected_llm_model', // Encrypt model selections for privacy
 | 
					 | 
				
			||||||
    'selected_stt_model'
 | 
					 | 
				
			||||||
]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function providerSettingsCol() {
 | 
					 | 
				
			||||||
    const db = getFirestore();
 | 
					 | 
				
			||||||
    return collection(db, 'provider_settings').withConverter(providerSettingsConverter);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function getByProvider(uid, provider) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const docRef = doc(providerSettingsCol(), `${uid}_${provider}`);
 | 
					 | 
				
			||||||
        const docSnap = await getDoc(docRef);
 | 
					 | 
				
			||||||
        return docSnap.exists() ? { id: docSnap.id, ...docSnap.data() } : null;
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('[ProviderSettings Firebase] Error getting provider settings:', error);
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function getAllByUid(uid) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const q = query(providerSettingsCol(), where('uid', '==', uid));
 | 
					 | 
				
			||||||
        const querySnapshot = await getDocs(q);
 | 
					 | 
				
			||||||
        return querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('[ProviderSettings Firebase] Error getting all provider settings:', error);
 | 
					 | 
				
			||||||
        return [];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function upsert(uid, provider, settings) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const docRef = doc(providerSettingsCol(), `${uid}_${provider}`);
 | 
					 | 
				
			||||||
        await setDoc(docRef, settings, { merge: true });
 | 
					 | 
				
			||||||
        return { changes: 1 };
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('[ProviderSettings Firebase] Error upserting provider settings:', error);
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function remove(uid, provider) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const docRef = doc(providerSettingsCol(), `${uid}_${provider}`);
 | 
					 | 
				
			||||||
        await deleteDoc(docRef);
 | 
					 | 
				
			||||||
        return { changes: 1 };
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('[ProviderSettings Firebase] Error removing provider settings:', error);
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function removeAllByUid(uid) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const settings = await getAllByUid(uid);
 | 
					 | 
				
			||||||
        const deletePromises = settings.map(setting => {
 | 
					 | 
				
			||||||
            const docRef = doc(providerSettingsCol(), setting.id);
 | 
					 | 
				
			||||||
            return deleteDoc(docRef);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        await Promise.all(deletePromises);
 | 
					 | 
				
			||||||
        return { changes: settings.length };
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('[ProviderSettings Firebase] Error removing all provider settings:', error);
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    getByProvider,
 | 
					 | 
				
			||||||
    getAllByUid,
 | 
					 | 
				
			||||||
    upsert,
 | 
					 | 
				
			||||||
    remove,
 | 
					 | 
				
			||||||
    removeAllByUid
 | 
					 | 
				
			||||||
}; 
 | 
					 | 
				
			||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
const firebaseRepository = require('./firebase.repository');
 | 
					 | 
				
			||||||
const sqliteRepository = require('./sqlite.repository');
 | 
					const sqliteRepository = require('./sqlite.repository');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let authService = null;
 | 
					let authService = null;
 | 
				
			||||||
@ -8,12 +7,7 @@ function setAuthService(service) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getBaseRepository() {
 | 
					function getBaseRepository() {
 | 
				
			||||||
    if (!authService) {
 | 
					    return sqliteRepository;
 | 
				
			||||||
        throw new Error('AuthService not set for providerSettings repository');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const user = authService.getCurrentUser();
 | 
					 | 
				
			||||||
    return user.isLoggedIn ? firebaseRepository : sqliteRepository;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const providerSettingsRepositoryAdapter = {
 | 
					const providerSettingsRepositoryAdapter = {
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ class AuthService {
 | 
				
			|||||||
                    // ** Initialize encryption key for the logged-in user if permissions are already granted **
 | 
					                    // ** Initialize encryption key for the logged-in user if permissions are already granted **
 | 
				
			||||||
                    if (process.platform === 'darwin' && !(await permissionService.checkKeychainCompleted(this.currentUserId))) {
 | 
					                    if (process.platform === 'darwin' && !(await permissionService.checkKeychainCompleted(this.currentUserId))) {
 | 
				
			||||||
                        console.warn('[AuthService] Keychain permission not yet completed for this user. Deferring key initialization.');
 | 
					                        console.warn('[AuthService] Keychain permission not yet completed for this user. Deferring key initialization.');
 | 
				
			||||||
                    } else if (process.platform === 'darwin') {
 | 
					                    } else {
 | 
				
			||||||
                        await encryptionService.initializeKey(user.uid);
 | 
					                        await encryptionService.initializeKey(user.uid);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -113,12 +113,7 @@ class AuthService {
 | 
				
			|||||||
                    // End active sessions for the local/default user as well.
 | 
					                    // End active sessions for the local/default user as well.
 | 
				
			||||||
                    await sessionRepository.endAllActiveSessions();
 | 
					                    await sessionRepository.endAllActiveSessions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // ** Initialize encryption key for the default/local user if permissions are already granted **
 | 
					                    encryptionService.resetSessionKey();
 | 
				
			||||||
                    if (process.platform === 'darwin' && !(await permissionService.checkKeychainCompleted(this.currentUserId))) {
 | 
					 | 
				
			||||||
                        console.warn('[AuthService] Keychain permission not yet completed for default user. Deferring key initialization.');
 | 
					 | 
				
			||||||
                    } else if (process.platform === 'darwin') {
 | 
					 | 
				
			||||||
                        await encryptionService.initializeKey(this.currentUserId);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                this.broadcastUserState();
 | 
					                this.broadcastUserState();
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,10 @@ async function initializeKey(userId) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function resetSessionKey() {
 | 
				
			||||||
 | 
					    sessionKey = null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Encrypts a given text using AES-256-GCM.
 | 
					 * Encrypts a given text using AES-256-GCM.
 | 
				
			||||||
 * @param {string} text The text to encrypt.
 | 
					 * @param {string} text The text to encrypt.
 | 
				
			||||||
@ -149,8 +153,23 @@ function decrypt(encryptedText) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function looksEncrypted(str) {
 | 
				
			||||||
 | 
					    if (!str || typeof str !== 'string') return false;
 | 
				
			||||||
 | 
					    // Base64 chars + optional '=' padding
 | 
				
			||||||
 | 
					    if (!/^[A-Za-z0-9+/]+={0,2}$/.test(str)) return false;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        const buf = Buffer.from(str, 'base64');
 | 
				
			||||||
 | 
					        // Our AES-GCM cipher text must be at least 32 bytes (IV 16 + TAG 16)
 | 
				
			||||||
 | 
					        return buf.length >= 32;
 | 
				
			||||||
 | 
					    } catch {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    initializeKey,
 | 
					    initializeKey,
 | 
				
			||||||
 | 
					    resetSessionKey,
 | 
				
			||||||
    encrypt,
 | 
					    encrypt,
 | 
				
			||||||
    decrypt,
 | 
					    decrypt,
 | 
				
			||||||
 | 
					    looksEncrypted,
 | 
				
			||||||
}; 
 | 
					}; 
 | 
				
			||||||
@ -6,23 +6,7 @@ const { PROVIDERS, getProviderClass } = require('../ai/factory');
 | 
				
			|||||||
const encryptionService = require('./encryptionService');
 | 
					const encryptionService = require('./encryptionService');
 | 
				
			||||||
const providerSettingsRepository = require('../repositories/providerSettings');
 | 
					const providerSettingsRepository = require('../repositories/providerSettings');
 | 
				
			||||||
const userModelSelectionsRepository = require('../repositories/userModelSelections');
 | 
					const userModelSelectionsRepository = require('../repositories/userModelSelections');
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Import authService directly (singleton)
 | 
					 | 
				
			||||||
const authService = require('./authService');
 | 
					const authService = require('./authService');
 | 
				
			||||||
const permissionService = require('./permissionService');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function looksEncrypted(str) {
 | 
					 | 
				
			||||||
    if (!str || typeof str !== 'string') return false;
 | 
					 | 
				
			||||||
    // Base64 chars + optional '=' padding
 | 
					 | 
				
			||||||
    if (!/^[A-Za-z0-9+/]+={0,2}$/.test(str)) return false;
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const buf = Buffer.from(str, 'base64');
 | 
					 | 
				
			||||||
        // Our AES-GCM cipher text must be at least 32 bytes (IV 16 + TAG 16)
 | 
					 | 
				
			||||||
        return buf.length >= 32;
 | 
					 | 
				
			||||||
    } catch {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ModelStateService extends EventEmitter {
 | 
					class ModelStateService extends EventEmitter {
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
@ -223,7 +207,7 @@ class ModelStateService extends EventEmitter {
 | 
				
			|||||||
        // Conditionally initialize encryption if old encrypted keys are detected
 | 
					        // Conditionally initialize encryption if old encrypted keys are detected
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            const rows = await providerSettingsRepository.getRawApiKeysByUid();
 | 
					            const rows = await providerSettingsRepository.getRawApiKeysByUid();
 | 
				
			||||||
            if (rows.some(r => looksEncrypted(r.api_key))) {
 | 
					            if (rows.some(r => encryptionService.looksEncrypted(r.api_key))) {
 | 
				
			||||||
                console.log('[ModelStateService] Encrypted keys detected, initializing encryption...');
 | 
					                console.log('[ModelStateService] Encrypted keys detected, initializing encryption...');
 | 
				
			||||||
                await encryptionService.initializeKey(userId);
 | 
					                await encryptionService.initializeKey(userId);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user