Merge branch 'dev' into SP-197-be-retrieve-devices-in-the-gateway

This commit is contained in:
faris Aljohari
2024-05-21 15:35:31 +03:00
90 changed files with 1546 additions and 314 deletions

View File

@ -4,4 +4,5 @@ export class AuthInterface {
uuid: string;
sessionId: string;
id: number;
roles?: string[];
}

View File

@ -22,7 +22,9 @@ export class AuthService {
where: {
email,
},
relations: ['roles.roleType'],
});
if (!user.isUserVerified) {
throw new BadRequestException('User is not verified');
}
@ -68,7 +70,9 @@ export class AuthService {
uuid: user.uuid,
type: user.type,
sessionId: user.sessionId,
roles: user?.roles,
};
const tokens = await this.getTokens(payload);
await this.updateRefreshToken(user.uuid, tokens.refreshToken);
return tokens;

View File

@ -28,9 +28,10 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
if (validateUser) {
return {
email: payload.email,
userId: payload.id,
userUuid: payload.uuid,
uuid: payload.uuid,
sessionId: payload.sessionId,
roles: payload?.roles,
};
} else {
throw new BadRequestException('Unauthorized');

View File

@ -31,9 +31,10 @@ export class RefreshTokenStrategy extends PassportStrategy(
if (validateUser) {
return {
email: payload.email,
userId: payload.id,
userUuid: payload.uuid,
uuid: payload.uuid,
sessionId: payload.sessionId,
roles: payload?.roles,
};
} else {
throw new BadRequestException('Unauthorized');

View File

@ -1,2 +1,3 @@
import emailConfig from './email.config';
export default [emailConfig];
import superAdminConfig from './super.admin.config';
export default [emailConfig, superAdminConfig];

View File

@ -0,0 +1,9 @@
import { registerAs } from '@nestjs/config';
export default registerAs(
'super-admin',
(): Record<string, any> => ({
SUPER_ADMIN_EMAIL: process.env.SUPER_ADMIN_EMAIL,
SUPER_ADMIN_PASSWORD: process.env.SUPER_ADMIN_PASSWORD,
}),
);

View File

@ -0,0 +1,4 @@
export enum RoleType {
SUPER_ADMIN = 'SUPER_ADMIN',
ADMIN = 'ADMIN',
}

View File

@ -0,0 +1,7 @@
export enum SpaceType {
COMMUNITY = 'community',
BUILDING = 'building',
FLOOR = 'floor',
UNIT = 'unit',
ROOM = 'room',
}

View File

@ -6,16 +6,16 @@ import { UserEntity } from '../modules/user/entities/user.entity';
import { UserSessionEntity } from '../modules/session/entities/session.entity';
import { UserOtpEntity } from '../modules/user-otp/entities';
import { ProductEntity } from '../modules/product/entities';
import {
DeviceEntity,
DeviceUserPermissionEntity,
} from '../modules/device/entities';
import { DeviceEntity } from '../modules/device/entities';
import { PermissionTypeEntity } from '../modules/permission/entities';
import { SpaceEntity } from '../modules/space/entities';
import { SpaceTypeEntity } from '../modules/space-type/entities';
import { UserSpaceEntity } from '../modules/user-space/entities';
import { GroupEntity } from '../modules/group/entities';
import { GroupDeviceEntity } from '../modules/group-device/entities';
import { DeviceUserPermissionEntity } from '../modules/device-user-permission/entities';
import { UserRoleEntity } from '../modules/user-role/entities';
import { RoleTypeEntity } from '../modules/role-type/entities';
@Module({
imports: [
@ -43,6 +43,9 @@ import { GroupDeviceEntity } from '../modules/group-device/entities';
UserSpaceEntity,
GroupEntity,
GroupDeviceEntity,
DeviceUserPermissionEntity,
UserRoleEntity,
RoleTypeEntity,
],
namingStrategy: new SnakeNamingStrategy(),
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),

View File

@ -1,11 +1,14 @@
import { Global, Module } from '@nestjs/common';
import { HelperHashService } from './services';
import { SpacePermissionService } from './services/space.permission.service';
import { SpaceRepository } from '../modules/space/repositories';
import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
@Global()
@Module({
providers: [HelperHashService],
exports: [HelperHashService],
providers: [HelperHashService, SpacePermissionService, SpaceRepository],
exports: [HelperHashService, SpacePermissionService],
controllers: [],
imports: [],
imports: [SpaceRepositoryModule],
})
export class HelperModule {}

View File

@ -1 +1,2 @@
export * from './helper.hash.service';
export * from './space.permission.service';

View File

@ -0,0 +1,39 @@
import { Injectable } from '@nestjs/common';
import { SpaceRepository } from '@app/common/modules/space/repositories';
import { BadRequestException } from '@nestjs/common';
@Injectable()
export class SpacePermissionService {
constructor(private readonly spaceRepository: SpaceRepository) {}
async checkUserPermission(
spaceUuid: string,
userUuid: string,
type: string,
): Promise<void> {
try {
const spaceData = await this.spaceRepository.findOne({
where: {
uuid: spaceUuid,
spaceType: {
type: type,
},
userSpaces: {
user: {
uuid: userUuid,
},
},
},
relations: ['spaceType', 'userSpaces', 'userSpaces.user'],
});
if (!spaceData) {
throw new BadRequestException(
`You do not have permission to access this ${type}`,
);
}
} catch (err) {
throw new BadRequestException(err.message || 'Invalid UUID');
}
}
}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DeviceUserPermissionEntity } from './entities';
@Module({
providers: [],
exports: [],
controllers: [],
imports: [TypeOrmModule.forFeature([DeviceUserPermissionEntity])],
})
export class DeviceUserPermissionRepositoryModule {}

View File

@ -1,6 +1,6 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class DeviceUserTypeDto {
export class DeviceUserPermissionDto {
@IsString()
@IsNotEmpty()
public uuid: string;

View File

@ -0,0 +1 @@
export * from './device.user.permission.dto';

View File

@ -0,0 +1,43 @@
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { DeviceUserPermissionDto } from '../dtos';
import { PermissionTypeEntity } from '../../permission/entities';
import { DeviceEntity } from '../../device/entities';
import { UserEntity } from '../../user/entities';
@Entity({ name: 'device-user-permission' })
@Unique(['userUuid', 'deviceUuid'])
export class DeviceUserPermissionEntity extends AbstractEntity<DeviceUserPermissionDto> {
@Column({
nullable: false,
})
public userUuid: string;
@Column({
nullable: false,
})
deviceUuid: string;
@ManyToOne(() => DeviceEntity, (device) => device.permission, {
nullable: false,
})
device: DeviceEntity;
@ManyToOne(
() => PermissionTypeEntity,
(permissionType) => permissionType.permission,
{
nullable: false,
},
)
permissionType: PermissionTypeEntity;
@ManyToOne(() => UserEntity, (user) => user.userPermission, {
nullable: false,
})
user: UserEntity;
constructor(partial: Partial<DeviceUserPermissionEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -0,0 +1 @@
export * from './device.user.permission.entity';

View File

@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common';
import { DeviceUserPermissionEntity } from '../entities';
@Injectable()
export class DeviceUserTypeRepository extends Repository<DeviceUserPermissionEntity> {
export class DeviceUserPermissionRepository extends Repository<DeviceUserPermissionEntity> {
constructor(private dataSource: DataSource) {
super(DeviceUserPermissionEntity, dataSource.createEntityManager());
}

View File

@ -0,0 +1 @@
export * from './device.user.permission.repository';

View File

@ -1,13 +1,11 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DeviceEntity, DeviceUserPermissionEntity } from './entities';
import { DeviceEntity } from './entities';
@Module({
providers: [],
exports: [],
controllers: [],
imports: [
TypeOrmModule.forFeature([DeviceEntity, DeviceUserPermissionEntity]),
],
imports: [TypeOrmModule.forFeature([DeviceEntity])],
})
export class DeviceRepositoryModule {}

View File

@ -1,2 +1 @@
export * from './device.dto';
export * from './device-user-type.dto';

View File

@ -1,42 +0,0 @@
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { DeviceUserTypeDto } from '../dtos/device-user-type.dto';
import { DeviceEntity } from './device.entity';
import { PermissionTypeEntity } from '../../permission/entities';
@Entity({ name: 'device-user-permission' })
export class DeviceUserPermissionEntity extends AbstractEntity<DeviceUserTypeDto> {
@Column({
nullable: false,
})
public userUuid: string;
@Column({
nullable: false,
})
deviceUuid: string;
@Column({
nullable: false,
})
public permissionTypeUuid: string;
@ManyToOne(() => DeviceEntity, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
@JoinColumn({ name: 'device_uuid', referencedColumnName: 'uuid' })
device: DeviceEntity;
@ManyToOne(() => PermissionTypeEntity, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
@JoinColumn({ name: 'permission_type_uuid', referencedColumnName: 'uuid' })
type: PermissionTypeEntity;
constructor(partial: Partial<DeviceUserPermissionEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -1,10 +1,10 @@
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { DeviceDto } from '../dtos/device.dto';
import { DeviceUserPermissionEntity } from './device-user-type.entity';
import { GroupDeviceEntity } from '../../group-device/entities';
import { SpaceEntity } from '../../space/entities';
import { ProductEntity } from '../../product/entities';
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities';
@Entity({ name: 'device' })
@Unique(['spaceDevice', 'deviceTuyaUuid'])
@ -25,8 +25,6 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
(permission) => permission.device,
{
nullable: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
)
permission: DeviceUserPermissionEntity[];

View File

@ -1,2 +1 @@
export * from './device.entity';
export * from './device-user-type.entity';

View File

@ -1,2 +1 @@
export * from './device.repository';
export * from './device-user-type.repository';

View File

@ -19,7 +19,6 @@ export class GroupEntity extends AbstractEntity<GroupDto> {
@OneToMany(() => GroupDeviceEntity, (groupDevice) => groupDevice.group, {
cascade: true,
onDelete: 'CASCADE',
})
groupDevices: GroupDeviceEntity[];

View File

@ -2,7 +2,7 @@ import { Column, Entity, OneToMany } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { PermissionType } from '@app/common/constants/permission-type.enum';
import { PermissionTypeDto } from '../dtos/permission.dto';
import { DeviceUserPermissionEntity } from '../../device/entities';
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities';
@Entity({ name: 'permission-type' })
export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {
@ -14,11 +14,9 @@ export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {
@OneToMany(
() => DeviceUserPermissionEntity,
(permission) => permission.type,
(permission) => permission.permissionType,
{
nullable: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
)
permission: DeviceUserPermissionEntity[];

View File

@ -0,0 +1 @@
export * from './role.type.dto';

View File

@ -0,0 +1,11 @@
import { RoleType } from '@app/common/constants/role.type.enum';
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
export class RoleTypeDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsEnum(RoleType)
public type: RoleType;
}

View File

@ -0,0 +1 @@
export * from './role.type.entity';

View File

@ -0,0 +1,23 @@
import { Column, Entity, OneToMany, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { RoleTypeDto } from '../dtos/role.type.dto';
import { RoleType } from '@app/common/constants/role.type.enum';
import { UserRoleEntity } from '../../user-role/entities';
@Entity({ name: 'role-type' })
@Unique(['type'])
export class RoleTypeEntity extends AbstractEntity<RoleTypeDto> {
@Column({
nullable: false,
enum: Object.values(RoleType),
})
type: string;
@OneToMany(() => UserRoleEntity, (role) => role.roleType, {
nullable: true,
})
roles: UserRoleEntity[];
constructor(partial: Partial<RoleTypeEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -0,0 +1 @@
export * from './role.type.repository';

View File

@ -0,0 +1,10 @@
import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { RoleTypeEntity } from '../entities/role.type.entity';
@Injectable()
export class RoleTypeRepository extends Repository<RoleTypeEntity> {
constructor(private dataSource: DataSource) {
super(RoleTypeEntity, dataSource.createEntityManager());
}
}

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RoleTypeEntity } from './entities/role.type.entity';
@Module({
providers: [],
exports: [],
controllers: [],
imports: [TypeOrmModule.forFeature([RoleTypeEntity])],
})
export class RoleTypeRepositoryModule {}

View File

@ -0,0 +1 @@
export * from './user.role.dto';

View File

@ -0,0 +1,15 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class UserRoleDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public roleTypeUuid: string;
}

View File

@ -0,0 +1 @@
export * from './user.role.entity';

View File

@ -0,0 +1,24 @@
import { Entity, ManyToOne, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserRoleDto } from '../dtos';
import { UserEntity } from '../../user/entities';
import { RoleTypeEntity } from '../../role-type/entities';
@Entity({ name: 'user-role' })
@Unique(['user', 'roleType'])
export class UserRoleEntity extends AbstractEntity<UserRoleDto> {
@ManyToOne(() => UserEntity, (user) => user.roles, {
nullable: false,
})
user: UserEntity;
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.roles, {
nullable: false,
})
roleType: RoleTypeEntity;
constructor(partial: Partial<UserRoleEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -0,0 +1 @@
export * from './user.role.repository';

View File

@ -0,0 +1,10 @@
import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { UserRoleEntity } from '../entities';
@Injectable()
export class UserRoleRepository extends Repository<UserRoleEntity> {
constructor(private dataSource: DataSource) {
super(UserRoleEntity, dataSource.createEntityManager());
}
}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserRoleEntity } from './entities';
@Module({
providers: [],
exports: [],
controllers: [],
imports: [TypeOrmModule.forFeature([UserRoleEntity])],
})
export class UserRoleRepositoryModule {}

View File

@ -1,7 +1,9 @@
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities/device.user.permission.entity';
import { Column, Entity, OneToMany } from 'typeorm';
import { UserDto } from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserSpaceEntity } from '../../user-space/entities';
import { UserRoleEntity } from '../../user-role/entities';
@Entity({ name: 'user' })
export class UserEntity extends AbstractEntity<UserDto> {
@ -51,6 +53,16 @@ export class UserEntity extends AbstractEntity<UserDto> {
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user)
userSpaces: UserSpaceEntity[];
@OneToMany(
() => DeviceUserPermissionEntity,
(userPermission) => userPermission.user,
)
userPermission: DeviceUserPermissionEntity[];
@OneToMany(() => UserRoleEntity, (role) => role.user, {
nullable: true,
})
roles: UserRoleEntity[];
constructor(partial: Partial<UserEntity>) {
super();
Object.assign(this, partial);

View File

@ -0,0 +1,43 @@
import { Global, Module } from '@nestjs/common';
import { SeederService } from './services/seeder.service';
import { PermissionTypeRepository } from '../modules/permission/repositories';
import { PermissionTypeSeeder } from './services/permission.type.seeder';
import { PermissionTypeRepositoryModule } from '../modules/permission/permission.repository.module';
import { ConfigModule } from '@nestjs/config';
import { RoleTypeRepositoryModule } from '../modules/role-type/role.type.repository.module';
import { RoleTypeRepository } from '../modules/role-type/repositories';
import { RoleTypeSeeder } from './services/role.type.seeder';
import { SpaceTypeRepository } from '../modules/space-type/repositories';
import { SpaceTypeSeeder } from './services/space.type.seeder';
import { SpaceTypeRepositoryModule } from '../modules/space-type/space.type.repository.module';
import { SuperAdminSeeder } from './services/supper.admin.seeder';
import { UserRepository } from '../modules/user/repositories';
import { UserRoleRepository } from '../modules/user-role/repositories';
import { UserRoleRepositoryModule } from '../modules/user-role/user.role.repository.module';
import { UserRepositoryModule } from '../modules/user/user.repository.module';
@Global()
@Module({
providers: [
PermissionTypeSeeder,
RoleTypeSeeder,
SpaceTypeSeeder,
SeederService,
PermissionTypeRepository,
RoleTypeRepository,
SpaceTypeRepository,
SuperAdminSeeder,
UserRepository,
UserRoleRepository,
],
exports: [SeederService],
controllers: [],
imports: [
ConfigModule.forRoot(),
PermissionTypeRepositoryModule,
RoleTypeRepositoryModule,
UserRepositoryModule,
UserRoleRepositoryModule,
SpaceTypeRepositoryModule,
],
})
export class SeederModule {}

View File

@ -0,0 +1,49 @@
import { Injectable } from '@nestjs/common';
import { PermissionTypeRepository } from '../../modules/permission/repositories';
import { PermissionType } from '../../constants/permission-type.enum';
@Injectable()
export class PermissionTypeSeeder {
constructor(
private readonly permissionTypeRepository: PermissionTypeRepository,
) {}
async addPermissionTypeDataIfNotFound(): Promise<void> {
try {
const existingPermissionTypes =
await this.permissionTypeRepository.find();
const permissionTypeNames = existingPermissionTypes.map((pt) => pt.type);
const missingPermissionTypes = [];
if (!permissionTypeNames.includes(PermissionType.CONTROLLABLE)) {
missingPermissionTypes.push(PermissionType.CONTROLLABLE);
}
if (!permissionTypeNames.includes(PermissionType.READ)) {
missingPermissionTypes.push(PermissionType.READ);
}
if (missingPermissionTypes.length > 0) {
await this.addPermissionTypeData(missingPermissionTypes);
}
} catch (err) {
console.error('Error while checking permission type data:', err);
throw err;
}
}
private async addPermissionTypeData(
permissionTypes: string[],
): Promise<void> {
try {
const permissionTypeEntities = permissionTypes.map((type) => ({
type,
}));
await this.permissionTypeRepository.save(permissionTypeEntities);
} catch (err) {
console.error('Error while adding permission type data:', err);
throw err;
}
}
}

View File

@ -0,0 +1,44 @@
import { Injectable } from '@nestjs/common';
import { RoleType } from '../../constants/role.type.enum';
import { RoleTypeRepository } from '../../modules/role-type/repositories';
@Injectable()
export class RoleTypeSeeder {
constructor(private readonly roleTypeRepository: RoleTypeRepository) {}
async addRoleTypeDataIfNotFound(): Promise<void> {
try {
const existingRoleTypes = await this.roleTypeRepository.find();
const roleTypeNames = existingRoleTypes.map((pt) => pt.type);
const missingRoleTypes = [];
if (!roleTypeNames.includes(RoleType.SUPER_ADMIN)) {
missingRoleTypes.push(RoleType.SUPER_ADMIN);
}
if (!roleTypeNames.includes(RoleType.ADMIN)) {
missingRoleTypes.push(RoleType.ADMIN);
}
if (missingRoleTypes.length > 0) {
await this.addRoleTypeData(missingRoleTypes);
}
} catch (err) {
console.error('Error while checking role type data:', err);
throw err;
}
}
private async addRoleTypeData(roleTypes: string[]): Promise<void> {
try {
const roleTypeEntities = roleTypes.map((type) => ({
type,
}));
await this.roleTypeRepository.save(roleTypeEntities);
} catch (err) {
console.error('Error while adding role type data:', err);
throw err;
}
}
}

View File

@ -0,0 +1,21 @@
import { Injectable } from '@nestjs/common';
import { PermissionTypeSeeder } from './permission.type.seeder';
import { RoleTypeSeeder } from './role.type.seeder';
import { SpaceTypeSeeder } from './space.type.seeder';
import { SuperAdminSeeder } from './supper.admin.seeder';
@Injectable()
export class SeederService {
constructor(
private readonly permissionTypeSeeder: PermissionTypeSeeder,
private readonly roleTypeSeeder: RoleTypeSeeder,
private readonly spaceTypeSeeder: SpaceTypeSeeder,
private readonly superAdminSeeder: SuperAdminSeeder,
) {}
async seed() {
await this.permissionTypeSeeder.addPermissionTypeDataIfNotFound();
await this.roleTypeSeeder.addRoleTypeDataIfNotFound();
await this.spaceTypeSeeder.addSpaceTypeDataIfNotFound();
await this.superAdminSeeder.createSuperAdminIfNotFound();
}
}

View File

@ -0,0 +1,52 @@
import { Injectable } from '@nestjs/common';
import { SpaceType } from '../../constants/space-type.enum';
import { SpaceTypeRepository } from '../../modules/space-type/repositories';
@Injectable()
export class SpaceTypeSeeder {
constructor(private readonly spaceTypeRepository: SpaceTypeRepository) {}
async addSpaceTypeDataIfNotFound(): Promise<void> {
try {
const existingSpaceTypes = await this.spaceTypeRepository.find();
const spaceTypeNames = existingSpaceTypes.map((pt) => pt.type);
const missingSpaceTypes = [];
if (!spaceTypeNames.includes(SpaceType.COMMUNITY)) {
missingSpaceTypes.push(SpaceType.COMMUNITY);
}
if (!spaceTypeNames.includes(SpaceType.BUILDING)) {
missingSpaceTypes.push(SpaceType.BUILDING);
}
if (!spaceTypeNames.includes(SpaceType.FLOOR)) {
missingSpaceTypes.push(SpaceType.FLOOR);
}
if (!spaceTypeNames.includes(SpaceType.UNIT)) {
missingSpaceTypes.push(SpaceType.UNIT);
}
if (!spaceTypeNames.includes(SpaceType.ROOM)) {
missingSpaceTypes.push(SpaceType.ROOM);
}
if (missingSpaceTypes.length > 0) {
await this.addSpaceTypeData(missingSpaceTypes);
}
} catch (err) {
console.error('Error while checking space type data:', err);
throw err;
}
}
private async addSpaceTypeData(spaceTypes: string[]): Promise<void> {
try {
const spaceTypeEntities = spaceTypes.map((type) => ({
type,
}));
await this.spaceTypeRepository.save(spaceTypeEntities);
} catch (err) {
console.error('Error while adding space type data:', err);
throw err;
}
}
}

View File

@ -0,0 +1,72 @@
import { Injectable } from '@nestjs/common';
import { UserRepository } from '@app/common/modules/user/repositories';
import { RoleType } from '@app/common/constants/role.type.enum';
import { UserRoleRepository } from '@app/common/modules/user-role/repositories';
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
import { ConfigService } from '@nestjs/config';
import { HelperHashService } from '../../helper/services';
@Injectable()
export class SuperAdminSeeder {
constructor(
private readonly configService: ConfigService,
private readonly userRepository: UserRepository,
private readonly userRoleRepository: UserRoleRepository,
private readonly roleTypeRepository: RoleTypeRepository,
private readonly helperHashService: HelperHashService,
) {}
async createSuperAdminIfNotFound(): Promise<void> {
try {
const superAdminData = await this.userRoleRepository.find({
where: { roleType: { type: RoleType.SUPER_ADMIN } },
relations: ['roleType'],
});
if (superAdminData.length <= 0) {
// Create the super admin user if not found
console.log('Creating super admin user...');
await this.createSuperAdmin();
}
} catch (err) {
console.error('Error while checking super admin:', err);
throw err;
}
}
private async getRoleUuidByRoleType(roleType: string) {
const role = await this.roleTypeRepository.findOne({
where: { type: roleType },
});
return role.uuid;
}
private async createSuperAdmin(): Promise<void> {
const salt = this.helperHashService.randomSalt(10); // Hash the password using bcrypt
const hashedPassword = await this.helperHashService.bcrypt(
this.configService.get<string>('super-admin.SUPER_ADMIN_PASSWORD'),
salt,
);
try {
const user = await this.userRepository.save({
email: this.configService.get<string>('super-admin.SUPER_ADMIN_EMAIL'),
password: hashedPassword,
firstName: 'Super',
lastName: 'Admin',
isUserVerified: true,
isActive: true,
});
const defaultUserRoleUuid = await this.getRoleUuidByRoleType(
RoleType.SUPER_ADMIN,
);
await this.userRoleRepository.save({
user: { uuid: user.uuid },
roleType: { uuid: defaultUserRoleUuid },
});
} catch (err) {
console.error('Error while creating super admin:', err);
throw err;
}
}
}