Files
xinmi/migrations/versioned/000207_content_action_permissions.up.sql
T

67 lines
3.4 KiB
SQL
Raw Normal View History

-- Split review and delivery without changing identities, memberships or owners.
CREATE TABLE IF NOT EXISTS workbench_content_permission_migrations (
version integer PRIMARY KEY,
changes jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
DO $migration$
DECLARE r record; saved jsonb; before_permissions jsonb; next_permissions jsonb;
mapped_permissions jsonb; source_permissions jsonb; changes jsonb := '[]'::jsonb;
restored boolean;
BEGIN
PERFORM pg_advisory_xact_lock(207, 11905);
IF EXISTS(SELECT 1 FROM workbench_content_permission_migrations WHERE version=207) THEN RETURN; END IF;
LOCK TABLE workbench_access_roles IN SHARE ROW EXCLUSIVE MODE;
FOR r IN SELECT * FROM workbench_access_roles ORDER BY tenant_id,id LOOP
saved := NULL;
IF to_regclass('yawan_legacy_access_mappings') IS NOT NULL THEN
EXECUTE 'SELECT source_spec FROM yawan_legacy_access_mappings
WHERE source_system=$1 AND target_tenant_id=$2 AND entity_key LIKE ''role/%''
AND source_spec->>''id''=$3'
INTO saved USING 'yawan-workbench',r.tenant_id,r.id;
END IF;
before_permissions := r.permissions;
-- Before this split, readers could export and producers could approve/review.
SELECT coalesce(jsonb_agg(p ORDER BY p),'[]'::jsonb) INTO next_permissions FROM (
SELECT DISTINCT p FROM (
SELECT jsonb_array_elements_text(r.permissions) AS p
UNION ALL SELECT 'content.review' WHERE r.permissions ? 'content.write'
UNION ALL SELECT 'content.deliver' WHERE r.permissions ? 'content.read'
) existing
) permissions;
mapped_permissions := NULL;
restored := false;
IF saved IS NOT NULL THEN
source_permissions := saved->'source_permissions';
SELECT coalesce(jsonb_agg(p ORDER BY p),'[]'::jsonb) INTO mapped_permissions
FROM jsonb_array_elements_text(saved->'permissions') p WHERE p NOT LIKE 'content.%';
-- Legacy task GETs required tasks:review; generic read alone granted no task access.
IF source_permissions ? 'tasks:review' OR source_permissions ? 'review' THEN
mapped_permissions := mapped_permissions || '["content.read","content.review"]'::jsonb;
IF source_permissions ? 'tasks:write' OR source_permissions ? 'content:write' THEN
mapped_permissions := mapped_permissions || '"content.write"'::jsonb;
END IF;
IF source_permissions ? 'tasks:deliver' OR source_permissions ? 'content:write' THEN
mapped_permissions := mapped_permissions || '"content.deliver"'::jsonb;
END IF;
END IF;
SELECT coalesce(jsonb_agg(p ORDER BY p),'[]'::jsonb) INTO mapped_permissions
FROM jsonb_array_elements_text(mapped_permissions) p;
-- An edited imported role keeps its current native policy.
IF r.version=1 AND r.name=saved->>'name' AND r.permissions=saved->'permissions' THEN
next_permissions := mapped_permissions;
restored := true;
END IF;
END IF;
IF next_permissions IS DISTINCT FROM before_permissions THEN
UPDATE workbench_access_roles SET permissions=next_permissions,version=version+1,updated_at=now()
WHERE id=r.id AND tenant_id=r.tenant_id;
END IF;
changes := changes || jsonb_build_array(jsonb_build_object(
'role_id',r.id,'tenant_id',r.tenant_id,'before',before_permissions,'after',next_permissions,
'legacy_source_spec',saved,'mapped_permissions',mapped_permissions,'legacy_restored',restored));
END LOOP;
INSERT INTO workbench_content_permission_migrations(version,changes) VALUES(207,changes);
END $migration$;