177 lines
6.0 KiB
PL/PgSQL
177 lines
6.0 KiB
PL/PgSQL
-- ============================================================================
|
|
-- RBAC Schema: Roles Table
|
|
-- Role-Based Access Control for Trading Platform SaaS
|
|
-- ============================================================================
|
|
|
|
-- Create RBAC schema if not exists
|
|
CREATE SCHEMA IF NOT EXISTS rbac;
|
|
|
|
-- Grant usage
|
|
GRANT USAGE ON SCHEMA rbac TO trading_user;
|
|
|
|
-- ============================================================================
|
|
-- ROLES TABLE
|
|
-- Defines roles within a tenant organization
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS rbac.roles (
|
|
-- Primary key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Tenant relationship (multi-tenancy)
|
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Role information
|
|
name VARCHAR(100) NOT NULL,
|
|
slug VARCHAR(100) NOT NULL,
|
|
description TEXT,
|
|
|
|
-- Role type: system (predefined) or custom (tenant-created)
|
|
role_type VARCHAR(20) NOT NULL DEFAULT 'custom'
|
|
CHECK (role_type IN ('system', 'custom')),
|
|
|
|
-- Hierarchy level (lower = more permissions, 0 = super admin)
|
|
hierarchy_level INTEGER NOT NULL DEFAULT 100,
|
|
|
|
-- Status
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
|
|
-- Role settings (JSON for extensibility)
|
|
settings JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
|
|
-- Audit fields
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES users.users(id),
|
|
updated_by UUID REFERENCES users.users(id),
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_roles_tenant_slug UNIQUE (tenant_id, slug),
|
|
CONSTRAINT uq_roles_tenant_name UNIQUE (tenant_id, name)
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- INDEXES
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_roles_tenant_id ON rbac.roles(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_roles_slug ON rbac.roles(slug);
|
|
CREATE INDEX IF NOT EXISTS idx_roles_role_type ON rbac.roles(role_type);
|
|
CREATE INDEX IF NOT EXISTS idx_roles_is_active ON rbac.roles(is_active);
|
|
CREATE INDEX IF NOT EXISTS idx_roles_hierarchy ON rbac.roles(tenant_id, hierarchy_level);
|
|
|
|
-- ============================================================================
|
|
-- ROW LEVEL SECURITY
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE rbac.roles ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Policy: Users can only see roles in their tenant
|
|
CREATE POLICY roles_tenant_isolation ON rbac.roles
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- ============================================================================
|
|
-- TRIGGERS
|
|
-- ============================================================================
|
|
|
|
-- Auto-update updated_at timestamp
|
|
CREATE OR REPLACE FUNCTION rbac.update_roles_timestamp()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_roles_updated_at
|
|
BEFORE UPDATE ON rbac.roles
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION rbac.update_roles_timestamp();
|
|
|
|
-- ============================================================================
|
|
-- DEFAULT SYSTEM ROLES (inserted per tenant)
|
|
-- These will be created when a new tenant is created
|
|
-- ============================================================================
|
|
|
|
-- Function to create default roles for a tenant
|
|
CREATE OR REPLACE FUNCTION rbac.create_default_roles(p_tenant_id UUID, p_owner_id UUID)
|
|
RETURNS void AS $$
|
|
BEGIN
|
|
-- Owner role (highest level)
|
|
INSERT INTO rbac.roles (tenant_id, name, slug, description, role_type, hierarchy_level, created_by)
|
|
VALUES (
|
|
p_tenant_id,
|
|
'Owner',
|
|
'owner',
|
|
'Full access to all features and settings. Can manage billing and delete organization.',
|
|
'system',
|
|
0,
|
|
p_owner_id
|
|
);
|
|
|
|
-- Admin role
|
|
INSERT INTO rbac.roles (tenant_id, name, slug, description, role_type, hierarchy_level, created_by)
|
|
VALUES (
|
|
p_tenant_id,
|
|
'Admin',
|
|
'admin',
|
|
'Administrative access. Can manage users, roles, and most settings.',
|
|
'system',
|
|
10,
|
|
p_owner_id
|
|
);
|
|
|
|
-- Manager role
|
|
INSERT INTO rbac.roles (tenant_id, name, slug, description, role_type, hierarchy_level, created_by)
|
|
VALUES (
|
|
p_tenant_id,
|
|
'Manager',
|
|
'manager',
|
|
'Can manage team members and view reports.',
|
|
'system',
|
|
50,
|
|
p_owner_id
|
|
);
|
|
|
|
-- Member role
|
|
INSERT INTO rbac.roles (tenant_id, name, slug, description, role_type, hierarchy_level, created_by)
|
|
VALUES (
|
|
p_tenant_id,
|
|
'Member',
|
|
'member',
|
|
'Standard user access. Can use platform features.',
|
|
'system',
|
|
100,
|
|
p_owner_id
|
|
);
|
|
|
|
-- Viewer role (read-only)
|
|
INSERT INTO rbac.roles (tenant_id, name, slug, description, role_type, hierarchy_level, created_by)
|
|
VALUES (
|
|
p_tenant_id,
|
|
'Viewer',
|
|
'viewer',
|
|
'Read-only access. Can view but not modify.',
|
|
'system',
|
|
200,
|
|
p_owner_id
|
|
);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ============================================================================
|
|
-- GRANTS
|
|
-- ============================================================================
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON rbac.roles TO trading_user;
|
|
|
|
-- ============================================================================
|
|
-- COMMENTS
|
|
-- ============================================================================
|
|
|
|
COMMENT ON TABLE rbac.roles IS 'Roles for Role-Based Access Control within tenant organizations';
|
|
COMMENT ON COLUMN rbac.roles.role_type IS 'system = predefined roles, custom = tenant-created roles';
|
|
COMMENT ON COLUMN rbac.roles.hierarchy_level IS 'Lower value = higher permissions. Owner=0, Admin=10, etc.';
|
|
COMMENT ON COLUMN rbac.roles.settings IS 'JSON settings for role customization';
|