feat: auto-migration on startup (ensureSchema)
- db.js: ensureSchema() creates tables if not exist - server.js: calls ensureSchema() after DB connection - No manual SQL needed for deployment
This commit is contained in:
@@ -23,7 +23,7 @@ const path = require('path');
|
|||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
const { checkConnection } = require('./src/db');
|
const { checkConnection, ensureSchema } = require('./src/db');
|
||||||
const { initAuth } = require('./src/auth');
|
const { initAuth } = require('./src/auth');
|
||||||
const q = require('./src/queries');
|
const q = require('./src/queries');
|
||||||
const { MOCK_USERS, APP_VERSION } = require('./src/config');
|
const { MOCK_USERS, APP_VERSION } = require('./src/config');
|
||||||
@@ -127,7 +127,7 @@ async function start() {
|
|||||||
|
|
||||||
// ── Старт сервера ─────────────────────────────────────────────────────────────
|
// ── Старт сервера ─────────────────────────────────────────────────────────────
|
||||||
checkConnection()
|
checkConnection()
|
||||||
.then(() => console.log('DB connected'))
|
.then(() => { console.log('DB connected'); return ensureSchema(); })
|
||||||
.catch(e => console.error('DB not ready:', e.message));
|
.catch(e => console.error('DB not ready:', e.message));
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
|
|||||||
@@ -21,4 +21,46 @@ async function checkConnection() {
|
|||||||
return rows[0].ok === 1;
|
return rows[0].ok === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { pool, checkConnection };
|
async function ensureSchema() {
|
||||||
|
await pool.query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS companies (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
client_id VARCHAR(64) UNIQUE NOT NULL,
|
||||||
|
name VARCHAR(255),
|
||||||
|
custom_limit INTEGER DEFAULT NULL CHECK (custom_limit IS NULL OR custom_limit >= 0),
|
||||||
|
owner_email TEXT DEFAULT NULL,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS whitelist_entries (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE RESTRICT,
|
||||||
|
value_cidr VARCHAR(18) NOT NULL CHECK (value_cidr ~ '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$'),
|
||||||
|
comment VARCHAR(255),
|
||||||
|
created_by VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
updated_by VARCHAR(255),
|
||||||
|
updated_at TIMESTAMPTZ,
|
||||||
|
deleted_by VARCHAR(255),
|
||||||
|
deleted_at TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_entries_active_cidr
|
||||||
|
ON whitelist_entries(company_id, value_cidr) WHERE deleted_at IS NULL;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_entries_active
|
||||||
|
ON whitelist_entries(company_id, created_at DESC) WHERE deleted_at IS NULL;
|
||||||
|
CREATE TABLE IF NOT EXISTS audit_log (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_email VARCHAR(255) NOT NULL,
|
||||||
|
company_id INTEGER NOT NULL,
|
||||||
|
action VARCHAR(32) NOT NULL CHECK (action IN ('CREATE','UPDATE','DELETE')),
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
entry_id INTEGER,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_company_time ON audit_log(company_id, created_at DESC);
|
||||||
|
`);
|
||||||
|
console.log('[db] Schema ensured');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { pool, checkConnection, ensureSchema };
|
||||||
|
|||||||
Reference in New Issue
Block a user