Files
Final_PGA/infra/init/001-control.sql
2026-03-19 18:00:46 +07:00

138 lines
4.1 KiB
SQL

create extension if not exists "pgcrypto";
create table if not exists users (
id uuid primary key default gen_random_uuid(),
username text unique not null,
password_hash text not null,
is_active boolean not null default true,
is_locked boolean not null default false,
created_at timestamptz not null default now()
);
create table if not exists roles (
id uuid primary key default gen_random_uuid(),
slug text unique not null,
name text not null,
description text not null default '',
created_at timestamptz not null default now()
);
create table if not exists permissions (
id uuid primary key default gen_random_uuid(),
resource text not null,
action text not null,
unique (resource, action)
);
create table if not exists role_permissions (
role_id uuid not null references roles(id) on delete cascade,
permission_id uuid not null references permissions(id) on delete cascade,
scope_type text not null default 'global',
scope_value text null
);
create unique index if not exists role_permissions_scope_uidx
on role_permissions (role_id, permission_id, scope_type, coalesce(scope_value, ''));
create table if not exists user_roles (
user_id uuid not null references users(id) on delete cascade,
role_id uuid not null references roles(id) on delete cascade,
primary key (user_id, role_id)
);
create table if not exists resource_groups (
id uuid primary key default gen_random_uuid(),
slug text unique not null,
name text not null
);
create table if not exists resource_group_tables (
group_id uuid not null references resource_groups(id) on delete cascade,
table_name text not null,
primary key (group_id, table_name)
);
create table if not exists sessions (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references users(id) on delete cascade,
token_hash text not null unique,
expires_at timestamptz not null,
ip text null,
user_agent text null,
created_at timestamptz not null default now()
);
create table if not exists audit_events (
id uuid primary key default gen_random_uuid(),
created_at timestamptz not null default now(),
actor_user_id uuid null references users(id) on delete set null,
action text not null,
resource_type text not null,
resource_name text null,
group_id text null,
target_connection_id text null,
sql_text_masked text null,
payload_before jsonb null,
payload_after jsonb null,
ip text null,
user_agent text null,
status text not null
);
create table if not exists db_connections (
id uuid primary key default gen_random_uuid(),
name text not null,
host text not null,
port integer not null,
database_name text not null,
is_default boolean not null default false,
created_at timestamptz not null default now()
);
insert into permissions (resource, action) values
('database', 'read'),
('database', 'write'),
('database', 'delete'),
('database', 'schema_change'),
('group', 'read'),
('group', 'write'),
('group', 'delete'),
('group', 'schema_change'),
('table', 'read'),
('table', 'write'),
('table', 'delete'),
('table', 'schema_change'),
('sql_console', 'execute_sql'),
('logs', 'view_logs'),
('users', 'manage_users'),
('roles', 'manage_roles'),
('audit', 'read')
on conflict do nothing;
insert into roles (slug, name, description) values
('root', 'Root', 'Full access to the control plane'),
('folder_admin', 'Folder Admin', 'Admin for selected groups'),
('user', 'User', 'Read-only or restricted access')
on conflict do nothing;
insert into resource_groups (slug, name) values
('finance', 'Finance'),
('users', 'Users'),
('logs', 'Logs')
on conflict do nothing;
insert into resource_group_tables (group_id, table_name)
select g.id, x.table_name
from (
values
('finance', 'finance__invoices'),
('users', 'users__accounts'),
('logs', 'logs__events')
) as x(group_slug, table_name)
join resource_groups g on g.slug = x.group_slug
on conflict do nothing;
insert into db_connections (name, host, port, database_name, is_default)
values ('Default Target DB', 'postgres-target', 5432, 'appdb', true)
on conflict do nothing;