feat: Add comprehensive database schema migrations for all platform tables

- Add subscribers table with IMSI, MSISDN, authentication keys, and eSIM profile fields
- Add service_plans table for data/voice/SMS limits and QoS parameters (ARPA, AMBR)
- Add sessions table for tracking PDU sessions with QoS and usage metrics
- Add usage_records table for billing and charging data
- Add users table with role-based access control fields
- Add roles, permissions, and role_permissions junction table for RBAC
- Add auth
This commit is contained in:
nutcas3
2026-04-29 03:25:28 +03:00
parent 28422fafc1
commit e6450f15ad
16 changed files with 485 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
-- +goose Up
-- Create subscribers table
CREATE TABLE IF NOT EXISTS subscribers (
id SERIAL PRIMARY KEY,
imsi TEXT NOT NULL UNIQUE,
msisdn TEXT UNIQUE,
imei TEXT,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT UNIQUE,
organization_id TEXT,
status TEXT NOT NULL DEFAULT 'active',
plan_id INTEGER,
balance DOUBLE PRECISION NOT NULL DEFAULT 0,
auth_key TEXT NOT NULL,
opc TEXT NOT NULL,
serving_plmn_mcc TEXT NOT NULL,
serving_plmn_mnc TEXT NOT NULL,
euicc_id TEXT,
profile_id TEXT,
profile_status TEXT NOT NULL DEFAULT 'inactive',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_subscribers_imsi ON subscribers(imsi);
CREATE INDEX IF NOT EXISTS idx_subscribers_msisdn ON subscribers(msisdn);
CREATE INDEX IF NOT EXISTS idx_subscribers_email ON subscribers(email);
CREATE INDEX IF NOT EXISTS idx_subscribers_status ON subscribers(status);
CREATE INDEX IF NOT EXISTS idx_subscribers_organization_id ON subscribers(organization_id);
CREATE INDEX IF NOT EXISTS idx_subscribers_plan_id ON subscribers(plan_id);
CREATE INDEX IF NOT EXISTS idx_subscribers_deleted_at ON subscribers(deleted_at);
-- +goose Down
-- Drop subscribers table
DROP TABLE IF EXISTS subscribers CASCADE;
+28
View File
@@ -0,0 +1,28 @@
-- +goose Up
-- Create service_plans table
CREATE TABLE IF NOT EXISTS service_plans (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
data_limit BIGINT,
voice_limit INTEGER,
sms_limit INTEGER,
monthly_fee DOUBLE PRECISION,
data_rate DOUBLE PRECISION,
voice_rate DOUBLE PRECISION,
sms_rate DOUBLE PRECISION,
arpa INTEGER,
ambr_uplink INTEGER,
ambr_downlink INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_service_plans_name ON service_plans(name);
CREATE INDEX IF NOT EXISTS idx_service_plans_deleted_at ON service_plans(deleted_at);
-- +goose Down
-- Drop service_plans table
DROP TABLE IF EXISTS service_plans CASCADE;
+37
View File
@@ -0,0 +1,37 @@
-- +goose Up
-- Create sessions table
CREATE TABLE IF NOT EXISTS sessions (
id SERIAL PRIMARY KEY,
subscriber_id INTEGER NOT NULL,
session_id TEXT NOT NULL UNIQUE,
pdu_address TEXT,
dnn TEXT,
snssai_sst SMALLINT,
snssai_sd INTEGER,
qos_qci SMALLINT,
qos_arpa INTEGER,
qos_mbr_uplink INTEGER,
qos_mbr_downlink INTEGER,
qos_gbr_uplink INTEGER,
qos_gbr_downlink INTEGER,
qos_priority SMALLINT,
status TEXT NOT NULL DEFAULT 'active',
start_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
end_time TIMESTAMPTZ,
data_used BIGINT NOT NULL DEFAULT 0,
voice_used INTEGER NOT NULL DEFAULT 0,
sms_used INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_sessions_subscriber_id ON sessions(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_sessions_session_id ON sessions(session_id);
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
CREATE INDEX IF NOT EXISTS idx_sessions_deleted_at ON sessions(deleted_at);
-- +goose Down
-- Drop sessions table
DROP TABLE IF EXISTS sessions CASCADE;
+27
View File
@@ -0,0 +1,27 @@
-- +goose Up
-- Create usage_records table
CREATE TABLE IF NOT EXISTS usage_records (
id SERIAL PRIMARY KEY,
subscriber_id INTEGER NOT NULL,
session_id INTEGER,
usage_type TEXT NOT NULL,
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ NOT NULL,
volume BIGINT NOT NULL,
rate DOUBLE PRECISION,
cost DOUBLE PRECISION,
billing_cycle TEXT,
invoice_id INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_usage_records_subscriber_id ON usage_records(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_usage_records_session_id ON usage_records(session_id);
CREATE INDEX IF NOT EXISTS idx_usage_records_usage_type ON usage_records(usage_type);
CREATE INDEX IF NOT EXISTS idx_usage_records_billing_cycle ON usage_records(billing_cycle);
-- +goose Down
-- Drop usage_records table
DROP TABLE IF EXISTS usage_records CASCADE;
+26
View File
@@ -0,0 +1,26 @@
-- +goose Up
-- Create users table
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'viewer',
is_active BOOLEAN NOT NULL DEFAULT true,
last_login TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
CREATE INDEX IF NOT EXISTS idx_users_deleted_at ON users(deleted_at);
-- +goose Down
-- Drop users table
DROP TABLE IF EXISTS users CASCADE;
@@ -0,0 +1,37 @@
-- +goose Up
-- Create roles table
CREATE TABLE IF NOT EXISTS roles (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create permissions table
CREATE TABLE IF NOT EXISTS permissions (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
resource TEXT NOT NULL,
action TEXT NOT NULL,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create role_permissions junction table
CREATE TABLE IF NOT EXISTS role_permissions (
role_id INTEGER NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
permission_id INTEGER NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
PRIMARY KEY (role_id, permission_id)
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_role_permissions_role_id ON role_permissions(role_id);
CREATE INDEX IF NOT EXISTS idx_role_permissions_permission_id ON role_permissions(permission_id);
-- +goose Down
-- Drop role_permissions, permissions, and roles tables
DROP TABLE IF EXISTS role_permissions CASCADE;
DROP TABLE IF EXISTS permissions CASCADE;
DROP TABLE IF EXISTS roles CASCADE;
@@ -0,0 +1,40 @@
-- +goose Up
-- Create auth_sessions table
CREATE TABLE IF NOT EXISTS auth_sessions (
id TEXT PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token TEXT NOT NULL,
refresh_token TEXT NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
ip_address TEXT,
user_agent TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create api_keys table
CREATE TABLE IF NOT EXISTS api_keys (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
key TEXT NOT NULL UNIQUE,
secret TEXT NOT NULL,
permissions JSONB,
is_active BOOLEAN NOT NULL DEFAULT true,
expires_at TIMESTAMPTZ,
last_used TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_auth_sessions_user_id ON auth_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_auth_sessions_token ON auth_sessions(token);
CREATE INDEX IF NOT EXISTS idx_auth_sessions_expires_at ON auth_sessions(expires_at);
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key);
CREATE INDEX IF NOT EXISTS idx_api_keys_is_active ON api_keys(is_active);
-- +goose Down
-- Drop auth_sessions and api_keys tables
DROP TABLE IF EXISTS auth_sessions CASCADE;
DROP TABLE IF EXISTS api_keys CASCADE;
+30
View File
@@ -0,0 +1,30 @@
-- +goose Up
-- Create plugins table
CREATE TABLE IF NOT EXISTS plugins (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
version TEXT NOT NULL,
description TEXT,
author TEXT,
type TEXT,
category TEXT,
license TEXT,
homepage TEXT,
repository TEXT,
enabled BOOLEAN NOT NULL DEFAULT false,
status TEXT NOT NULL DEFAULT 'installed',
config JSONB,
installed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_plugins_name ON plugins(name);
CREATE INDEX IF NOT EXISTS idx_plugins_enabled ON plugins(enabled);
CREATE INDEX IF NOT EXISTS idx_plugins_deleted_at ON plugins(deleted_at);
-- +goose Down
-- Drop plugins table
DROP TABLE IF EXISTS plugins CASCADE;
+46
View File
@@ -0,0 +1,46 @@
-- +goose Up
-- Create automations table
CREATE TABLE IF NOT EXISTS automations (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
type TEXT,
enabled BOOLEAN NOT NULL DEFAULT true,
schedule_type TEXT,
schedule_cron TEXT,
schedule_interval_sec INTEGER,
timezone TEXT NOT NULL DEFAULT 'UTC',
definition JSONB,
last_run_at TIMESTAMPTZ,
next_run_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Create automation_runs table
CREATE TABLE IF NOT EXISTS automation_runs (
id SERIAL PRIMARY KEY,
automation_id INTEGER NOT NULL REFERENCES automations(id) ON DELETE CASCADE,
status TEXT NOT NULL,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
ended_at TIMESTAMPTZ,
duration_ms BIGINT NOT NULL DEFAULT 0,
output TEXT,
error TEXT,
details JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_automations_name ON automations(name);
CREATE INDEX IF NOT EXISTS idx_automations_enabled ON automations(enabled);
CREATE INDEX IF NOT EXISTS idx_automations_deleted_at ON automations(deleted_at);
CREATE INDEX IF NOT EXISTS idx_automation_runs_automation_id ON automation_runs(automation_id);
CREATE INDEX IF NOT EXISTS idx_automation_runs_status ON automation_runs(status);
CREATE INDEX IF NOT EXISTS idx_automation_runs_started_at ON automation_runs(started_at);
-- +goose Down
-- Drop automation_runs and automations tables
DROP TABLE IF EXISTS automation_runs CASCADE;
DROP TABLE IF EXISTS automations CASCADE;
+23
View File
@@ -0,0 +1,23 @@
-- +goose Up
-- Create config_entries table
CREATE TABLE IF NOT EXISTS config_entries (
id SERIAL PRIMARY KEY,
section TEXT NOT NULL,
key TEXT NOT NULL,
value TEXT,
type TEXT,
sensitive BOOLEAN NOT NULL DEFAULT false,
description TEXT,
updated_by TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(section, key)
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_config_entries_section ON config_entries(section);
CREATE INDEX IF NOT EXISTS idx_config_entries_key ON config_entries(key);
-- +goose Down
-- Drop config_entries table
DROP TABLE IF EXISTS config_entries CASCADE;
@@ -0,0 +1,28 @@
-- +goose Up
-- Create deployment_records table
CREATE TABLE IF NOT EXISTS deployment_records (
id SERIAL PRIMARY KEY,
service TEXT NOT NULL,
version TEXT NOT NULL,
environment TEXT,
status TEXT NOT NULL,
strategy TEXT,
replicas INTEGER NOT NULL DEFAULT 1,
triggered_by TEXT,
reason TEXT,
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
rollback_to TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_deployment_records_service ON deployment_records(service);
CREATE INDEX IF NOT EXISTS idx_deployment_records_environment ON deployment_records(environment);
CREATE INDEX IF NOT EXISTS idx_deployment_records_status ON deployment_records(status);
CREATE INDEX IF NOT EXISTS idx_deployment_records_created_at ON deployment_records(created_at);
-- +goose Down
-- Drop deployment_records table
DROP TABLE IF EXISTS deployment_records CASCADE;
@@ -0,0 +1,28 @@
-- +goose Up
-- Create chaos_experiment_records table
CREATE TABLE IF NOT EXISTS chaos_experiment_records (
id SERIAL PRIMARY KEY,
external_id TEXT UNIQUE,
name TEXT,
type TEXT,
target TEXT,
status TEXT,
duration_ms BIGINT NOT NULL DEFAULT 0,
probability DOUBLE PRECISION,
amount INTEGER NOT NULL DEFAULT 0,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
finished_at TIMESTAMPTZ,
error TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_chaos_experiment_records_external_id ON chaos_experiment_records(external_id);
CREATE INDEX IF NOT EXISTS idx_chaos_experiment_records_status ON chaos_experiment_records(status);
CREATE INDEX IF NOT EXISTS idx_chaos_experiment_records_target ON chaos_experiment_records(target);
CREATE INDEX IF NOT EXISTS idx_chaos_experiment_records_started_at ON chaos_experiment_records(started_at);
-- +goose Down
-- Drop chaos_experiment_records table
DROP TABLE IF EXISTS chaos_experiment_records CASCADE;
@@ -0,0 +1,14 @@
-- +goose Up
-- Create imsi_allocations table
CREATE TABLE IF NOT EXISTS imsi_allocations (
id SERIAL PRIMARY KEY,
last_imsi BIGINT NOT NULL DEFAULT 0,
min_imsi BIGINT NOT NULL DEFAULT 1,
max_imsi BIGINT NOT NULL DEFAULT 999999999,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- +goose Down
-- Drop imsi_allocations table
DROP TABLE IF EXISTS imsi_allocations CASCADE;
+23
View File
@@ -0,0 +1,23 @@
-- +goose Up
-- Create payment_methods table
CREATE TABLE IF NOT EXISTS payment_methods (
id TEXT PRIMARY KEY,
subscriber_id INTEGER NOT NULL,
gateway_id TEXT,
type TEXT NOT NULL,
customer_id TEXT,
last4 TEXT,
brand TEXT,
expiry_month INTEGER,
expiry_year INTEGER,
is_default BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_payment_methods_subscriber_id ON payment_methods(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_payment_methods_gateway_id ON payment_methods(gateway_id);
-- +goose Down
-- Drop payment_methods table
DROP TABLE IF EXISTS payment_methods CASCADE;
+25
View File
@@ -0,0 +1,25 @@
-- +goose Up
-- Create transactions table
CREATE TABLE IF NOT EXISTS transactions (
id SERIAL PRIMARY KEY,
subscriber_id INTEGER NOT NULL,
transaction_id TEXT NOT NULL,
type TEXT NOT NULL,
amount DOUBLE PRECISION NOT NULL,
currency TEXT NOT NULL,
status TEXT NOT NULL,
description TEXT,
parent_id INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_transactions_subscriber_id ON transactions(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_transactions_transaction_id ON transactions(transaction_id);
CREATE INDEX IF NOT EXISTS idx_transactions_status ON transactions(status);
CREATE INDEX IF NOT EXISTS idx_transactions_created_at ON transactions(created_at);
-- +goose Down
-- Drop transactions table
DROP TABLE IF EXISTS transactions CASCADE;
@@ -0,0 +1,35 @@
-- +goose Up
-- Create notifications table
CREATE TABLE IF NOT EXISTS notifications (
id SERIAL PRIMARY KEY,
subscriber_id INTEGER NOT NULL,
type TEXT NOT NULL,
title TEXT NOT NULL,
message TEXT NOT NULL,
read BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Create alerts table
CREATE TABLE IF NOT EXISTS alerts (
id SERIAL PRIMARY KEY,
type TEXT NOT NULL,
severity TEXT NOT NULL,
message TEXT NOT NULL,
subscriber_id INTEGER,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
resolved BOOLEAN NOT NULL DEFAULT false
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_notifications_subscriber_id ON notifications(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_notifications_read ON notifications(read);
CREATE INDEX IF NOT EXISTS idx_alerts_subscriber_id ON alerts(subscriber_id);
CREATE INDEX IF NOT EXISTS idx_alerts_type ON alerts(type);
CREATE INDEX IF NOT EXISTS idx_alerts_severity ON alerts(severity);
CREATE INDEX IF NOT EXISTS idx_alerts_resolved ON alerts(resolved);
-- +goose Down
-- Drop notifications and alerts tables
DROP TABLE IF EXISTS notifications CASCADE;
DROP TABLE IF EXISTS alerts CASCADE;