File size: 3,628 Bytes
6fb88e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
const { Pool } = require('pg');
const fs = require('fs');
const path = require('path');

/**
 * ZETA DATABASE MANAGER v1.0
 * Handles persistent logging for ephemeral cloud environments.
 */

class DatabaseManager {
    constructor(logPath) {
        this.logPath = logPath;
        this.useDB = !!process.env.DATABASE_URL;
        this.pool = null;

        if (this.useDB) {
            console.log('[Z374-DB] 🗄️ Database URL detected. Initializing PostgreSQL pool...');
            this.pool = new Pool({
                connectionString: process.env.DATABASE_URL,
                ssl: { rejectUnauthorized: false } // Required for Supabase/Neon
            });
            this.initDB();
        } else {
            console.log('[Z374-DB] 📁 No database detected. Falling back to local file logging.');
        }
    }

    async initDB() {
        try {
            const client = await this.pool.connect();
            await client.query(`
                CREATE TABLE IF NOT EXISTS audit_logs (
                    id SERIAL PRIMARY KEY,
                    timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
                    action TEXT,
                    details JSONB
                );
            `);
            client.release();
            console.log('[Z374-DB] ✅ Database schema verified.');
        } catch (e) {
            console.error('[Z374-DB] ❌ Database initialization failed:', e.message);
            this.useDB = false;
        }
    }

    async log(action, details) {
        const timestamp = new Date().toISOString();
        const entry = `[${timestamp}] ACTION: ${action} | DETAILS: ${JSON.stringify(details)}\n`;

        // Always log to console
        console.log(`[AUDIT] ${action}:`, details);

        // Persistent DB Logging
        if (this.useDB) {
            try {
                await this.pool.query(
                    'INSERT INTO audit_logs (action, details) VALUES ($1, $2)',
                    [action, details]
                );
            } catch (e) {
                console.error('[Z374-DB] ⚠️ DB log failed, falling back to file:', e.message);
            }
        }

        // Local File Logging (Secondary)
        try {
            fs.appendFileSync(this.logPath, entry);
        } catch (e) {
            console.error('[Z374-DB] ⚠️ File log failed:', e.message);
        }
    }

    async getLogs(limit = 50) {
        if (this.useDB) {
            try {
                const res = await this.pool.query(
                    'SELECT timestamp, action, details FROM audit_logs ORDER BY timestamp DESC LIMIT $1',
                    [limit]
                );
                return res.rows.map(row => 
                    `[${row.timestamp.toISOString()}] ACTION: ${row.action} | DETAILS: ${JSON.stringify(row.details)}`
                );
            } catch (e) {
                console.error('[Z374-DB] ⚠️ DB fetch failed:', e.message);
            }
        }

        // Fallback to file
        if (!fs.existsSync(this.logPath)) return [];
        return fs.readFileSync(this.logPath, 'utf8')
            .split('\n')
            .filter(l => l)
            .reverse()
            .slice(0, limit);
    }

    async purge() {
        if (this.useDB) {
            try {
                await this.pool.query('DELETE FROM audit_logs');
            } catch (e) {
                console.error('[Z374-DB] ⚠️ DB purge failed:', e.message);
            }
        }
        fs.writeFileSync(this.logPath, `[${new Date().toISOString()}] AUDIT_PURGE: Log cleared by operator.\n`);
    }
}

module.exports = DatabaseManager;