176 lines
7.3 KiB
PL/PgSQL
176 lines
7.3 KiB
PL/PgSQL
-- Permissions UI cleanup — 2026-05-28
|
|
--
|
|
-- WHAT THIS DOES
|
|
-- Rewrites permissions.name and permissions.category for clarity.
|
|
-- Consolidates 17 categories down to 10. Renames ambiguous entries so
|
|
-- the User Management UI reads cleanly. Does NOT touch permissions.code,
|
|
-- so every existing route gate (backend requirePermission and frontend
|
|
-- Protected page=) and every row in user_permissions keeps working
|
|
-- without any code change or remapping.
|
|
--
|
|
-- WHAT THIS DOES *NOT* DO
|
|
-- No DROP/DELETE of any permission (except in the optional block at the
|
|
-- very bottom — commented out by default). No changes to permissions.code.
|
|
-- No INSERT of new permissions. No changes to other tables.
|
|
--
|
|
-- SAFETY
|
|
-- Wrapped in a transaction. Run end-to-end; if any row count is wrong,
|
|
-- ROLLBACK and inspect. The auth middleware caches the user's loaded
|
|
-- permissions for 60s — after this runs, names refresh on next cache
|
|
-- miss for the admin UI. user_permissions joins by id, so granted
|
|
-- permissions remain granted across renames.
|
|
|
|
BEGIN;
|
|
|
|
------------------------------------------------------------------------
|
|
-- 1. Category consolidation
|
|
------------------------------------------------------------------------
|
|
|
|
-- 1a. Orphan "Pages" (just the Settings page) → Pages/Settings
|
|
UPDATE permissions SET category = 'Pages/Settings'
|
|
WHERE code = 'access:settings';
|
|
|
|
-- 1b. Existing settings:* tab-access permissions stay under a renamed
|
|
-- "Settings Tabs" category (was "Settings") so it reads less ambiguously
|
|
-- next to "Pages/Settings" and "Write Actions".
|
|
UPDATE permissions SET category = 'Settings Tabs'
|
|
WHERE category = 'Settings';
|
|
|
|
-- 1c. Dashboard widget perms keep their codes but get a clearer category name.
|
|
UPDATE permissions SET category = 'Dashboard Widgets'
|
|
WHERE category = 'Dashboard Components';
|
|
|
|
-- 1d. Collapse the 7 single-member "new permission" categories
|
|
-- (Imports, Data, AI, Templates, Images, Audit, ACOT, Dashboard
|
|
-- [the dashboard-server one — distinct from Pages/Dashboard])
|
|
-- into a single "Write Actions" category.
|
|
UPDATE permissions SET category = 'Write Actions'
|
|
WHERE category IN ('Imports', 'Data', 'AI', 'Templates',
|
|
'Images', 'Audit', 'ACOT', 'Dashboard');
|
|
|
|
-- 1e. The "Admin" category (just Show Debug) stays as-is — single member
|
|
-- but conceptually distinct enough that bucketing under Write Actions
|
|
-- would muddy the meaning. Leaving it alone.
|
|
|
|
------------------------------------------------------------------------
|
|
-- 2. Name renames for clarity
|
|
------------------------------------------------------------------------
|
|
|
|
-- 2a. Distinguish "page that lets you do X" from "permission to do X"
|
|
-- by suffixing the page-access permissions with " (page)" where the
|
|
-- name otherwise collides with the corresponding write permission.
|
|
UPDATE permissions SET name = 'Import Products (page)'
|
|
WHERE code = 'access:import';
|
|
|
|
UPDATE permissions SET name = 'Product Editor (page)'
|
|
WHERE code = 'access:product_editor';
|
|
|
|
UPDATE permissions SET name = 'Bulk Edit (page)'
|
|
WHERE code = 'access:bulk_edit';
|
|
|
|
-- 2b. Settings tab-access perms get a uniform "Settings: X Tab" name so
|
|
-- they sort together and read as "what you're seeing access to" not
|
|
-- "the feature itself."
|
|
UPDATE permissions SET name = 'Settings: Data Management Tab'
|
|
WHERE code = 'settings:data_management';
|
|
|
|
UPDATE permissions SET name = 'Settings: Reusable Images Tab'
|
|
WHERE code = 'settings:library_management';
|
|
|
|
UPDATE permissions SET name = 'Settings: AI Prompts Tab'
|
|
WHERE code = 'settings:prompt_management';
|
|
|
|
UPDATE permissions SET name = 'Settings: Templates Tab'
|
|
WHERE code = 'settings:templates';
|
|
|
|
UPDATE permissions SET name = 'Settings: User Management Tab'
|
|
WHERE code = 'settings:user_management';
|
|
|
|
UPDATE permissions SET name = 'Settings: Audit Log Tab'
|
|
WHERE code = 'settings:audit_log';
|
|
|
|
UPDATE permissions SET name = 'Settings: Global Tab'
|
|
WHERE code = 'settings:global';
|
|
|
|
UPDATE permissions SET name = 'Settings: Products Tab'
|
|
WHERE code = 'settings:products';
|
|
|
|
UPDATE permissions SET name = 'Settings: Vendors Tab'
|
|
WHERE code = 'settings:vendors';
|
|
|
|
-- 2c. Write-action perms get verb-leading names so it's obvious what
|
|
-- granting them actually allows.
|
|
UPDATE permissions
|
|
SET name = 'Product Import: Upload & Submit',
|
|
description = 'Allows POST/PUT/DELETE on /api/import — image uploads, '
|
|
|| 'product submission, deletions, and generate-upc. Does NOT '
|
|
|| 'grant access to the Import Products page (access:import).'
|
|
WHERE code = 'product_import';
|
|
|
|
UPDATE permissions
|
|
SET name = 'Data Management: Run Operations',
|
|
description = 'Allows POST/PUT/DELETE on /api/csv — CSV operations, '
|
|
|| 'full updates, full resets. Does NOT grant access to the '
|
|
|| 'Data Management settings tab (settings:data_management).'
|
|
WHERE code = 'data_management';
|
|
|
|
UPDATE permissions
|
|
SET name = 'Reusable Images: Upload & Delete',
|
|
description = 'Allows uploads and deletions on /api/reusable-images. '
|
|
|| 'Distinct from product_import (which gates uploads inside '
|
|
|| 'the product import flow).'
|
|
WHERE code = 'image_admin';
|
|
|
|
UPDATE permissions
|
|
SET name = 'Templates: Create & Edit',
|
|
description = 'Allows POST/PUT/DELETE on /api/templates.'
|
|
WHERE code = 'templates_write';
|
|
|
|
UPDATE permissions
|
|
SET name = 'AI: Edit Prompts & Validation',
|
|
description = 'Allows write access to /api/ai-prompts and /api/ai-validation.'
|
|
WHERE code = 'ai_admin';
|
|
|
|
UPDATE permissions
|
|
SET name = 'Klaviyo: Clear Cache',
|
|
description = 'Allows POST /api/klaviyo/events/clearCache.'
|
|
WHERE code = 'klaviyo_admin';
|
|
|
|
UPDATE permissions
|
|
SET name = 'Meta: Mutate Campaigns',
|
|
description = 'Allows PATCH/POST on /api/meta/campaigns/*.'
|
|
WHERE code = 'meta_write';
|
|
|
|
------------------------------------------------------------------------
|
|
-- 3. Verification — should all return non-zero
|
|
------------------------------------------------------------------------
|
|
-- Uncomment to inspect before commit:
|
|
-- SELECT category, COUNT(*) FROM permissions GROUP BY category ORDER BY category;
|
|
-- SELECT code, name, category FROM permissions
|
|
-- WHERE category IN ('Write Actions', 'Settings Tabs', 'Pages/Settings')
|
|
-- ORDER BY category, name;
|
|
|
|
COMMIT;
|
|
|
|
------------------------------------------------------------------------
|
|
-- 4. OPTIONAL — drop unused "Reserved for future" codes
|
|
------------------------------------------------------------------------
|
|
-- These five codes are referenced only in their own description ("Reserved
|
|
-- for…") and appear in NO route gate, NO Protected page=, and NO frontend
|
|
-- permissions.includes() check. Verified 2026-05-28.
|
|
--
|
|
-- Run this block separately if you want to drop them. user_permissions has
|
|
-- ON DELETE CASCADE on permission_id is NOT configured (only on user_id),
|
|
-- so we must clear user_permissions rows first.
|
|
--
|
|
-- BEGIN;
|
|
-- DELETE FROM user_permissions
|
|
-- WHERE permission_id IN (SELECT id FROM permissions
|
|
-- WHERE code IN ('klaviyo_write', 'google_write',
|
|
-- 'typeform_write', 'acot_admin',
|
|
-- 'audit_read'));
|
|
-- DELETE FROM permissions
|
|
-- WHERE code IN ('klaviyo_write', 'google_write', 'typeform_write',
|
|
-- 'acot_admin', 'audit_read');
|
|
-- COMMIT;
|