dragonflight/services/mam-api/src/db/migrations/026-project-access.sql

31 lines
1.3 KiB
MySQL
Raw Normal View History

-- Migration 026 — per-project access grants (RBAC v2).
--
-- v1 auth is flat: any logged-in user can do everything. This adds per-project
-- scoping. A grant targets either a user or a group (polymorphic subject) and
-- carries a level: 'view' (read-only) or 'edit' (read-write). Admins bypass all
-- of this in code (authz.js) and need no rows here.
--
-- subject_id is intentionally NOT a foreign key — it points at either users.id
-- or groups.id depending on subject_type. Rows are cleaned up when the project
-- is deleted (FK cascade). A deleted user/group leaves an orphan row that
-- resolves to nobody (harmless); a later sweep can prune them if desired.
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'access_level') THEN
CREATE TYPE access_level AS ENUM ('view', 'edit');
END IF;
END $$;
CREATE TABLE IF NOT EXISTS project_access (
project_id UUID NOT NULL REFERENCES projects ON DELETE CASCADE,
subject_type TEXT NOT NULL CHECK (subject_type IN ('user', 'group')),
subject_id UUID NOT NULL,
level access_level NOT NULL DEFAULT 'view',
granted_by UUID REFERENCES users ON DELETE SET NULL,
granted_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (project_id, subject_type, subject_id)
);
CREATE INDEX IF NOT EXISTS idx_project_access_subject
ON project_access (subject_type, subject_id);