mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Refactor EdrOrgSeeder
This commit is contained in:
@@ -164,20 +164,25 @@ export class EdrOrgSeeder {
|
||||
manager: EntityManager,
|
||||
applicationId: string,
|
||||
) {
|
||||
const permissionRepository = manager.getRepository(Permission);
|
||||
|
||||
// Upsert by key so reruns are idempotent; applicationId ties every
|
||||
// permission to the EDR Freight application (also backfills rows that
|
||||
// were previously seeded without the relation).
|
||||
await permissionRepository.upsert(
|
||||
EDR_FREIGHT_PERMISSIONS.map((permission) => ({
|
||||
id: permission.id,
|
||||
key: permission.key,
|
||||
name: { ...permission.name },
|
||||
applicationId,
|
||||
})),
|
||||
{ conflictPaths: { key: true } },
|
||||
);
|
||||
// iam.permissions has TWO unique columns (PK id, UQ key) but ON CONFLICT
|
||||
// can only target one. Seeding a hand-minted id that some older/retired key
|
||||
// already owns in an environment slips past ON CONFLICT (key) and dies on
|
||||
// the PK. The key is the identity every consumer resolves by (positions
|
||||
// seeder maps key -> id at runtime), so ids are left to the column default
|
||||
// and never sent — no id can collide.
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(Permission)
|
||||
.values(
|
||||
EDR_FREIGHT_PERMISSIONS.map((permission) => ({
|
||||
key: permission.key,
|
||||
name: { ...permission.name },
|
||||
applicationId,
|
||||
})),
|
||||
)
|
||||
.orUpdate(["name", "application_id"], ["key"])
|
||||
.execute();
|
||||
|
||||
this.logger.log(
|
||||
`Ensured ${EDR_FREIGHT_PERMISSIONS.length} permissions on application '${EDR_FREIGHT_APPLICATION.key}'`,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { EDR_FREIGHT_PERMISSIONS } from './edr-freight.seed';
|
||||
|
||||
describe('EDR_FREIGHT_PERMISSIONS', () => {
|
||||
// The seeder inserts the whole catalog in one ON CONFLICT (key) DO UPDATE
|
||||
// statement — a duplicated key there is a Postgres 21000 at boot, not a
|
||||
// silent no-op.
|
||||
it('has no duplicate keys', () => {
|
||||
const keys = EDR_FREIGHT_PERMISSIONS.map((permission) => permission.key);
|
||||
const duplicates = [...new Set(keys.filter((key, i) => keys.indexOf(key) !== i))];
|
||||
|
||||
expect(duplicates).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -109,8 +109,12 @@ export const CONTRACT_PERMISSIONS: FreightPermissionSeed[] = [
|
||||
perm('a3000001-0001-4000-8000-00000000001b', 'edr_freight_app:contracts:suspend', 'Suspend / resume a signed contract'),
|
||||
];
|
||||
|
||||
// Existing per-slug view ids are kept as-is: position-type grants reference
|
||||
// them by id, so re-minting would orphan those rows.
|
||||
// Historical ids. EdrOrgSeeder no longer sends them — it upserts on `key` and
|
||||
// lets the column default mint the uuid — so these are kept only as a record of
|
||||
// which ids each environment already holds. A hand-picked id must still never
|
||||
// be recycled from a retired key: `edr_freight_app:rule_engine:truck_types:manage`
|
||||
// owned …001b, and reusing it for transit-agents crashed boot with a PK 23505
|
||||
// on every environment that still had the retired row.
|
||||
const RULE_ENGINE_VIEW_IDS: Record<RuleEngineResourceSlug, string> = {
|
||||
'cargo-types': 'b2000001-0001-4000-8000-000000000001',
|
||||
'container-types': 'b2000001-0001-4000-8000-000000000003',
|
||||
@@ -124,7 +128,7 @@ const RULE_ENGINE_VIEW_IDS: Record<RuleEngineResourceSlug, string> = {
|
||||
rates: 'b2000001-0001-4000-8000-000000000011',
|
||||
'approval-rules': 'b2000001-0001-4000-8000-000000000013',
|
||||
'yard-distances': 'b2000001-0001-4000-8000-000000000018',
|
||||
'transit-agents': 'b2000001-0001-4000-8000-00000000001b',
|
||||
'transit-agents': 'b2000003-0001-4000-8000-000000000001',
|
||||
};
|
||||
|
||||
// CRUD replaces the retired coarse `:manage`. New ids live in a fresh block
|
||||
|
||||
Reference in New Issue
Block a user