import { Injectable, Logger } from '@nestjs/common'; import { hashPassword } from '@tria-plc/api-common/utils/argon'; import { EUserStatus } from '@tria-plc/api-common/utils/enums/user.enum'; import { Employee, EmployeePosition, Organization, Position, Role, Unit, User, UserCredential, UserRole, } from '@tria-plc/iamapi-common'; import { DataSource } from 'typeorm'; const SEED_FLAG = 'SEED_FREIGHT_STAFF'; const EDR_ORG_KEY = 'edr_freight'; const EDR_UNIT_KEY = 'edr_freight_app'; // roleKey is kept only for backwards compatibility with existing UserRole rows; // access is granted via the assigned position (positionKey) + PositionPermission. const STAFF_USERS = [ { email: 'linestaff@edr.local', username: 'linestaff', roleKey: 'edr_line_staff', positionKey: 'operation' }, { email: 'chief@edr.local', username: 'chief', roleKey: 'edr_org_manager', positionKey: 'chief' }, { email: 'director@edr.local', username: 'director', roleKey: 'edr_director', positionKey: 'director' }, { email: 'ceo@edr.local', username: 'ceo', roleKey: 'edr_ceo', positionKey: 'ceo' }, { email: 'marketer@edr.local', username: 'marketer', roleKey: 'edr_marketing', positionKey: 'marketer' }, { email: 'operation@edr.local', username: 'operation', roleKey: 'edr_operations_officer', positionKey: 'operation' }, { email: 'gl-et@edr.local', username: 'gl_et', roleKey: 'edr_gl_ethiopia', positionKey: 'ethiopian_gl' }, { email: 'gl-dj@edr.local', username: 'gl_dj', roleKey: 'edr_gl_djibouti', positionKey: 'djibouti_gl' }, ] as const; @Injectable() export class FreightStaffUsersSeeder { private readonly logger = new Logger(FreightStaffUsersSeeder.name); constructor(private readonly dataSource: DataSource) {} async run() { if (process.env[SEED_FLAG]?.trim().toLowerCase() !== 'true') { this.logger.log(`Skipping freight staff seed because ${SEED_FLAG} is not enabled`); return; } const password = process.env.DEFAULT_PASSWORD?.trim() || '12345678'; await this.dataSource.transaction(async (manager) => { const organization = await manager.getRepository(Organization).findOne({ where: { key: EDR_ORG_KEY }, select: { id: true, key: true }, }); if (!organization) { throw new Error(`missing_organization:${EDR_ORG_KEY}`); } const unit = await manager.getRepository(Unit).findOne({ where: { key: EDR_UNIT_KEY, organizationId: organization.id }, select: { id: true }, }); if (!unit) { throw new Error(`missing_unit:${EDR_UNIT_KEY}`); } const roleRepository = manager.getRepository(Role); const userRepository = manager.getRepository(User); const userCredentialRepository = manager.getRepository(UserCredential); const userRoleRepository = manager.getRepository(UserRole); const employeeRepository = manager.getRepository(Employee); const positionRepository = manager.getRepository(Position); const employeePositionRepository = manager.getRepository(EmployeePosition); const hashedPassword = await hashPassword(password); for (const staff of STAFF_USERS) { const role = await roleRepository.findOne({ where: { key: staff.roleKey }, select: { id: true, key: true }, }); if (!role) { throw new Error(`missing_role:${staff.roleKey}`); } let user = await userRepository.findOne({ where: { email: staff.email }, select: { id: true, email: true }, }); if (!user) { user = await userRepository.save( userRepository.create({ email: staff.email, username: staff.username, name: { en: staff.username }, isActive: true, hasSetPassword: true, status: EUserStatus.ACCEPTED, }), ); this.logger.log(`Seeded freight staff user ${staff.email}`); } const activeCredentialExists = await userCredentialRepository.exists({ where: { userId: user.id, isActive: true }, }); if (!activeCredentialExists) { await userCredentialRepository.insert({ userId: user.id, password: hashedPassword, isActive: true, }); } await userRoleRepository.upsert( { userId: user.id, roleId: role.id, organizationId: organization.id, }, { conflictPaths: { userId: true, roleId: true } }, ); let employee = await employeeRepository.findOne({ where: { userId: user.id, organizationId: organization.id, isCurrent: true, }, select: { id: true }, }); if (!employee) { employee = await employeeRepository.save( employeeRepository.create({ userId: user.id, organizationId: organization.id, unitId: unit.id, isCurrent: true, name: { en: staff.username }, }), ); } // Grant access via the assigned position (positions-as-roles). const position = await positionRepository.findOne({ where: { key: staff.positionKey, unitId: unit.id }, select: { id: true, key: true }, }); if (!position) { throw new Error(`missing_position:${staff.positionKey}`); } const employeePositionExists = await employeePositionRepository.exists({ where: { employeeId: employee.id as string, positionId: position.id as string, }, }); if (!employeePositionExists) { await employeePositionRepository.insert({ employeeId: employee.id as string, positionId: position.id as string, unitId: unit.id, isCurrent: true, }); } } }); this.logger.log( 'Ensured freight staff users (linestaff@, director@, ceo@, gl@)', ); } }