140 lines
4.9 KiB
PL/PgSQL
140 lines
4.9 KiB
PL/PgSQL
BEGIN;
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'record_status') THEN
|
|
CREATE TYPE record_status AS ENUM ('active','inactive');
|
|
END IF;
|
|
END
|
|
$$;
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
authentik_sub TEXT NOT NULL UNIQUE,
|
|
authentik_user_id INTEGER,
|
|
email TEXT UNIQUE,
|
|
display_name TEXT,
|
|
status record_status 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 IF NOT EXISTS companies (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
company_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status record_status NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS systems (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
system_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status record_status NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS modules (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
module_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status record_status NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS 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 record_status NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'scope_type') THEN
|
|
CREATE TYPE scope_type AS ENUM ('company','site');
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'permission_action') THEN
|
|
CREATE TYPE permission_action AS ENUM ('view','create','update','delete','manage');
|
|
END IF;
|
|
END
|
|
$$;
|
|
|
|
CREATE TABLE IF NOT EXISTS 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 permission_action NOT NULL,
|
|
scope_type scope_type 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()
|
|
);
|
|
|
|
ALTER TABLE user_scope_permissions DROP CONSTRAINT IF EXISTS user_scope_permissions_check;
|
|
ALTER TABLE user_scope_permissions
|
|
ADD CONSTRAINT user_scope_permissions_check
|
|
CHECK (
|
|
((scope_type = 'company' AND company_id IS NOT NULL AND site_id IS NULL)
|
|
OR (scope_type = 'site' AND site_id IS NOT NULL AND company_id IS NULL))
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_usp_company
|
|
ON user_scope_permissions(user_id, module_id, action, scope_type, company_id)
|
|
WHERE scope_type = 'company';
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_usp_site
|
|
ON user_scope_permissions(user_id, module_id, action, scope_type, site_id)
|
|
WHERE scope_type = 'site';
|
|
|
|
CREATE TABLE IF NOT EXISTS permission_groups (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status record_status NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS permission_group_members (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
group_id UUID NOT NULL REFERENCES permission_groups(id) ON DELETE CASCADE,
|
|
authentik_sub TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
CONSTRAINT uq_permission_group_members_group_sub UNIQUE (group_id, authentik_sub)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS 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()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_pgp_group_rule
|
|
ON permission_group_permissions(group_id, system, module, action, scope_type, scope_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_users_authentik_sub ON users(authentik_sub);
|
|
CREATE INDEX IF NOT EXISTS idx_sites_company_id ON sites(company_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usp_user_id ON user_scope_permissions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usp_module_id ON user_scope_permissions(module_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usp_company_id ON user_scope_permissions(company_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usp_site_id ON user_scope_permissions(site_id);
|
|
|
|
COMMIT;
|