Files
kitchen-agent/config.js
2025-10-23 19:02:56 -04:00

160 lines
3.9 KiB
JavaScript

const database = require('./database');
const crypto = require('crypto');
class ConfigManager {
constructor() {
this.encryptionKey = null;
}
getOrCreateEncryptionKey() {
// Lazy initialization - only create key when first needed
if (this.encryptionKey) {
return this.encryptionKey;
}
// In production, this should be stored securely (environment variable or secure file)
// For now, we'll generate a random key and store it in the database
try {
let key = database.getConfig('_encryption_key');
if (!key) {
key = crypto.randomBytes(32).toString('hex');
database.setConfig('_encryption_key', key);
}
this.encryptionKey = key;
return key;
} catch (error) {
// If database not ready, generate temporary key
console.warn('Database not ready, using temporary encryption key');
this.encryptionKey = crypto.randomBytes(32).toString('hex');
return this.encryptionKey;
}
}
encrypt(text) {
if (!text) return null;
try {
const key = this.getOrCreateEncryptionKey();
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(
'aes-256-cbc',
Buffer.from(key, 'hex'),
iv
);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return iv.toString('hex') + ':' + encrypted;
} catch (error) {
console.error('Encryption error:', error.message);
return null;
}
}
decrypt(text) {
if (!text) return null;
try {
const key = this.getOrCreateEncryptionKey();
const parts = text.split(':');
const iv = Buffer.from(parts[0], 'hex');
const encrypted = parts[1];
const decipher = crypto.createDecipheriv(
'aes-256-cbc',
Buffer.from(key, 'hex'),
iv
);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (error) {
console.error('Decryption error:', error.message);
return null;
}
}
get(key) {
try {
const value = database.getConfig(key);
// Decrypt token if it's the auth token
if (key === 'authToken' && value) {
return this.decrypt(value);
}
return value;
} catch (error) {
console.warn(`Config.get('${key}') failed:`, error.message);
return null;
}
}
set(key, value) {
try {
// Encrypt token if it's the auth token
if (key === 'authToken' && value) {
value = this.encrypt(value);
}
database.setConfig(key, value);
} catch (error) {
console.error(`Config.set('${key}') failed:`, error.message);
}
}
getAll() {
try {
const config = database.getConfig();
// Decrypt auth token if present
if (config.authToken) {
config.authToken = this.decrypt(config.authToken);
}
return config;
} catch (error) {
console.warn('Config.getAll() failed:', error.message);
return {};
}
}
setMultiple(configObj) {
try {
// Encrypt auth token if present
if (configObj.authToken) {
configObj.authToken = this.encrypt(configObj.authToken);
}
database.setConfigMultiple(configObj);
} catch (error) {
console.error('Config.setMultiple() failed:', error.message);
}
}
isAuthenticated() {
try {
const token = this.get('authToken');
const expiry = this.get('tokenExpiry');
if (!token) return false;
if (!expiry) return false;
const expiryDate = new Date(expiry);
const now = new Date();
return now < expiryDate;
} catch (error) {
return false;
}
}
clearAuth() {
try {
this.set('authToken', '');
this.set('tokenExpiry', '');
} catch (error) {
console.error('Failed to clear auth:', error.message);
}
}
}
module.exports = new ConfigManager();