72129af0bd
- remove permission centric mode
- finalize migration drop all tables with permissions
- ensure roles are ENUM (owner is always displayed first)
73 lines
4.1 KiB
SQL
73 lines
4.1 KiB
SQL
-- ════════════════════════════════════════════════════════════════════════════
|
|
-- Cleanup #1: storage.role_grants.role — TEXT → storage.grant_role ENUM
|
|
-- ════════════════════════════════════════════════════════════════════════════
|
|
-- D-Prep shipped `role_grants.role` as TEXT + CHECK constraint. Promoting it
|
|
-- to a native PostgreSQL ENUM gives us three things at once:
|
|
--
|
|
-- 1. Index-driven sort by role strength. The ENUM values are declared in
|
|
-- strength order — owner first, viewer last. `ORDER BY role ASC` then
|
|
-- yields the UX-mandated "strongest first" ordering (Owner → Editor →
|
|
-- Contributor → Commenter → Viewer) without a CASE expression. The
|
|
-- `idx_role_grants_subject` / `idx_role_grants_resource` indexes can be
|
|
-- extended (or composite-augmented) with the role column for index-only
|
|
-- ordered scans.
|
|
--
|
|
-- 2. Type-level safety. The CHECK constraint goes away; invalid roles fail
|
|
-- at the column type, not at row insertion. One contract instead of two
|
|
-- (column type AND check constraint).
|
|
--
|
|
-- 3. Cleaner query shape. Every listing query that used the strength CASE
|
|
-- becomes a plain `ORDER BY role` after this migration.
|
|
--
|
|
-- Trade-off accepted: PostgreSQL ENUMs allow ADD VALUE (with BEFORE / AFTER
|
|
-- positional anchors) and RENAME VALUE, but not DROP VALUE or arbitrary
|
|
-- reorder. The OxiCloud role roster is intentionally stable — new roles get
|
|
-- appended, none get reordered or removed. Confirmed with Ed.
|
|
--
|
|
-- This migration must run BEFORE the access_grants drop, since it's purely
|
|
-- about role_grants.role.
|
|
|
|
-- ── 1. Create the ENUM type ────────────────────────────────────────────────
|
|
-- Declaration order = sort order. Strongest first so `ORDER BY role ASC`
|
|
-- matches the UX requirement (max permission → least permission).
|
|
|
|
CREATE TYPE storage.grant_role AS ENUM (
|
|
'owner', -- ordinal 0, sorts first
|
|
'editor', -- ordinal 1
|
|
'contributor', -- ordinal 2
|
|
'commenter', -- ordinal 3
|
|
'viewer' -- ordinal 4, sorts last
|
|
);
|
|
|
|
COMMENT ON TYPE storage.grant_role IS
|
|
'Role-keyed grant strength. Declaration order is sort order: ORDER BY '
|
|
'role ASC yields owner → viewer (strongest → weakest), matching the '
|
|
'share-dialog and shared-with-me UX. Adding a new role is ALTER TYPE '
|
|
'ADD VALUE; renaming is ALTER TYPE RENAME VALUE. Dropping or reordering '
|
|
'is not supported — adjust the roster only by append.';
|
|
|
|
|
|
-- ── 2. Drop the redundant CHECK constraint ─────────────────────────────────
|
|
-- The inline CHECK on role_grants.role was auto-named
|
|
-- `role_grants_role_check` by PostgreSQL. Drop it before the type swap —
|
|
-- the ENUM now enforces the same invariant at the column level.
|
|
|
|
ALTER TABLE storage.role_grants
|
|
DROP CONSTRAINT IF EXISTS role_grants_role_check;
|
|
|
|
|
|
-- ── 3. Convert role TEXT → storage.grant_role ──────────────────────────────
|
|
-- USING cast: text values are guaranteed to be one of the five valid labels
|
|
-- (the dropped CHECK enforced this; the D-Prep backfill only produced these
|
|
-- five values). If a stray value slipped through, the cast errors out and
|
|
-- the migration aborts — preferable to silently coercing.
|
|
|
|
ALTER TABLE storage.role_grants
|
|
ALTER COLUMN role TYPE storage.grant_role
|
|
USING role::storage.grant_role;
|
|
|
|
COMMENT ON COLUMN storage.role_grants.role IS
|
|
'One of owner / editor / contributor / commenter / viewer. Expanded to '
|
|
'a Permission bundle by the in-code role_bundle() function at engine '
|
|
'read time. Sort order matches declaration order in storage.grant_role.';
|