mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
183 lines
6.1 KiB
TypeScript
183 lines
6.1 KiB
TypeScript
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' },
|
|
{ email: 'tm-chief@edr.local', username: 'tm_chief', roleKey: 'edr_operations_officer', positionKey: 'truck_machinery_chief' },
|
|
] 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@)',
|
|
);
|
|
}
|
|
}
|