Чистый ensureSchema: только CREATE TABLE IF NOT EXISTS, без миграций. Версия 0.1.21

This commit is contained in:
2026-07-09 00:27:53 +04:00
parent 3e15fd4973
commit b3f5c4903e
3 changed files with 4 additions and 49 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "ipwhitelist",
"version": "0.1.20",
"version": "0.1.21",
"description": "IP WhiteList microservice for cloud provider",
"main": "server.js",
"scripts": {
+1 -1
View File
@@ -8,7 +8,7 @@
// ═══════════════════════════════════════════════════════════════════════════════
module.exports = {
version: '0.1.20',
version: '0.1.21',
// ── Среда ─────────────────────────────────────────────────────────────────
// APP_ENV=test → тестовый стенд (жёлтый баннер в UI, можно включать тестовый API)
+2 -47
View File
@@ -2,19 +2,11 @@
// V2 — инициализация схемы БД
//
// ЭТО: CREATE TABLE IF NOT EXISTS — безопасный повторный запуск.
// ЗАЧЕМ:
// 1. Приложение само создаёт таблицы при старте.
// 2. Безопасно для production: IF NOT EXISTS.
//
// ТАБЛИЦЫ:
// companies — client_id (W-номер), name, custom_limit
// whitelist_entries — CIDR, комментарий, кто создал/изменил/удалил
// audit_log — все действия: CREATE/UPDATE/DELETE/RESTORE, с impersonated_by
// НИКАКИХ ALTER, миграций, DO$$ блоков. Только создание таблиц.
// ═══════════════════════════════════════════════════════════════════════════════
async function ensureSchema(pool) {
await pool.query(`
-- Компании: W-номер уникален, upsert через ON CONFLICT
CREATE TABLE IF NOT EXISTS companies (
id SERIAL PRIMARY KEY,
client_id VARCHAR(64) NOT NULL UNIQUE,
@@ -24,7 +16,6 @@ async function ensureSchema(pool) {
updated_at TIMESTAMPTZ
);
-- Записи: CIDR + метаданные, soft delete
CREATE TABLE IF NOT EXISTS whitelist_entries (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL,
@@ -38,17 +29,15 @@ async function ensureSchema(pool) {
deleted_at TIMESTAMPTZ
);
-- Защита от дублей: уникальный CIDR в компании среди активных записей
CREATE UNIQUE INDEX IF NOT EXISTS idx_whitelist_entries_active_cidr
ON whitelist_entries(company_id, value_cidr)
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','RESTORE')),
action VARCHAR(32) NOT NULL,
old_value TEXT,
new_value TEXT,
entry_id INTEGER,
@@ -60,40 +49,6 @@ async function ensureSchema(pool) {
ON audit_log(company_id, created_at DESC);
`);
// Миграция: impersonated_by (если колонки ещё нет)
await pool.query(`
ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS impersonated_by VARCHAR(255) DEFAULT NULL
`).catch(() => {});
// Миграция: добавить RESTORE в CHECK — только если ещё нет (без DROP+ADD каждый раз)
await pool.query(`
DO $$
DECLARE
cn text;
has_restore boolean;
BEGIN
-- Проверяем, есть ли уже RESTORE в constraint
SELECT con.consrc LIKE '%RESTORE%' OR pg_get_constraintdef(con.oid) LIKE '%RESTORE%' INTO has_restore
FROM pg_constraint con
JOIN pg_class rel ON rel.oid = con.conrelid
WHERE rel.relname = 'audit_log' AND con.contype = 'c';
-- Если уже есть — ничего не делаем
IF has_restore THEN
RAISE NOTICE 'audit_log CHECK already includes RESTORE, skipping';
RETURN;
END IF;
SELECT con.conname INTO cn
FROM pg_constraint con
JOIN pg_class rel ON rel.oid = con.conrelid
WHERE rel.relname = 'audit_log' AND con.contype = 'c';
IF cn IS NOT NULL THEN
EXECUTE 'ALTER TABLE audit_log DROP CONSTRAINT ' || cn;
END IF;
EXECUTE 'ALTER TABLE audit_log ADD CONSTRAINT audit_log_action_check CHECK (action IN (''CREATE'',''UPDATE'',''DELETE'',''RESTORE''))';
END;
$$;
`).catch(() => {});
console.log('[db] Schema ensured');
}