85 lines
2.5 KiB
JavaScript
85 lines
2.5 KiB
JavaScript
// SQLite data layer + schema.
|
|
// Uses Node's built-in node:sqlite (no native compilation needed).
|
|
const { DatabaseSync } = require('node:sqlite');
|
|
const path = require('path');
|
|
|
|
const db = new DatabaseSync(process.env.DB_PATH || path.join(__dirname, 'data.db'));
|
|
// WAL is preferred but unsupported on some mounted/network filesystems; fall back quietly.
|
|
try { db.exec('PRAGMA journal_mode = WAL'); } catch { /* default rollback journal is fine */ }
|
|
db.exec('PRAGMA foreign_keys = ON');
|
|
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS teams (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
team_id TEXT NOT NULL REFERENCES teams(id),
|
|
email TEXT NOT NULL UNIQUE,
|
|
pw_hash TEXT NOT NULL,
|
|
pw_salt TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'technician',
|
|
mfa_secret TEXT,
|
|
mfa_enabled INTEGER NOT NULL DEFAULT 0,
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sessions_auth (
|
|
token TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES users(id),
|
|
mfa_passed INTEGER NOT NULL DEFAULT 0,
|
|
created_at INTEGER NOT NULL,
|
|
expires_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS machines (
|
|
id TEXT PRIMARY KEY,
|
|
team_id TEXT NOT NULL REFERENCES teams(id),
|
|
name TEXT NOT NULL,
|
|
enroll_token TEXT NOT NULL UNIQUE,
|
|
unattended INTEGER NOT NULL DEFAULT 0,
|
|
last_seen INTEGER,
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
team_id TEXT NOT NULL,
|
|
user_id TEXT,
|
|
user_email TEXT,
|
|
machine_id TEXT,
|
|
machine_name TEXT,
|
|
action TEXT NOT NULL,
|
|
detail TEXT,
|
|
at INTEGER NOT NULL
|
|
);
|
|
`);
|
|
|
|
// Migration: optional display name for agents (shown to customers on consent)
|
|
try { db.exec('ALTER TABLE users ADD COLUMN name TEXT'); } catch (e) { /* already exists */ }
|
|
|
|
// Migration: agent active flag (deactivate without deleting)
|
|
try { db.exec('ALTER TABLE users ADD COLUMN active INTEGER NOT NULL DEFAULT 1'); } catch (e) { /* exists */ }
|
|
|
|
// Session report: one row per support session with duration
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS sessions_log (
|
|
id TEXT PRIMARY KEY,
|
|
team_id TEXT NOT NULL,
|
|
agent_email TEXT,
|
|
agent_name TEXT,
|
|
ticket TEXT,
|
|
started_at INTEGER NOT NULL,
|
|
ended_at INTEGER
|
|
);
|
|
`);
|
|
|
|
// Migration: stored recording filename for a session (null if not recorded)
|
|
try { db.exec('ALTER TABLE sessions_log ADD COLUMN recording TEXT'); } catch (e) { /* exists */ }
|
|
try { db.exec('ALTER TABLE sessions_log ADD COLUMN transcript TEXT'); } catch (e) { /* exists */ }
|
|
|
|
module.exports = db;
|