166 lines
6.2 KiB
PL/PgSQL
166 lines
6.2 KiB
PL/PgSQL
BEGIN;
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
-- Drop all managed tables to ensure clean rebuild
|
|
DROP TABLE IF EXISTS auth_sync_state CASCADE;
|
|
DROP TABLE IF EXISTS user_scope_permissions CASCADE;
|
|
DROP TABLE IF EXISTS permission_group_permissions CASCADE;
|
|
DROP TABLE IF EXISTS permission_group_members CASCADE;
|
|
DROP TABLE IF EXISTS permission_groups CASCADE;
|
|
DROP TABLE IF EXISTS modules CASCADE;
|
|
DROP TABLE IF EXISTS systems CASCADE;
|
|
DROP TABLE IF EXISTS sites CASCADE;
|
|
DROP TABLE IF EXISTS companies CASCADE;
|
|
DROP TABLE IF EXISTS users CASCADE;
|
|
DROP TABLE IF EXISTS api_clients CASCADE;
|
|
-- remove legacy table if present
|
|
DROP TABLE IF EXISTS permissions CASCADE;
|
|
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_sub TEXT NOT NULL UNIQUE,
|
|
idp_user_id VARCHAR(128),
|
|
username TEXT UNIQUE,
|
|
email TEXT UNIQUE,
|
|
display_name TEXT,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE auth_sync_state (
|
|
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
|
last_synced_at TIMESTAMPTZ,
|
|
source_version TEXT,
|
|
last_error TEXT,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE companies (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
company_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE sites (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
site_key TEXT NOT NULL UNIQUE,
|
|
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE systems (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
system_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE modules (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
system_key TEXT NOT NULL REFERENCES systems(system_key) ON DELETE CASCADE,
|
|
module_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- direct permission table retained only for compatibility
|
|
CREATE TABLE user_scope_permissions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
module_id UUID NOT NULL REFERENCES modules(id) ON DELETE CASCADE,
|
|
action VARCHAR(32) NOT NULL,
|
|
scope_type VARCHAR(16) NOT NULL,
|
|
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
|
|
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT user_scope_permissions_scope_check
|
|
CHECK (scope_type = 'site' AND site_id IS NOT NULL AND company_id IS NULL),
|
|
CONSTRAINT user_scope_permissions_action_check
|
|
CHECK (action IN ('view', 'edit'))
|
|
);
|
|
|
|
CREATE TABLE permission_groups (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE permission_group_members (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_id UUID NOT NULL REFERENCES permission_groups(id) ON DELETE CASCADE,
|
|
user_sub TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uq_permission_group_members_group_sub UNIQUE (group_id, user_sub)
|
|
);
|
|
|
|
CREATE TABLE permission_group_permissions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_id UUID NOT NULL REFERENCES permission_groups(id) ON DELETE CASCADE,
|
|
system TEXT NOT NULL,
|
|
module TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
scope_type TEXT NOT NULL,
|
|
scope_id TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT permission_group_permissions_scope_check CHECK (scope_type = 'site'),
|
|
CONSTRAINT permission_group_permissions_action_check CHECK (action IN ('view', 'edit')),
|
|
CONSTRAINT uq_pgp_group_rule UNIQUE (group_id, system, module, action, scope_type, scope_id)
|
|
);
|
|
|
|
CREATE TABLE api_clients (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
client_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
api_key_hash TEXT NOT NULL,
|
|
allowed_origins JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
allowed_ips JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
allowed_paths JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
rate_limit_per_min INTEGER,
|
|
expires_at TIMESTAMPTZ,
|
|
last_used_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
INSERT INTO systems (system_key, name, status)
|
|
VALUES ('member', 'Member Center', 'active')
|
|
ON CONFLICT (system_key) DO NOTHING;
|
|
|
|
CREATE INDEX idx_users_user_sub ON users(user_sub);
|
|
CREATE INDEX idx_users_username ON users(username);
|
|
CREATE INDEX idx_sites_company_id ON sites(company_id);
|
|
CREATE INDEX idx_usp_user_id ON user_scope_permissions(user_id);
|
|
CREATE INDEX idx_usp_module_id ON user_scope_permissions(module_id);
|
|
CREATE INDEX idx_usp_site_id ON user_scope_permissions(site_id);
|
|
CREATE UNIQUE INDEX uq_usp_site
|
|
ON user_scope_permissions(user_id, module_id, action, scope_type, site_id);
|
|
CREATE INDEX idx_pgm_group_id ON permission_group_members(group_id);
|
|
CREATE INDEX idx_pgm_user_sub ON permission_group_members(user_sub);
|
|
CREATE INDEX idx_pgp_group_id ON permission_group_permissions(group_id);
|
|
CREATE INDEX idx_pgp_scope_site ON permission_group_permissions(scope_id);
|
|
CREATE INDEX idx_api_clients_status ON api_clients(status);
|
|
CREATE INDEX idx_api_clients_expires_at ON api_clients(expires_at);
|
|
CREATE INDEX idx_systems_system_key ON systems(system_key);
|
|
CREATE INDEX idx_modules_system_key ON modules(system_key);
|
|
CREATE INDEX idx_modules_module_key ON modules(module_key);
|
|
|
|
COMMIT;
|