mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 13:40:57 +00:00
214 lines
6.3 KiB
TypeScript
214 lines
6.3 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 { ERoleKey } from "@tria-plc/api-common/utils/enums/seed.enum";
|
|
import {
|
|
Employee,
|
|
Organization,
|
|
Permission,
|
|
Role,
|
|
RolePermission,
|
|
User,
|
|
UserCredential,
|
|
UserRole,
|
|
} from "@tria-plc/iamapi-common";
|
|
import { DataSource } from "typeorm";
|
|
|
|
const SEED_FLAG = "SEED_DEMO_USERS";
|
|
|
|
const DEMO_ORG_KEY = "demo_iam";
|
|
const DEMO_ORG_NAME = { en: "Demo IAM" };
|
|
|
|
const DEMO_PERMISSIONS = [
|
|
{ key: "can:demo:user1", name: { en: "Can access demo user1" } },
|
|
{ key: "can:demo:user2", name: { en: "Can access demo user2" } },
|
|
];
|
|
|
|
const DEMO_ROLES = [
|
|
{ key: "demo_user1", name: { en: "Demo User1" } },
|
|
{ key: "demo_user2", name: { en: "Demo User2" } },
|
|
];
|
|
|
|
const DEMO_USERS = [
|
|
{
|
|
email: "user@gmail.com",
|
|
username: "user",
|
|
name: { en: "Demo User 1" },
|
|
roleKey: "demo_user1",
|
|
},
|
|
{
|
|
email: "user2@gmail.com",
|
|
username: "user2",
|
|
name: { en: "Demo User 2" },
|
|
roleKey: "demo_user2",
|
|
},
|
|
];
|
|
|
|
@Injectable()
|
|
export class DemoUsersSeeder {
|
|
private readonly logger = new Logger(DemoUsersSeeder.name);
|
|
|
|
constructor(private readonly dataSource: DataSource) {}
|
|
|
|
async run() {
|
|
const shouldSeed = process.env[SEED_FLAG]?.trim().toLowerCase() === "true";
|
|
if (!shouldSeed) {
|
|
this.logger.log(`Skipping demo user seed because ${SEED_FLAG} is not enabled`);
|
|
return;
|
|
}
|
|
|
|
await this.dataSource.transaction(async (manager) => {
|
|
const organizationRepository = manager.getRepository(Organization);
|
|
const employeeRepository = manager.getRepository(Employee);
|
|
const permissionRepository = manager.getRepository(Permission);
|
|
const roleRepository = manager.getRepository(Role);
|
|
const rolePermissionRepository = manager.getRepository(RolePermission);
|
|
const userRepository = manager.getRepository(User);
|
|
const userCredentialRepository = manager.getRepository(UserCredential);
|
|
const userRoleRepository = manager.getRepository(UserRole);
|
|
|
|
await organizationRepository.upsert(
|
|
{
|
|
key: DEMO_ORG_KEY,
|
|
name: DEMO_ORG_NAME,
|
|
// status defaults to ACTIVE in IAM entity
|
|
isGovernmentOrganization: true,
|
|
},
|
|
{ conflictPaths: { key: true } },
|
|
);
|
|
|
|
const organization = await organizationRepository.findOne({
|
|
where: { key: DEMO_ORG_KEY },
|
|
select: { id: true, key: true },
|
|
});
|
|
|
|
if (!organization) {
|
|
throw new Error("demo_org_seed_failed");
|
|
}
|
|
|
|
await permissionRepository.upsert(DEMO_PERMISSIONS, {
|
|
conflictPaths: { key: true },
|
|
});
|
|
|
|
await roleRepository.upsert(DEMO_ROLES, {
|
|
conflictPaths: { key: true },
|
|
});
|
|
|
|
const roles = await roleRepository.find({ where: DEMO_ROLES.map((r) => ({ key: r.key })) });
|
|
const permissions = await permissionRepository.find({
|
|
where: DEMO_PERMISSIONS.map((p) => ({ key: p.key })),
|
|
});
|
|
|
|
const roleByKey = new Map(roles.map((r) => [r.key, r]));
|
|
const permissionByKey = new Map(permissions.map((p) => [p.key, p]));
|
|
|
|
const superAdminRole = await roleRepository.findOne({
|
|
where: { key: ERoleKey.SUPER_ADMIN },
|
|
select: { id: true, key: true },
|
|
});
|
|
|
|
const rolePermissionsToUpsert = [
|
|
{
|
|
roleId: roleByKey.get("demo_user1")!.id,
|
|
permissionId: permissionByKey.get("can:demo:user1")!.id,
|
|
},
|
|
{
|
|
roleId: roleByKey.get("demo_user2")!.id,
|
|
permissionId: permissionByKey.get("can:demo:user2")!.id,
|
|
},
|
|
...(superAdminRole
|
|
? ([
|
|
{
|
|
roleId: superAdminRole.id,
|
|
permissionId: permissionByKey.get("can:demo:user1")!.id,
|
|
},
|
|
{
|
|
roleId: superAdminRole.id,
|
|
permissionId: permissionByKey.get("can:demo:user2")!.id,
|
|
},
|
|
] as Array<{ roleId: string; permissionId: string }>)
|
|
: []),
|
|
];
|
|
|
|
await rolePermissionRepository.upsert(rolePermissionsToUpsert, {
|
|
conflictPaths: { roleId: true, permissionId: true },
|
|
});
|
|
|
|
const hashedPassword = await hashPassword("12345678");
|
|
|
|
for (const demoUser of DEMO_USERS) {
|
|
const existingUser = await userRepository.findOne({
|
|
where: { email: demoUser.email },
|
|
select: { id: true, email: true },
|
|
});
|
|
|
|
let user = existingUser;
|
|
if (!user) {
|
|
user = await userRepository.save(
|
|
userRepository.create({
|
|
email: demoUser.email,
|
|
username: demoUser.username,
|
|
name: demoUser.name,
|
|
isActive: true,
|
|
hasSetPassword: true,
|
|
status: EUserStatus.ACCEPTED,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// Ensure an active credential exists for login.
|
|
const activeCredentialExists = await userCredentialRepository.exists({
|
|
where: {
|
|
userId: user.id,
|
|
isActive: true,
|
|
},
|
|
});
|
|
|
|
if (!activeCredentialExists) {
|
|
await userCredentialRepository.insert({
|
|
userId: user.id,
|
|
password: hashedPassword,
|
|
isActive: true,
|
|
});
|
|
}
|
|
|
|
// Login query requires a current employee in an ACTIVE organization.
|
|
const employeeExists = await employeeRepository.exists({
|
|
where: {
|
|
userId: user.id,
|
|
organizationId: organization.id,
|
|
isCurrent: true,
|
|
},
|
|
});
|
|
|
|
if (!employeeExists) {
|
|
await employeeRepository.insert({
|
|
userId: user.id,
|
|
organizationId: organization.id,
|
|
isCurrent: true,
|
|
name: demoUser.name,
|
|
});
|
|
}
|
|
|
|
const role = roleByKey.get(demoUser.roleKey);
|
|
if (!role) {
|
|
throw new Error(`missing_role:${demoUser.roleKey}`);
|
|
}
|
|
|
|
await userRoleRepository.upsert(
|
|
{
|
|
userId: user.id,
|
|
roleId: role.id,
|
|
organizationId: organization.id,
|
|
},
|
|
{ conflictPaths: { userId: true, roleId: true } },
|
|
);
|
|
}
|
|
});
|
|
|
|
this.logger.log(
|
|
"Seeded demo users + permissions (user@gmail.com, user2@gmail.com; permissions can:demo:user1/can:demo:user2)",
|
|
);
|
|
}
|
|
}
|