mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
Position types holding only an action key are denied by their module's class-level view guard, so grant the matching <module>:view alongside every action key a type already holds.
120 lines
5.7 KiB
PL/PgSQL
120 lines
5.7 KiB
PL/PgSQL
-- Position-type grant mapping for the granular permission system rollout.
|
|
-- Grants the NEW granular keys to every hand-curated position type that holds
|
|
-- the old broad key whose routes the new keys took over. Idempotent (unique
|
|
-- constraint on (position_type_id, permission_id) + ON CONFLICT DO NOTHING).
|
|
--
|
|
-- PREREQUISITE: run the seeded API once first (SEED_EDR_ORG=true) so
|
|
-- EdrOrgSeeder has created the new permission rows this script references.
|
|
-- Running it too early is not destructive but silently under-applies: keys that
|
|
-- do not exist yet simply match nothing (measured: 11 of 42 rows land pre-seed,
|
|
-- because invoices:view/export and payments:view already exist on dev). Re-run
|
|
-- after seeding — it is safe to run any number of times.
|
|
--
|
|
-- Verified 2026-08-07 on a virgin restore of the live dev DB: seeded boot, then
|
|
-- this script → 42 rows inserted, second run → 0 rows, final per-key grant
|
|
-- counts identical to the reference environment. Per-user API probes across 20
|
|
-- departmental test accounts confirm the keys resolve through /me and gate
|
|
-- routes correctly.
|
|
|
|
BEGIN;
|
|
|
|
-- Helper shape used throughout:
|
|
-- holders of <old key> => also grant <new keys>
|
|
|
|
-- 1. bookings:view holders => dashboard/read keys that replaced blanket access
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pnew.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pold ON pold.id = ptp.permission_id
|
|
AND pold.key = 'edr_freight_app:bookings:view'
|
|
JOIN iam.permissions pnew ON pnew.key IN (
|
|
'edr_freight_app:overview:view',
|
|
'edr_freight_app:reports:view',
|
|
'edr_freight_app:invoices:view',
|
|
'edr_freight_app:invoices:export',
|
|
'edr_freight_app:payments:view'
|
|
)
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 2. train_scheduling:update holders => the write actions split out of it
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pnew.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pold ON pold.id = ptp.permission_id
|
|
AND pold.key = 'edr_freight_app:train_scheduling:update'
|
|
JOIN iam.permissions pnew ON pnew.key IN (
|
|
'edr_freight_app:train_scheduling:dispatch',
|
|
'edr_freight_app:train_scheduling:mark_paid',
|
|
'edr_freight_app:train_scheduling:expire_booking'
|
|
)
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 3. GL Djibouti clearance holders => final-invoice raise + confirm
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pnew.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pold ON pold.id = ptp.permission_id
|
|
AND pold.key = 'edr_freight_app:contracts:clearance_dj_actions'
|
|
JOIN iam.permissions pnew ON pnew.key IN (
|
|
'edr_freight_app:contracts:final_invoice_raise',
|
|
'edr_freight_app:contracts:final_invoice_confirm'
|
|
)
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 4. GL Ethiopia clearance holders => final-invoice confirm
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pnew.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pold ON pold.id = ptp.permission_id
|
|
AND pold.key = 'edr_freight_app:contracts:clearance_et_actions'
|
|
JOIN iam.permissions pnew ON pnew.key = 'edr_freight_app:contracts:final_invoice_confirm'
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 5. Contract-intake holders (any staff_accept flavour) => edit_document
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pnew.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pold ON pold.id = ptp.permission_id
|
|
AND pold.key IN (
|
|
'edr_freight_app:bookings:staff_accept',
|
|
'edr_freight_app:contracts:staff_accept:bulk',
|
|
'edr_freight_app:contracts:staff_accept:container'
|
|
)
|
|
JOIN iam.permissions pnew ON pnew.key = 'edr_freight_app:contracts:edit_document'
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 6. Support inbox ownership (decision 2026-08-07): marketing department types
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT pt.id, p.id
|
|
FROM iam.position_types pt
|
|
CROSS JOIN iam.permissions p
|
|
WHERE (pt.name::text ILIKE '%marketing%' OR pt.key ILIKE '%marketing%')
|
|
AND p.key IN (
|
|
'edr_freight_app:support:agent_view',
|
|
'edr_freight_app:support:agent_send'
|
|
)
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
-- 7. Companion view keys.
|
|
-- Most freight controllers carry a class-level `<module>:view` guard, and Nest
|
|
-- runs class AND method guards — so a type holding only `<module>:<action>` is
|
|
-- denied before the action key is ever checked. Grant the module's view key
|
|
-- alongside every action key the type already holds. View-only, so it widens
|
|
-- reads within a module the type already operates in, never across modules.
|
|
INSERT INTO iam.position_type_permissions (position_type_id, permission_id)
|
|
SELECT DISTINCT ptp.position_type_id, pview.id
|
|
FROM iam.position_type_permissions ptp
|
|
JOIN iam.permissions pact ON pact.id = ptp.permission_id
|
|
AND pact.key LIKE 'edr_freight_app:%'
|
|
JOIN iam.permissions pview ON pview.key = regexp_replace(pact.key, ':[^:]+$', ':view')
|
|
ON CONFLICT (position_type_id, permission_id) DO NOTHING;
|
|
|
|
COMMIT;
|
|
|
|
-- Verification: expected non-zero counts per new key after running.
|
|
-- SELECT p.key, count(*) FROM iam.position_type_permissions ptp
|
|
-- JOIN iam.permissions p ON p.id = ptp.permission_id
|
|
-- WHERE p.key IN ('edr_freight_app:overview:view','edr_freight_app:support:agent_view',
|
|
-- 'edr_freight_app:train_scheduling:dispatch','edr_freight_app:contracts:final_invoice_raise')
|
|
-- GROUP BY p.key;
|