const fs = require('fs'); const path = require('path'); const SECRETS_PATH = process.env.SECRETS_PATH || path.join(__dirname, '..', 'secrets.json'); const SECRET_TYPES = ['api_token', 'ssl_certificate', 'password', 'generic']; function load() { try { return JSON.parse(fs.readFileSync(SECRETS_PATH, 'utf8')); } catch { return []; } } function save(secrets) { fs.writeFileSync(SECRETS_PATH, JSON.stringify(secrets, null, 2), 'utf8'); } function getAll() { return load(); } function getById(id) { return load().find(s => s.id === id) ?? null; } function create(data) { const secrets = load(); const secret = { id: Date.now().toString(), name: data.name, type: data.type || 'generic', description: data.description || '', expires_at: data.expires_at, warning_days: Number(data.warning_days) || 30, notes: data.notes || '', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), }; secrets.push(secret); save(secrets); return secret; } function update(id, data) { const secrets = load(); const idx = secrets.findIndex(s => s.id === id); if (idx === -1) throw new Error('Secret not found'); secrets[idx] = { ...secrets[idx], name: data.name ?? secrets[idx].name, type: data.type ?? secrets[idx].type, description: data.description ?? secrets[idx].description, expires_at: data.expires_at ?? secrets[idx].expires_at, warning_days: data.warning_days !== undefined ? Number(data.warning_days) : secrets[idx].warning_days, notes: data.notes ?? secrets[idx].notes, updated_at: new Date().toISOString(), }; save(secrets); return secrets[idx]; } function remove(id) { const secrets = load(); const filtered = secrets.filter(s => s.id !== id); if (filtered.length === secrets.length) throw new Error('Secret not found'); save(filtered); } /** * Returns secrets grouped by expiry status. * Status: 'expired' | 'warning' | 'ok' */ function getStatus() { const secrets = load(); const now = new Date(); return secrets.map(s => { const expiry = new Date(s.expires_at); const daysLeft = Math.ceil((expiry - now) / (1000 * 60 * 60 * 24)); let status; if (daysLeft < 0) status = 'expired'; else if (daysLeft <= s.warning_days) status = 'warning'; else status = 'ok'; return { ...s, daysLeft, status }; }); } /** * Returns secrets that are expired or within their warning window. */ function getExpiring() { return getStatus().filter(s => s.status !== 'ok'); } module.exports = { SECRET_TYPES, getAll, getById, create, update, remove, getStatus, getExpiring };