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