Merge pull request #972 from Tria-plc/freight/nati-1

IAM Seeder centralized
This commit is contained in:
Nathnael Wondisha
2026-07-27 14:11:16 +03:00
committed by GitHub
18 changed files with 1901 additions and 9 deletions

View File

@@ -42,8 +42,17 @@ JWT_REFRESH_TOKEN_EXPIRES=7d
# IAM seed defaults (used by @tria-plc/iamapi-common on first boot)
SUPER_ADMIN_EMAIL=superadmin@tria.com
SUPER_ADMIN_PHONE=
# Super-admin password. Falls back to DEFAULT_PASSWORD when empty.
SUPER_ADMIN_DEFAULT_PASSWORD=
DEFAULT_PASSWORD=password@tria
# IAM baseline shared with edr-passenger-api (roles, IAM app + permissions,
# position types, organization types + default units, org/unit settings, super
# admin). Replaces the seeder that shipped inside @tria-plc/iamapi-common — see
# packages/iam-seed. Seeds by DEFAULT when unset; every write is insert-only.
# Set to false to opt out.
SEED_IAM_BASELINE=true
# Freight org + staff (bookings / rule-engine IAM)
SEED_EDR_ORG=true
SEED_FREIGHT_STAFF=true

View File

@@ -35,12 +35,12 @@
"iam:migration:run": "pnpm run iam:typeorm:cli migration:run",
"iam:migration:revert": "pnpm run iam:typeorm:cli migration:revert",
"iam:migration:show": "pnpm run iam:typeorm:cli migration:show",
"iam:seed:run": "cross-env APP_MODULE_PATH=./dist/app.module dotenv -- node ./node_modules/@tria-plc/iamapi-common/dist/db/seed.cli.js",
"migrate": "ts-node -r tsconfig-paths/register src/scripts/run-migrations.ts",
"script": "ts-node -r tsconfig-paths/register src/scripts/main.ts"
},
"dependencies": {
"@edr/api-common": "workspace:*",
"@edr/iam-seed": "workspace:*",
"@edr/payment-providers": "workspace:*",
"@edr/types": "workspace:*",
"@golevelup/nestjs-rabbitmq": "^5.5.0",

View File

@@ -12,7 +12,8 @@ import {
ensurePostgresSchemas,
APPLICATION_SEARCH_PATH,
} from "./config/ensure-postgres-schemas";
import { IamModule, DataSeeder } from "@tria-plc/iamapi-common";
import { IamBaselineSeeder, IamSeedModule } from "@edr/iam-seed";
import { IamModule } from "@tria-plc/iamapi-common";
import { SharedAuthModule } from "@tria-plc/api-common/modules/auth/shared-auth.module";
import appConfig from "./config/app.config";
@@ -153,6 +154,18 @@ import { LoggerMiddleware } from "./logger.middleware";
applications: [EDR_FREIGHT_APPLICATION],
permissions: EDR_FREIGHT_PERMISSIONS,
}),
// Replaces the package's DataSeeder. Shared with edr-passenger-api, which
// seeds the same `iam` schema — see packages/iam-seed.
IamSeedModule.forRoot({
superAdmin: {
username: "superadmin",
name: { am: "ሱፐር አድሚን", en: "Super Admin" },
roleKey: "super_admin",
organizationKey: "edr_freight",
unitKey: "edr_freight_app",
fallbackEmail: "superadmin@tria.com",
},
}),
BookingsModule,
ContractsModule,
SignaturesModule,
@@ -231,7 +244,7 @@ import { LoggerMiddleware } from "./logger.middleware";
})
export class AppModule implements OnApplicationBootstrap {
constructor(
private readonly seeder: DataSeeder,
private readonly iamBaselineSeeder: IamBaselineSeeder,
private readonly edrOrgSeeder: EdrOrgSeeder,
private readonly freightPositionsSeeder: FreightPositionsSeeder,
private readonly fileUploadSettingsSeeder: FileUploadSettingsSeeder,
@@ -261,13 +274,22 @@ export class AppModule implements OnApplicationBootstrap {
// Permissions foundation — keep enabled:
// freightPermissionKeyMigration → renames legacy permission keys
// seeder (IAM DataSeeder) → seeds the IAM app, roles, permissions
// edrOrgSeeder → seeds org/unit + the Permission catalog
// iamBaselineSeeder → @edr/iam-seed: IAM app, roles, permissions,
// position types, organization types +
// default units, org/unit settings and the
// super-admin account. Replaces the package's
// DataSeeder, and is shared with
// edr-passenger-api so one writer owns the
// `iam` schema. Runs after edrOrgSeeder
// because the super admin attaches to the
// edr_freight org/unit.
// Writes nothing unless SEED_IAM_BASELINE=true.
// freightPositionsSeeder → seeds Position + PositionPermission rows
// (depends on edrOrgSeeder, must run after)
await this.freightPermissionKeyMigrationSeeder.run();
await this.seeder.run();
await this.edrOrgSeeder.run();
await this.iamBaselineSeeder.run();
await this.freightPositionsSeeder.run();
// File upload settings — keep enabled.

View File

@@ -181,6 +181,17 @@ GITHUB_PACKAGE_TOKEN=<your-github-packages-token>
# Login endpoint for backoffice users: POST /v1/auth/login
SEED_EDR_PASSENGER_ORG=false
SEED_PASSENGER_STAFF=false
# IAM baseline shared with edr-freight-api (roles, IAM app + permissions, position
# types, organization types + default units, org/unit settings, super admin).
# Replaces the seeder that used to ship inside @tria-plc/iamapi-common — see
# packages/iam-seed. Seeds by DEFAULT when unset; every write is insert-only.
# Set to false to opt out.
SEED_IAM_BASELINE=true
# Super-admin account seeded by the above. Shared across the apps on this schema.
SUPER_ADMIN_EMAIL=superadmin@tria.com
SUPER_ADMIN_PHONE=
# Falls back to DEFAULT_PASSWORD when empty.
SUPER_ADMIN_DEFAULT_PASSWORD=
# Plain-text password set on seeded staff accounts. Defaults to '12345678' if unset.
DEFAULT_PASSWORD=Admin@1234

View File

@@ -27,6 +27,7 @@
"prisma:verify": "ts-node prisma/verify-backfill.ts"
},
"dependencies": {
"@edr/iam-seed": "workspace:*",
"@edr/types": "workspace:*",
"@golevelup/nestjs-rabbitmq": "^5.5.0",
"@nestjs/axios": "^4.0.1",

View File

@@ -4,8 +4,8 @@ import { ConfigModule, ConfigService } from "@nestjs/config";
import { ScheduleModule } from "@nestjs/schedule";
import { EventEmitterModule } from "@nestjs/event-emitter";
import { TypeOrmModule, TypeOrmModuleOptions } from "@nestjs/typeorm";
import { IamBaselineSeeder, IamSeedModule } from "@edr/iam-seed";
import { IamModule as TriaIamModule } from "@tria-plc/iamapi-common/iam.module";
import { DataSeeder } from "@tria-plc/iamapi-common/db/seed/seeder";
import { SharedAuthModule } from "@tria-plc/api-common/modules/auth/shared-auth.module";
import {
EDR_PASSENGER_APPLICATION,
@@ -103,6 +103,17 @@ import { EOtpType } from "@tria-plc/iamapi-common";
`Set your EDR Passenger password using this link: ${route}`,
},
}),
// Replaces the package's DataSeeder. Shared with edr-freight-api, which
// seeds the same `iam` schema — see packages/iam-seed.
IamSeedModule.forRoot({
superAdmin: {
username: "superadmin",
name: { am: "ሱፐር አድሚን", en: "Super Admin" },
roleKey: "super_admin",
organizationKey: "edr",
fallbackEmail: "superadmin@tria.com",
},
}),
SharedAuthModule,
PrismaModule,
AuditModule,
@@ -151,18 +162,23 @@ import { EOtpType } from "@tria-plc/iamapi-common";
export class AppModule implements OnApplicationBootstrap {
private readonly logger = new Logger(AppModule.name);
constructor(
private readonly seeder: DataSeeder,
private readonly iamBaselineSeeder: IamBaselineSeeder,
private readonly edrPassengerOrgSeeder: EdrPassengerOrgSeeder,
private readonly passengerStaffUsersSeeder: PassengerStaffUsersSeeder,
private readonly segmentFareSeeder: SegmentFareSeeder,
) {}
async onApplicationBootstrap() {
// Runs first so the roles it seeds exist before EdrPassengerOrgSeeder links
// super_admin permissions. Its own super-admin account attaches to the `edr`
// organization, which that seeder creates — so on a brand-new database the
// account lands on the next boot; it logs a warning and skips until then.
// Non-fatal internally, but the wrapper stays for symmetry with the rest.
try {
await this.seeder.run();
await this.iamBaselineSeeder.run();
} catch (err) {
this.logger.error(
"[DataSeeder] Seed failed (non-fatal):",
"[IamBaselineSeeder] Seed failed (non-fatal):",
(err as Error).message,
);
}