Merge branch 'dev'

This commit is contained in:
faris Aljohari
2024-09-03 14:44:23 +03:00
136 changed files with 4083 additions and 745 deletions

View File

@ -1,75 +1,92 @@
ACCESS_KEY= ACCESS_KEY=
AZURE_POSTGRESQL_DATABASE= AZURE_POSTGRESQL_DATABASE=
AZURE_POSTGRESQL_HOST= AZURE_POSTGRESQL_HOST=
AZURE_POSTGRESQL_PASSWORD= AZURE_POSTGRESQL_PASSWORD=
AZURE_POSTGRESQL_PORT= AZURE_POSTGRESQL_PORT=
AZURE_POSTGRESQL_SSL= AZURE_POSTGRESQL_SSL=
AZURE_POSTGRESQL_SYNC= AZURE_POSTGRESQL_SYNC=
AZURE_POSTGRESQL_USER= AZURE_POSTGRESQL_USER=
AZURE_REDIS_CONNECTIONSTRING= AZURE_REDIS_CONNECTIONSTRING=
BASE_URL= BASE_URL=
DB_SYNC= DB_SYNC=
DOCKER_REGISTRY_SERVER_PASSWORD= DOCKER_REGISTRY_SERVER_PASSWORD=
DOCKER_REGISTRY_SERVER_URL= DOCKER_REGISTRY_SERVER_URL=
DOCKER_REGISTRY_SERVER_USERNAME= DOCKER_REGISTRY_SERVER_USERNAME=
DOPPLER_CONFIG= DOPPLER_CONFIG=
DOPPLER_ENVIRONMENT= DOPPLER_ENVIRONMENT=
DOPPLER_PROJECT= DOPPLER_PROJECT=
JWT_EXPIRE_TIME= JWT_EXPIRE_TIME=
JWT_EXPIRE_TIME_REFRESH= JWT_EXPIRE_TIME_REFRESH=
JWT_SECRET= JWT_SECRET=
JWT_SECRET_REFRESH= JWT_SECRET_REFRESH=
SECRET_KEY= SECRET_KEY=
SMTP_HOST= SMTP_HOST=
SMTP_PASSWORD= SMTP_PASSWORD=
SMTP_PORT= SMTP_PORT=
SMTP_SECURE= SMTP_SECURE=
SMTP_USER= SMTP_USER=
WEBSITES_ENABLE_APP_SERVICE_STORAGE= WEBSITES_ENABLE_APP_SERVICE_STORAGE=
PORT= PORT=
SUPER_ADMIN_EMAIL= SUPER_ADMIN_EMAIL=
SUPER_ADMIN_PASSWORD= SUPER_ADMIN_PASSWORD=
TUYA_ACCESS_ID= TUYA_ACCESS_ID=
TUYA_ACCESS_KEY= TUYA_ACCESS_KEY=
ONESIGNAL_APP_ID= ONESIGNAL_APP_ID=
ONESIGNAL_API_KEY= ONESIGNAL_API_KEY=
TRUN_ON_TUYA_SOCKET= TRUN_ON_TUYA_SOCKET=
TUYA_EU_URL= TUYA_EU_URL=
MONGODB_URI= FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=
FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=d
FIREBASE_MEASUREMENT_ID=
FIREBASE_DATABASE_URL=
OTP_LIMITER=

View File

@ -17,10 +17,19 @@ export class AuthService {
private readonly configService: ConfigService, private readonly configService: ConfigService,
) {} ) {}
async validateUser(email: string, pass: string): Promise<any> { async validateUser(
email: string,
pass: string,
regionUuid?: string,
): Promise<any> {
const user = await this.userRepository.findOne({ const user = await this.userRepository.findOne({
where: { where: {
email, email,
region: regionUuid
? {
uuid: regionUuid,
}
: undefined,
}, },
relations: ['roles.roleType'], relations: ['roles.roleType'],
}); });

View File

@ -0,0 +1 @@
export const defaultDoorLockPass = '1233214';

View File

@ -129,7 +129,7 @@ export const allCountries = [
'Oman', 'Oman',
'Pakistan', 'Pakistan',
'Palau', 'Palau',
'Palestine State', 'Palestine',
'Panama', 'Panama',
'Papua New Guinea', 'Papua New Guinea',
'Paraguay', 'Paraguay',

View File

@ -4,20 +4,21 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { SnakeNamingStrategy } from './strategies'; import { SnakeNamingStrategy } from './strategies';
import { UserEntity } from '../modules/user/entities/user.entity'; import { UserEntity } from '../modules/user/entities/user.entity';
import { UserSessionEntity } from '../modules/session/entities/session.entity'; import { UserSessionEntity } from '../modules/session/entities/session.entity';
import { UserOtpEntity } from '../modules/user-otp/entities'; import { UserOtpEntity } from '../modules/user/entities';
import { ProductEntity } from '../modules/product/entities'; import { ProductEntity } from '../modules/product/entities';
import { DeviceEntity } from '../modules/device/entities'; import { DeviceEntity } from '../modules/device/entities';
import { PermissionTypeEntity } from '../modules/permission/entities'; import { PermissionTypeEntity } from '../modules/permission/entities';
import { SpaceEntity } from '../modules/space/entities'; import { SpaceEntity } from '../modules/space/entities';
import { SpaceTypeEntity } from '../modules/space-type/entities'; import { SpaceTypeEntity } from '../modules/space/entities';
import { UserSpaceEntity } from '../modules/user-space/entities'; import { UserSpaceEntity } from '../modules/user/entities';
import { DeviceUserPermissionEntity } from '../modules/device-user-permission/entities'; import { DeviceUserPermissionEntity } from '../modules/device/entities';
import { UserRoleEntity } from '../modules/user-role/entities'; import { UserRoleEntity } from '../modules/user/entities';
import { RoleTypeEntity } from '../modules/role-type/entities'; import { RoleTypeEntity } from '../modules/role-type/entities';
import { UserNotificationEntity } from '../modules/user-notification/entities'; import { UserNotificationEntity } from '../modules/user/entities';
import { DeviceNotificationEntity } from '../modules/device-notification/entities'; import { DeviceNotificationEntity } from '../modules/device/entities';
import { RegionEntity } from '../modules/region/entities'; import { RegionEntity } from '../modules/region/entities';
import { TimeZoneEntity } from '../modules/timezone/entities'; import { TimeZoneEntity } from '../modules/timezone/entities';
import { VisitorPasswordEntity } from '../modules/visitor-password/entities';
@Module({ @Module({
imports: [ imports: [
@ -50,6 +51,7 @@ import { TimeZoneEntity } from '../modules/timezone/entities';
DeviceNotificationEntity, DeviceNotificationEntity,
RegionEntity, RegionEntity,
TimeZoneEntity, TimeZoneEntity,
VisitorPasswordEntity,
], ],
namingStrategy: new SnakeNamingStrategy(), namingStrategy: new SnakeNamingStrategy(),
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))), synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),

View File

@ -0,0 +1,25 @@
import { Controller, Post, Param } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { AddDeviceStatusDto } from '../dtos/add.devices-status.dto';
import { DeviceStatusFirebaseService } from '../services/devices-status.service';
@ApiTags('Device Status Firebase Module')
@Controller({
version: '1',
path: 'device-status-firebase',
})
export class DeviceStatusFirebaseController {
constructor(
private readonly deviceStatusFirebaseService: DeviceStatusFirebaseService,
) {}
@ApiBearerAuth()
@Post(':deviceTuyaUuid')
async addDeviceStatus(
@Param('deviceTuyaUuid') deviceTuyaUuid: string,
): Promise<AddDeviceStatusDto> {
return this.deviceStatusFirebaseService.addDeviceStatusByDeviceUuid(
deviceTuyaUuid,
);
}
}

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { DeviceStatusFirebaseController } from './controllers/devices-status.controller';
import { DeviceStatusFirebaseService } from './services/devices-status.service';
import { DeviceRepository } from '@app/common/modules/device/repositories';
@Module({
providers: [DeviceStatusFirebaseService, DeviceRepository],
controllers: [DeviceStatusFirebaseController],
exports: [DeviceStatusFirebaseService],
})
export class DeviceStatusFirebaseModule {}

View File

@ -0,0 +1,38 @@
import {
IsString,
IsArray,
ValidateNested,
IsNotEmpty,
IsOptional,
} from 'class-validator';
import { Type } from 'class-transformer';
class StatusDto {
@IsString()
code: string;
@IsNotEmpty()
value: any;
}
export class AddDeviceStatusDto {
@IsString()
@IsOptional()
deviceUuid?: string;
@IsString()
deviceTuyaUuid: string;
@IsString()
@IsOptional()
productUuid?: string;
@IsString()
@IsOptional()
productType?: string;
@IsArray()
@ValidateNested({ each: true })
@Type(() => StatusDto)
status: StatusDto[];
}

View File

@ -0,0 +1,192 @@
import {
HttpException,
HttpStatus,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { AddDeviceStatusDto } from '../dtos/add.devices-status.dto';
import { DeviceRepository } from '@app/common/modules/device/repositories';
import { GetDeviceDetailsFunctionsStatusInterface } from 'src/device/interfaces/get.device.interface';
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
import { ConfigService } from '@nestjs/config';
import { firebaseDataBase } from '../../firebase.config';
import { Database, DataSnapshot, get, ref, set } from 'firebase/database';
@Injectable()
export class DeviceStatusFirebaseService {
private tuya: TuyaContext;
private firebaseDb: Database;
constructor(
private readonly configService: ConfigService,
private readonly deviceRepository: DeviceRepository,
) {
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
const tuyaEuUrl = this.configService.get<string>('tuya-config.TUYA_EU_URL');
this.tuya = new TuyaContext({
baseUrl: tuyaEuUrl,
accessKey,
secretKey,
});
// Initialize firebaseDb using firebaseDataBase function
this.firebaseDb = firebaseDataBase(this.configService);
}
async addDeviceStatusByDeviceUuid(
deviceTuyaUuid: string,
): Promise<AddDeviceStatusDto> {
try {
const device = await this.getDeviceByDeviceTuyaUuid(deviceTuyaUuid);
if (device.uuid) {
const deviceStatus = await this.getDevicesInstructionStatus(
device.uuid,
);
if (deviceStatus.productUuid) {
const deviceStatusSaved = await this.createDeviceStatusFirebase({
deviceUuid: device.uuid,
deviceTuyaUuid: deviceTuyaUuid,
status: deviceStatus.status,
productUuid: deviceStatus.productUuid,
productType: deviceStatus.productType,
});
return deviceStatusSaved;
}
}
} catch (error) {
throw new HttpException(
'Device Tuya UUID not found',
error.status || HttpStatus.BAD_REQUEST,
);
}
}
async addDeviceStatusToFirebase(
addDeviceStatusDto: AddDeviceStatusDto,
): Promise<AddDeviceStatusDto | null> {
try {
const device = await this.getDeviceByDeviceTuyaUuid(
addDeviceStatusDto.deviceTuyaUuid,
);
if (device?.uuid) {
return await this.createDeviceStatusFirebase({
deviceUuid: device.uuid,
...addDeviceStatusDto,
});
}
// Return null if device not found or no UUID
return null;
} catch (error) {
// Handle the error silently, perhaps log it internally or ignore it
return null;
}
}
async getDeviceByDeviceTuyaUuid(deviceTuyaUuid: string) {
return await this.deviceRepository.findOne({
where: {
deviceTuyaUuid,
},
relations: ['productDevice'],
});
}
async getDevicesInstructionStatus(deviceUuid: string) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails) {
throw new NotFoundException('Device Not Found');
}
const deviceStatus = await this.getDevicesInstructionStatusTuya(
deviceDetails.deviceTuyaUuid,
);
return {
productUuid: deviceDetails.productDevice.uuid,
productType: deviceDetails.productDevice.prodType,
status: deviceStatus.result[0].status,
};
} catch (error) {
throw new HttpException(
'Error fetching device functions status',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getDevicesInstructionStatusTuya(
deviceUuid: string,
): Promise<GetDeviceDetailsFunctionsStatusInterface> {
try {
const path = `/v1.0/iot-03/devices/status`;
const response = await this.tuya.request({
method: 'GET',
path,
query: {
device_ids: deviceUuid,
},
});
return response as GetDeviceDetailsFunctionsStatusInterface;
} catch (error) {
throw new HttpException(
'Error fetching device functions status from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getDeviceByDeviceUuid(
deviceUuid: string,
withProductDevice: boolean = true,
) {
return await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
...(withProductDevice && { relations: ['productDevice'] }),
});
}
async createDeviceStatusFirebase(
addDeviceStatusDto: AddDeviceStatusDto,
): Promise<any> {
const dataRef = ref(
this.firebaseDb,
`device-status/${addDeviceStatusDto.deviceUuid}`,
);
const snapshot: DataSnapshot = await get(dataRef);
const existingData = snapshot.val() || {};
// Assign default values if fields are not present
if (!existingData.deviceTuyaUuid) {
existingData.deviceTuyaUuid = addDeviceStatusDto.deviceTuyaUuid;
}
if (!existingData.productUuid) {
existingData.productUuid = addDeviceStatusDto.productUuid;
}
if (!existingData.productType) {
existingData.productType = addDeviceStatusDto.productType;
}
if (!existingData.status) {
existingData.status = [];
}
// Create a map to track existing status codes
const statusMap = new Map(
existingData.status.map((item) => [item.code, item.value]),
);
// Update or add status codes
for (const statusItem of addDeviceStatusDto.status) {
statusMap.set(statusItem.code, statusItem.value);
}
// Convert the map back to an array format
existingData.status = Array.from(statusMap, ([code, value]) => ({
code,
value,
}));
// Save the updated data to Firebase
await set(dataRef, existingData);
// Return the updated data
return existingData;
}
}

View File

@ -0,0 +1,24 @@
import { initializeApp } from 'firebase/app';
import { getDatabase } from 'firebase/database';
import { ConfigService } from '@nestjs/config';
export const initializeFirebaseApp = (configService: ConfigService) => {
const firebaseConfig = {
apiKey: configService.get<string>('FIREBASE_API_KEY'),
authDomain: configService.get<string>('FIREBASE_AUTH_DOMAIN'),
projectId: configService.get<string>('FIREBASE_PROJECT_ID'),
storageBucket: configService.get<string>('FIREBASE_STORAGE_BUCKET'),
messagingSenderId: configService.get<string>(
'FIREBASE_MESSAGING_SENDER_ID',
),
appId: configService.get<string>('FIREBASE_APP_ID'),
measurementId: configService.get<string>('FIREBASE_MEASUREMENT_ID'),
databaseURL: configService.get<string>('FIREBASE_DATABASE_URL'),
};
const app = initializeApp(firebaseConfig);
return getDatabase(app);
};
export const firebaseDataBase = (configService: ConfigService) =>
initializeFirebaseApp(configService);

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DeviceStatusFirebaseModule } from './devices-status/devices-status.module';
@Module({
imports: [DeviceStatusFirebaseModule],
providers: [],
exports: [],
})
export class FirebaseSharedModule {}

View File

@ -0,0 +1,4 @@
export function differenceInSeconds(date1: Date, date2: Date): number {
const diffInMilliseconds = date1.getTime() - date2.getTime();
return Math.floor(diffInMilliseconds / 1000);
}

View File

@ -7,8 +7,9 @@ import { TuyaWebSocketService } from './services/tuya.web.socket.service';
import { OneSignalService } from './services/onesignal.service'; import { OneSignalService } from './services/onesignal.service';
import { DeviceMessagesService } from './services/device.messages.service'; import { DeviceMessagesService } from './services/device.messages.service';
import { DeviceNotificationRepositoryModule } from '../modules/device-notification/device.notification.module'; import { DeviceRepositoryModule } from '../modules/device/device.repository.module';
import { DeviceNotificationRepository } from '../modules/device-notification/repositories'; import { DeviceNotificationRepository } from '../modules/device/repositories';
import { DeviceStatusFirebaseModule } from '../firebase/devices-status/devices-status.module';
@Global() @Global()
@Module({ @Module({
@ -23,6 +24,10 @@ import { DeviceNotificationRepository } from '../modules/device-notification/rep
], ],
exports: [HelperHashService, SpacePermissionService], exports: [HelperHashService, SpacePermissionService],
controllers: [], controllers: [],
imports: [SpaceRepositoryModule, DeviceNotificationRepositoryModule], imports: [
SpaceRepositoryModule,
DeviceRepositoryModule,
DeviceStatusFirebaseModule,
],
}) })
export class HelperModule {} export class HelperModule {}

View File

@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { DeviceNotificationRepository } from '@app/common/modules/device-notification/repositories'; import { DeviceNotificationRepository } from '@app/common/modules/device/repositories';
import { OneSignalService } from './onesignal.service'; import { OneSignalService } from './onesignal.service';
@Injectable() @Injectable()

View File

@ -1,8 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import TuyaWebsocket from '../../config/tuya-web-socket-config'; import TuyaWebsocket from '../../config/tuya-web-socket-config';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { OneSignalService } from './onesignal.service'; import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service';
import { DeviceMessagesService } from './device.messages.service';
@Injectable() @Injectable()
export class TuyaWebSocketService { export class TuyaWebSocketService {
@ -10,8 +9,7 @@ export class TuyaWebSocketService {
constructor( constructor(
private readonly configService: ConfigService, private readonly configService: ConfigService,
private readonly oneSignalService: OneSignalService, private readonly deviceStatusFirebaseService: DeviceStatusFirebaseService,
private readonly deviceMessagesService: DeviceMessagesService,
) { ) {
// Initialize the TuyaWebsocket client // Initialize the TuyaWebsocket client
this.client = new TuyaWebsocket({ this.client = new TuyaWebsocket({
@ -39,10 +37,11 @@ export class TuyaWebSocketService {
this.client.message(async (ws: WebSocket, message: any) => { this.client.message(async (ws: WebSocket, message: any) => {
try { try {
await this.deviceMessagesService.getDevicesUserNotifications( await this.deviceStatusFirebaseService.addDeviceStatusToFirebase({
message.payload.data.bizData.devId, deviceTuyaUuid: message.payload.data.bizData.devId,
message.payload.data.bizData, status: message.payload.data.bizData.properties,
); });
this.client.ackMessage(message.messageId); this.client.ackMessage(message.messageId);
} catch (error) { } catch (error) {
console.error('Error processing message:', error); console.error('Error processing message:', error);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +0,0 @@
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,19 +0,0 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class DeviceUserPermissionDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public deviceUuid: string;
@IsString()
@IsNotEmpty()
public permissionTypeUuid: string;
}

View File

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

View File

@ -1,43 +0,0 @@
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

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

View File

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

View File

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

View File

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

View File

@ -21,3 +21,35 @@ export class DeviceDto {
@IsNotEmpty() @IsNotEmpty()
productUuid: string; productUuid: string;
} }
export class DeviceUserPermissionDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public deviceUuid: string;
@IsString()
@IsNotEmpty()
public permissionTypeUuid: string;
}
export class DeviceNotificationDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public deviceUuid: string;
}

View File

@ -1,11 +1,11 @@
import { Column, Entity, ManyToOne, OneToMany, Unique, Index } from 'typeorm'; import { Column, Entity, ManyToOne, OneToMany, Unique, Index } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { DeviceDto } from '../dtos/device.dto'; import { DeviceDto, DeviceUserPermissionDto } from '../dtos/device.dto';
import { SpaceEntity } from '../../space/entities'; import { SpaceEntity } from '../../space/entities';
import { ProductEntity } from '../../product/entities'; import { ProductEntity } from '../../product/entities';
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities';
import { DeviceNotificationEntity } from '../../device-notification/entities';
import { UserEntity } from '../../user/entities'; import { UserEntity } from '../../user/entities';
import { DeviceNotificationDto } from '../dtos';
import { PermissionTypeEntity } from '../../permission/entities';
@Entity({ name: 'device' }) @Entity({ name: 'device' })
@Unique(['deviceTuyaUuid']) @Unique(['deviceTuyaUuid'])
@ -60,3 +60,68 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
Object.assign(this, partial); Object.assign(this, partial);
} }
} }
@Entity({ name: 'device-notification' })
@Unique(['userUuid', 'deviceUuid'])
export class DeviceNotificationEntity extends AbstractEntity<DeviceNotificationDto> {
@Column({
nullable: false,
})
public userUuid: string;
@Column({
nullable: false,
})
deviceUuid: string;
@ManyToOne(() => DeviceEntity, (device) => device.permission, {
nullable: false,
})
device: DeviceEntity;
@ManyToOne(() => UserEntity, (user) => user.userPermission, {
nullable: false,
})
user: UserEntity;
constructor(partial: Partial<DeviceNotificationEntity>) {
super();
Object.assign(this, partial);
}
}
@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

@ -1,6 +1,10 @@
import { DataSource, Repository } from 'typeorm'; import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { DeviceEntity } from '../entities'; import {
DeviceEntity,
DeviceNotificationEntity,
DeviceUserPermissionEntity,
} from '../entities';
@Injectable() @Injectable()
export class DeviceRepository extends Repository<DeviceEntity> { export class DeviceRepository extends Repository<DeviceEntity> {
@ -8,3 +12,15 @@ export class DeviceRepository extends Repository<DeviceEntity> {
super(DeviceEntity, dataSource.createEntityManager()); super(DeviceEntity, dataSource.createEntityManager());
} }
} }
@Injectable()
export class DeviceNotificationRepository extends Repository<DeviceNotificationEntity> {
constructor(private dataSource: DataSource) {
super(DeviceNotificationEntity, dataSource.createEntityManager());
}
}
@Injectable()
export class DeviceUserPermissionRepository extends Repository<DeviceUserPermissionEntity> {
constructor(private dataSource: DataSource) {
super(DeviceUserPermissionEntity, dataSource.createEntityManager());
}
}

View File

@ -2,7 +2,7 @@ import { Column, Entity, OneToMany } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { PermissionType } from '@app/common/constants/permission-type.enum'; import { PermissionType } from '@app/common/constants/permission-type.enum';
import { PermissionTypeDto } from '../dtos/permission.dto'; import { PermissionTypeDto } from '../dtos/permission.dto';
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities'; import { DeviceUserPermissionEntity } from '../../device/entities';
@Entity({ name: 'permission-type' }) @Entity({ name: 'permission-type' })
export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> { export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {

View File

@ -2,7 +2,7 @@ import { Column, Entity, OneToMany, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { RoleTypeDto } from '../dtos/role.type.dto'; import { RoleTypeDto } from '../dtos/role.type.dto';
import { RoleType } from '@app/common/constants/role.type.enum'; import { RoleType } from '@app/common/constants/role.type.enum';
import { UserRoleEntity } from '../../user-role/entities'; import { UserRoleEntity } from '../../user/entities';
@Entity({ name: 'role-type' }) @Entity({ name: 'role-type' })
@Unique(['type']) @Unique(['type'])

View File

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

View File

@ -1,11 +0,0 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class SpaceTypeDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public type: string;
}

View File

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

View File

@ -1,26 +0,0 @@
import { Column, Entity, OneToMany } from 'typeorm';
import { SpaceTypeDto } from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { SpaceEntity } from '../../space/entities';
@Entity({ name: 'space-type' })
export class SpaceTypeEntity extends AbstractEntity<SpaceTypeDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()', // Use gen_random_uuid() for default value
nullable: false,
})
public uuid: string;
@Column({
nullable: false,
})
type: string;
@OneToMany(() => SpaceEntity, (space) => space.spaceType)
spaces: SpaceEntity[];
constructor(partial: Partial<SpaceTypeEntity>) {
super();
Object.assign(this, partial);
}
}

View File

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

View File

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

View File

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

View File

@ -21,3 +21,13 @@ export class SpaceDto {
@IsNotEmpty() @IsNotEmpty()
public invitationCode: string; public invitationCode: string;
} }
export class SpaceTypeDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public type: string;
}

View File

@ -1,16 +1,37 @@
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm'; import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
import { SpaceDto } from '../dtos'; import { SpaceDto, SpaceTypeDto } from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { SpaceTypeEntity } from '../../space-type/entities'; import { UserSpaceEntity } from '../../user/entities';
import { UserSpaceEntity } from '../../user-space/entities';
import { DeviceEntity } from '../../device/entities'; import { DeviceEntity } from '../../device/entities';
@Entity({ name: 'space-type' })
export class SpaceTypeEntity extends AbstractEntity<SpaceTypeDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()',
nullable: false,
})
public uuid: string;
@Column({
nullable: false,
})
type: string;
@OneToMany(() => SpaceEntity, (space) => space.spaceType)
spaces: SpaceEntity[];
constructor(partial: Partial<SpaceTypeEntity>) {
super();
Object.assign(this, partial);
}
}
@Entity({ name: 'space' }) @Entity({ name: 'space' })
@Unique(['invitationCode']) @Unique(['invitationCode'])
export class SpaceEntity extends AbstractEntity<SpaceDto> { export class SpaceEntity extends AbstractEntity<SpaceDto> {
@Column({ @Column({
type: 'uuid', type: 'uuid',
default: () => 'gen_random_uuid()', // Use gen_random_uuid() for default value default: () => 'gen_random_uuid()',
nullable: false, nullable: false,
}) })
public uuid: string; public uuid: string;

View File

@ -1,6 +1,6 @@
import { DataSource, Repository } from 'typeorm'; import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { SpaceEntity } from '../entities/space.entity'; import { SpaceEntity, SpaceTypeEntity } from '../entities';
@Injectable() @Injectable()
export class SpaceRepository extends Repository<SpaceEntity> { export class SpaceRepository extends Repository<SpaceEntity> {
@ -8,3 +8,10 @@ export class SpaceRepository extends Repository<SpaceEntity> {
super(SpaceEntity, dataSource.createEntityManager()); super(SpaceEntity, dataSource.createEntityManager());
} }
} }
@Injectable()
export class SpaceTypeRepository extends Repository<SpaceTypeEntity> {
constructor(private dataSource: DataSource) {
super(SpaceTypeEntity, dataSource.createEntityManager());
}
}

View File

@ -1,11 +1,11 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { SpaceEntity } from './entities/space.entity'; import { SpaceEntity, SpaceTypeEntity } from './entities';
@Module({ @Module({
providers: [], providers: [],
exports: [], exports: [],
controllers: [], controllers: [],
imports: [TypeOrmModule.forFeature([SpaceEntity])], imports: [TypeOrmModule.forFeature([SpaceEntity, SpaceTypeEntity])],
}) })
export class SpaceRepositoryModule {} export class SpaceRepositoryModule {}

View File

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

View File

@ -1,19 +0,0 @@
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
export class UserNotificationDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public subscriptionUuid: string;
@IsBoolean()
@IsNotEmpty()
public active: boolean;
}

View File

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

View File

@ -1,27 +0,0 @@
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserNotificationDto } from '../dtos';
import { UserEntity } from '../../user/entities';
@Entity({ name: 'user-notification' })
@Unique(['user', 'subscriptionUuid'])
export class UserNotificationEntity extends AbstractEntity<UserNotificationDto> {
@ManyToOne(() => UserEntity, (user) => user.roles, {
nullable: false,
})
user: UserEntity;
@Column({
nullable: false,
})
subscriptionUuid: string;
@Column({
nullable: false,
default: true,
})
active: boolean;
constructor(partial: Partial<UserNotificationEntity>) {
super();
Object.assign(this, partial);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,19 +0,0 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class UserOtpDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public email: string;
@IsString()
@IsNotEmpty()
public otpCode: string;
@IsString()
@IsNotEmpty()
public expiryTime: string;
}

View File

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

View File

@ -1,34 +0,0 @@
import { Column, Entity } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserOtpDto } from '../dtos';
import { OtpType } from '../../../../src/constants/otp-type.enum';
@Entity({ name: 'user-otp' })
export class UserOtpEntity extends AbstractEntity<UserOtpDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()',
nullable: false,
})
public uuid: string;
@Column({ nullable: false })
email: string;
@Column({ nullable: false })
otpCode: string;
@Column({ nullable: false })
expiryTime: Date;
@Column({
type: 'enum',
enum: Object.values(OtpType),
})
type: OtpType;
constructor(partial: Partial<UserOtpEntity>) {
super();
Object.assign(this, partial);
}
}

View File

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

View File

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

View File

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

View File

@ -1,15 +0,0 @@
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

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

View File

@ -1,24 +0,0 @@
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

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

View File

@ -1,10 +0,0 @@
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

@ -1,10 +0,0 @@
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 +0,0 @@
export * from './user.space.dto';

View File

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

View File

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

View File

@ -1,29 +0,0 @@
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
import { UserSpaceDto } from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { SpaceEntity } from '../../space/entities';
import { UserEntity } from '../../user/entities';
@Entity({ name: 'user-space' })
@Unique(['user', 'space'])
export class UserSpaceEntity extends AbstractEntity<UserSpaceDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()', // Use gen_random_uuid() for default value
nullable: false,
})
public uuid: string;
@ManyToOne(() => UserEntity, (user) => user.userSpaces, { nullable: false })
user: UserEntity;
@ManyToOne(() => SpaceEntity, (space) => space.userSpaces, {
nullable: false,
})
space: SpaceEntity;
constructor(partial: Partial<UserSpaceEntity>) {
super();
Object.assign(this, partial);
}
}

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
import { IsNotEmpty, IsString } from 'class-validator'; import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
export class UserDto { export class UserDto {
@IsString() @IsString()
@ -21,3 +21,67 @@ export class UserDto {
@IsNotEmpty() @IsNotEmpty()
public lastName: string; public lastName: string;
} }
export class UserNotificationDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public subscriptionUuid: string;
@IsBoolean()
@IsNotEmpty()
public active: boolean;
}
export class UserOtpDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public email: string;
@IsString()
@IsNotEmpty()
public otpCode: string;
@IsString()
@IsNotEmpty()
public expiryTime: string;
}
export class UserRoleDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
@IsString()
@IsNotEmpty()
public roleTypeUuid: string;
}
export class UserSpaceDto {
@IsString()
@IsNotEmpty()
public uuid: string;
@IsString()
@IsNotEmpty()
public spaceUuid: string;
@IsString()
@IsNotEmpty()
public userUuid: string;
}

View File

@ -1,15 +1,31 @@
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities/device.user.permission.entity'; import {
import { Column, Entity, ManyToOne, OneToMany } from 'typeorm'; Column,
import { UserDto } from '../dtos'; DeleteDateColumn,
Entity,
ManyToOne,
OneToMany,
Unique,
} from 'typeorm';
import {
UserDto,
UserNotificationDto,
UserOtpDto,
UserRoleDto,
UserSpaceDto,
} from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserSpaceEntity } from '../../user-space/entities'; import {
import { UserRoleEntity } from '../../user-role/entities'; DeviceEntity,
import { DeviceNotificationEntity } from '../../device-notification/entities'; DeviceNotificationEntity,
import { UserNotificationEntity } from '../../user-notification/entities'; DeviceUserPermissionEntity,
import { DeviceEntity } from '../../device/entities'; } from '../../device/entities';
import { defaultProfilePicture } from '@app/common/constants/default.profile.picture'; import { defaultProfilePicture } from '@app/common/constants/default.profile.picture';
import { RegionEntity } from '../../region/entities'; import { RegionEntity } from '../../region/entities';
import { TimeZoneEntity } from '../../timezone/entities'; import { TimeZoneEntity } from '../../timezone/entities';
import { OtpType } from '../../../../src/constants/otp-type.enum';
import { RoleTypeEntity } from '../../role-type/entities';
import { SpaceEntity } from '../../space/entities';
import { VisitorPasswordEntity } from '../../visitor-password/entities';
@Entity({ name: 'user' }) @Entity({ name: 'user' })
export class UserEntity extends AbstractEntity<UserDto> { export class UserEntity extends AbstractEntity<UserDto> {
@ -94,8 +110,112 @@ export class UserEntity extends AbstractEntity<UserDto> {
nullable: true, nullable: true,
}) })
timezone: TimeZoneEntity; timezone: TimeZoneEntity;
@OneToMany(
() => VisitorPasswordEntity,
(visitorPassword) => visitorPassword.user,
)
public visitorPasswords: VisitorPasswordEntity[];
constructor(partial: Partial<UserEntity>) { constructor(partial: Partial<UserEntity>) {
super(); super();
Object.assign(this, partial); Object.assign(this, partial);
} }
} }
@Entity({ name: 'user-notification' })
@Unique(['user', 'subscriptionUuid'])
export class UserNotificationEntity extends AbstractEntity<UserNotificationDto> {
@ManyToOne(() => UserEntity, (user) => user.roles, {
nullable: false,
})
user: UserEntity;
@Column({
nullable: false,
})
subscriptionUuid: string;
@Column({
nullable: false,
default: true,
})
active: boolean;
constructor(partial: Partial<UserNotificationEntity>) {
super();
Object.assign(this, partial);
}
}
@Entity({ name: 'user-otp' })
export class UserOtpEntity extends AbstractEntity<UserOtpDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()',
nullable: false,
})
public uuid: string;
@Column({ nullable: false })
email: string;
@Column({ nullable: false })
otpCode: string;
@Column({ nullable: false })
expiryTime: Date;
@Column({
type: 'enum',
enum: Object.values(OtpType),
})
type: OtpType;
@DeleteDateColumn({ nullable: true })
deletedAt?: Date;
constructor(partial: Partial<UserOtpEntity>) {
super();
Object.assign(this, partial);
}
}
@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);
}
}
@Entity({ name: 'user-space' })
@Unique(['user', 'space'])
export class UserSpaceEntity extends AbstractEntity<UserSpaceDto> {
@Column({
type: 'uuid',
default: () => 'gen_random_uuid()', // Use gen_random_uuid() for default value
nullable: false,
})
public uuid: string;
@ManyToOne(() => UserEntity, (user) => user.userSpaces, { nullable: false })
user: UserEntity;
@ManyToOne(() => SpaceEntity, (space) => space.userSpaces, {
nullable: false,
})
space: SpaceEntity;
constructor(partial: Partial<UserSpaceEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -1,6 +1,12 @@
import { DataSource, Repository } from 'typeorm'; import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { UserEntity } from '../entities/user.entity'; import {
UserEntity,
UserNotificationEntity,
UserOtpEntity,
UserRoleEntity,
UserSpaceEntity,
} from '../entities/';
@Injectable() @Injectable()
export class UserRepository extends Repository<UserEntity> { export class UserRepository extends Repository<UserEntity> {
@ -8,3 +14,31 @@ export class UserRepository extends Repository<UserEntity> {
super(UserEntity, dataSource.createEntityManager()); super(UserEntity, dataSource.createEntityManager());
} }
} }
@Injectable()
export class UserNotificationRepository extends Repository<UserNotificationEntity> {
constructor(private dataSource: DataSource) {
super(UserNotificationEntity, dataSource.createEntityManager());
}
}
@Injectable()
export class UserOtpRepository extends Repository<UserOtpEntity> {
constructor(private dataSource: DataSource) {
super(UserOtpEntity, dataSource.createEntityManager());
}
}
@Injectable()
export class UserRoleRepository extends Repository<UserRoleEntity> {
constructor(private dataSource: DataSource) {
super(UserRoleEntity, dataSource.createEntityManager());
}
}
@Injectable()
export class UserSpaceRepository extends Repository<UserSpaceEntity> {
constructor(private dataSource: DataSource) {
super(UserSpaceEntity, dataSource.createEntityManager());
}
}

View File

@ -1,11 +1,25 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from './entities/user.entity'; import {
UserEntity,
UserNotificationEntity,
UserOtpEntity,
UserRoleEntity,
UserSpaceEntity,
} from './entities';
@Module({ @Module({
providers: [], providers: [],
exports: [], exports: [],
controllers: [], controllers: [],
imports: [TypeOrmModule.forFeature([UserEntity])], imports: [
TypeOrmModule.forFeature([
UserEntity,
UserNotificationEntity,
UserOtpEntity,
UserRoleEntity,
UserSpaceEntity,
]),
],
}) })
export class UserRepositoryModule {} export class UserRepositoryModule {}

View File

@ -0,0 +1 @@
export * from './visitor-password.dto';

View File

@ -1,15 +1,15 @@
import { IsNotEmpty, IsString } from 'class-validator'; import { IsNotEmpty, IsString } from 'class-validator';
export class DeviceNotificationDto { export class VisitorPasswordDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
public uuid: string; public uuid: string;
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
public userUuid: string; public authorizerUuid: string;
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
public deviceUuid: string; public passwordTuyaUuid: string;
} }

View File

@ -0,0 +1 @@
export * from './visitor-password.entity';

View File

@ -0,0 +1,25 @@
import { Column, Entity, ManyToOne, JoinColumn, Index } from 'typeorm';
import { VisitorPasswordDto } from '../dtos';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { UserEntity } from '../../user/entities/user.entity';
@Entity({ name: 'visitor-password' })
@Index('IDX_PASSWORD_TUYA_UUID', ['passwordTuyaUuid'])
export class VisitorPasswordEntity extends AbstractEntity<VisitorPasswordDto> {
@Column({
nullable: false,
unique: true,
})
public passwordTuyaUuid: string;
@ManyToOne(() => UserEntity, (user) => user.visitorPasswords, {
nullable: false,
})
@JoinColumn({ name: 'authorizer_uuid' })
public user: UserEntity;
constructor(partial: Partial<VisitorPasswordEntity>) {
super();
Object.assign(this, partial);
}
}

View File

@ -0,0 +1 @@
export * from './visitor-password.repository';

View File

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

View File

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

View File

@ -7,13 +7,12 @@ import { ConfigModule } from '@nestjs/config';
import { RoleTypeRepositoryModule } from '../modules/role-type/role.type.repository.module'; import { RoleTypeRepositoryModule } from '../modules/role-type/role.type.repository.module';
import { RoleTypeRepository } from '../modules/role-type/repositories'; import { RoleTypeRepository } from '../modules/role-type/repositories';
import { RoleTypeSeeder } from './services/role.type.seeder'; import { RoleTypeSeeder } from './services/role.type.seeder';
import { SpaceTypeRepository } from '../modules/space-type/repositories'; import { SpaceTypeRepository } from '../modules/space/repositories';
import { SpaceTypeSeeder } from './services/space.type.seeder'; import { SpaceTypeSeeder } from './services/space.type.seeder';
import { SpaceTypeRepositoryModule } from '../modules/space-type/space.type.repository.module'; import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
import { SuperAdminSeeder } from './services/supper.admin.seeder'; import { SuperAdminSeeder } from './services/supper.admin.seeder';
import { UserRepository } from '../modules/user/repositories'; import { UserRepository } from '../modules/user/repositories';
import { UserRoleRepository } from '../modules/user-role/repositories'; import { UserRoleRepository } from '../modules/user/repositories';
import { UserRoleRepositoryModule } from '../modules/user-role/user.role.repository.module';
import { UserRepositoryModule } from '../modules/user/user.repository.module'; import { UserRepositoryModule } from '../modules/user/user.repository.module';
import { RegionSeeder } from './services/regions.seeder'; import { RegionSeeder } from './services/regions.seeder';
import { RegionRepository } from '../modules/region/repositories'; import { RegionRepository } from '../modules/region/repositories';
@ -44,8 +43,7 @@ import { TimeZoneRepository } from '../modules/timezone/repositories';
PermissionTypeRepositoryModule, PermissionTypeRepositoryModule,
RoleTypeRepositoryModule, RoleTypeRepositoryModule,
UserRepositoryModule, UserRepositoryModule,
UserRoleRepositoryModule, SpaceRepositoryModule,
SpaceTypeRepositoryModule,
], ],
}) })
export class SeederModule {} export class SeederModule {}

View File

@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { SpaceType } from '../../constants/space-type.enum'; import { SpaceType } from '../../constants/space-type.enum';
import { SpaceTypeRepository } from '../../modules/space-type/repositories'; import { SpaceTypeRepository } from '../../modules/space/repositories';
@Injectable() @Injectable()
export class SpaceTypeSeeder { export class SpaceTypeSeeder {

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { UserRepository } from '@app/common/modules/user/repositories'; import { UserRepository } from '@app/common/modules/user/repositories';
import { RoleType } from '@app/common/constants/role.type.enum'; import { RoleType } from '@app/common/constants/role.type.enum';
import { UserRoleRepository } from '@app/common/modules/user-role/repositories'; import { UserRoleRepository } from '@app/common/modules/user/repositories';
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories'; import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { HelperHashService } from '../../helper/services'; import { HelperHashService } from '../../helper/services';

View File

@ -19,7 +19,7 @@ export class EmailService {
}; };
} }
async sendOTPEmail( async sendEmail(
email: string, email: string,
subject: string, subject: string,
message: string, message: string,

1077
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"express-rate-limit": "^7.1.5", "express-rate-limit": "^7.1.5",
"firebase": "^10.12.5",
"helmet": "^7.1.0", "helmet": "^7.1.0",
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"morgan": "^1.10.0", "morgan": "^1.10.0",

View File

@ -23,6 +23,7 @@ import { LoggingInterceptor } from './interceptors/logging.interceptor';
import { AutomationModule } from './automation/automation.module'; import { AutomationModule } from './automation/automation.module';
import { RegionModule } from './region/region.module'; import { RegionModule } from './region/region.module';
import { TimeZoneModule } from './timezone/timezone.module'; import { TimeZoneModule } from './timezone/timezone.module';
import { VisitorPasswordModule } from './vistor-password/visitor-password.module';
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot({ ConfigModule.forRoot({
@ -48,6 +49,7 @@ import { TimeZoneModule } from './timezone/timezone.module';
DoorLockModule, DoorLockModule,
RegionModule, RegionModule,
TimeZoneModule, TimeZoneModule,
VisitorPasswordModule,
], ],
controllers: [AuthenticationController], controllers: [AuthenticationController],
providers: [ providers: [

View File

@ -2,14 +2,16 @@ import { Module } from '@nestjs/common';
import { AuthenticationController } from './controllers/authentication.controller'; import { AuthenticationController } from './controllers/authentication.controller';
import { AuthenticationService } from './services/authentication.service'; import { AuthenticationService } from './services/authentication.service';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { UserRepositoryModule } from '../../libs/common/src/modules/user/user.repository.module'; import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
import { CommonModule } from '../../libs/common/src'; import { CommonModule } from '../../libs/common/src';
import { UserAuthController } from './controllers'; import { UserAuthController } from './controllers';
import { UserAuthService } from './services'; import { UserAuthService } from './services';
import { UserRepository } from '../../libs/common/src/modules/user/repositories'; import { UserRepository } from '@app/common/modules/user/repositories';
import { UserSessionRepository } from '../../libs/common/src/modules/session/repositories/session.repository'; import { UserSessionRepository } from '@app/common/modules/session/repositories/session.repository';
import { UserOtpRepository } from '../../libs/common/src/modules/user-otp/repositories/user-otp.repository'; import {
import { UserRoleRepository } from '@app/common/modules/user-role/repositories'; UserRoleRepository,
UserOtpRepository,
} from '@app/common/modules/user/repositories';
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories'; import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
@Module({ @Module({

View File

@ -71,7 +71,7 @@ export class UserAuthController {
return { return {
statusCode: HttpStatus.OK, statusCode: HttpStatus.OK,
data: { data: {
otp: otpCode, ...otpCode,
}, },
message: 'Otp Send Successfully', message: 'Otp Send Successfully',
}; };

View File

@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { IsPasswordStrong } from 'src/validators/password.validator'; import { IsPasswordStrong } from 'src/validators/password.validator';
export class UserSignUpDto { export class UserSignUpDto {
@ -38,4 +38,8 @@ export class UserSignUpDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
public lastName: string; public lastName: string;
@IsString()
@IsOptional()
public regionUuid: string;
} }

View File

@ -11,4 +11,9 @@ export class UserLoginDto {
@IsString() @IsString()
@IsOptional() @IsOptional()
password: string; password: string;
@ApiProperty()
@IsString()
@IsOptional()
regionUuid?: string;
} }

View File

@ -1,6 +1,12 @@
import { OtpType } from '../../../libs/common/src/constants/otp-type.enum'; import { OtpType } from '../../../libs/common/src/constants/otp-type.enum';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsEnum, IsNotEmpty, IsString } from 'class-validator'; import {
IsEmail,
IsEnum,
IsNotEmpty,
IsOptional,
IsString,
} from 'class-validator';
export class UserOtpDto { export class UserOtpDto {
@ApiProperty() @ApiProperty()
@ -12,6 +18,11 @@ export class UserOtpDto {
@IsEnum(OtpType) @IsEnum(OtpType)
@IsNotEmpty() @IsNotEmpty()
type: OtpType; type: OtpType;
@ApiProperty()
@IsOptional()
@IsString()
regionUuid?: string;
} }
export class VerifyOtpDto extends UserOtpDto { export class VerifyOtpDto extends UserOtpDto {

View File

@ -1,5 +1,5 @@
import { RoleTypeRepository } from './../../../libs/common/src/modules/role-type/repositories/role.type.repository'; import { RoleTypeRepository } from './../../../libs/common/src/modules/role-type/repositories/role.type.repository';
import { UserRoleRepository } from './../../../libs/common/src/modules/user-role/repositories/user.role.repository'; import { UserRoleRepository } from './../../../libs/common/src/modules/user/repositories/user.repository';
import { UserRepository } from '../../../libs/common/src/modules/user/repositories'; import { UserRepository } from '../../../libs/common/src/modules/user/repositories';
import { import {
BadRequestException, BadRequestException,
@ -12,12 +12,15 @@ import { HelperHashService } from '../../../libs/common/src/helper/services';
import { UserLoginDto } from '../dtos/user-login.dto'; import { UserLoginDto } from '../dtos/user-login.dto';
import { AuthService } from '../../../libs/common/src/auth/services/auth.service'; import { AuthService } from '../../../libs/common/src/auth/services/auth.service';
import { UserSessionRepository } from '../../../libs/common/src/modules/session/repositories/session.repository'; import { UserSessionRepository } from '../../../libs/common/src/modules/session/repositories/session.repository';
import { UserOtpRepository } from '../../../libs/common/src/modules/user-otp/repositories/user-otp.repository'; import { UserOtpRepository } from '../../../libs/common/src/modules/user/repositories/user.repository';
import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos'; import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos';
import { EmailService } from '../../../libs/common/src/util/email.service'; import { EmailService } from '../../../libs/common/src/util/email.service';
import { OtpType } from '../../../libs/common/src/constants/otp-type.enum'; import { OtpType } from '../../../libs/common/src/constants/otp-type.enum';
import { UserEntity } from '../../../libs/common/src/modules/user/entities/user.entity'; import { UserEntity } from '../../../libs/common/src/modules/user/entities/user.entity';
import * as argon2 from 'argon2'; import * as argon2 from 'argon2';
import { differenceInSeconds } from '@app/common/helper/differenceInSeconds';
import { LessThan, MoreThan } from 'typeorm';
import { ConfigService } from '@nestjs/config';
@Injectable() @Injectable()
export class UserAuthService { export class UserAuthService {
@ -30,6 +33,7 @@ export class UserAuthService {
private readonly emailService: EmailService, private readonly emailService: EmailService,
private readonly userRoleRepository: UserRoleRepository, private readonly userRoleRepository: UserRoleRepository,
private readonly roleTypeRepository: RoleTypeRepository, private readonly roleTypeRepository: RoleTypeRepository,
private readonly configService: ConfigService,
) {} ) {}
async signUp(userSignUpDto: UserSignUpDto): Promise<UserEntity> { async signUp(userSignUpDto: UserSignUpDto): Promise<UserEntity> {
@ -44,9 +48,17 @@ export class UserAuthService {
); );
try { try {
const { regionUuid, ...rest } = userSignUpDto;
const user = await this.userRepository.save({ const user = await this.userRepository.save({
...userSignUpDto, ...rest,
password: hashedPassword, password: hashedPassword,
region: regionUuid
? {
uuid: regionUuid,
}
: {
regionName: 'United Arab Emirates',
},
}); });
return user; return user;
@ -80,41 +92,46 @@ export class UserAuthService {
} }
async userLogin(data: UserLoginDto) { async userLogin(data: UserLoginDto) {
const user = await this.authService.validateUser(data.email, data.password); try {
const user = await this.authService.validateUser(
if (!user) { data.email,
throw new UnauthorizedException('Invalid login credentials.'); data.password,
} data.regionUuid,
);
const session = await Promise.all([ if (!user) {
await this.sessionRepository.update( throw new UnauthorizedException('Invalid login credentials.');
{ userId: user.id }, }
{ const session = await Promise.all([
isLoggedOut: true, await this.sessionRepository.update(
}, { userId: user.id },
), {
await this.authService.createSession({ isLoggedOut: true,
},
),
await this.authService.createSession({
userId: user.uuid,
loginTime: new Date(),
isLoggedOut: false,
}),
]);
return await this.authService.login({
email: user.email,
userId: user.uuid, userId: user.uuid,
loginTime: new Date(), uuid: user.uuid,
isLoggedOut: false, roles: user?.roles?.map((role) => {
}), return { uuid: role.uuid, type: role.roleType.type };
]); }),
sessionId: session[1].uuid,
return await this.authService.login({ });
email: user.email, } catch (error) {
userId: user.uuid, throw new BadRequestException('Invalid credentials');
uuid: user.uuid, }
roles: user?.roles?.map((role) => {
return { uuid: role.uuid, type: role.roleType.type };
}),
sessionId: session[1].uuid,
});
} }
async deleteUser(uuid: string) { async deleteUser(uuid: string) {
const user = await this.findOneById(uuid); const user = await this.findOneById(uuid);
if (!user) { if (!user) {
throw new BadRequestException('User does not found'); throw new BadRequestException('User not found');
} }
return await this.userRepository.update({ uuid }, { isActive: false }); return await this.userRepository.update({ uuid }, { isActive: false });
} }
@ -123,8 +140,61 @@ export class UserAuthService {
return await this.userRepository.findOne({ where: { uuid: id } }); return await this.userRepository.findOne({ where: { uuid: id } });
} }
async generateOTP(data: UserOtpDto): Promise<string> { async generateOTP(data: UserOtpDto): Promise<{
await this.otpRepository.delete({ email: data.email, type: data.type }); otpCode: string;
cooldown: number;
}> {
const otpLimiter = new Date();
otpLimiter.setDate(
otpLimiter.getDate() - this.configService.get<number>('OTP_LIMITER'),
);
const userExists = await this.userRepository.exists({
where: {
region: data.regionUuid
? {
uuid: data.regionUuid,
}
: undefined,
email: data.email,
isUserVerified: data.type === OtpType.PASSWORD ? true : undefined,
},
});
if (!userExists) {
throw new BadRequestException('User not found');
}
await this.otpRepository.softDelete({ email: data.email, type: data.type });
await this.otpRepository.delete({
email: data.email,
type: data.type,
createdAt: LessThan(otpLimiter),
});
const countOfOtp = await this.otpRepository.count({
withDeleted: true,
where: {
email: data.email,
type: data.type,
createdAt: MoreThan(otpLimiter),
},
});
const lastOtp = await this.otpRepository.findOne({
where: { email: data.email, type: data.type },
order: { createdAt: 'DESC' },
withDeleted: true,
});
let cooldown = 30 * Math.pow(2, countOfOtp - 1);
if (lastOtp) {
const now = new Date();
const timeSinceLastOtp = differenceInSeconds(now, lastOtp.createdAt);
if (timeSinceLastOtp < cooldown) {
throw new BadRequestException({
message: `Please wait ${cooldown - timeSinceLastOtp} more seconds before requesting a new OTP.`,
data: {
cooldown: cooldown - timeSinceLastOtp,
},
});
}
}
const otpCode = Math.floor(100000 + Math.random() * 900000).toString(); const otpCode = Math.floor(100000 + Math.random() * 900000).toString();
const expiryTime = new Date(); const expiryTime = new Date();
expiryTime.setMinutes(expiryTime.getMinutes() + 1); expiryTime.setMinutes(expiryTime.getMinutes() + 1);
@ -134,10 +204,19 @@ export class UserAuthService {
expiryTime, expiryTime,
type: data.type, type: data.type,
}); });
const countOfOtpToReturn = await this.otpRepository.count({
withDeleted: true,
where: {
email: data.email,
type: data.type,
createdAt: MoreThan(otpLimiter),
},
});
cooldown = 30 * Math.pow(2, countOfOtpToReturn - 1);
const subject = 'OTP send successfully'; const subject = 'OTP send successfully';
const message = `Your OTP code is ${otpCode}`; const message = `Your OTP code is ${otpCode}`;
this.emailService.sendOTPEmail(data.email, subject, message); this.emailService.sendEmail(data.email, subject, message);
return otpCode; return { otpCode, cooldown };
} }
async verifyOTP(data: VerifyOtpDto): Promise<boolean> { async verifyOTP(data: VerifyOtpDto): Promise<boolean> {

View File

@ -7,9 +7,10 @@ import { SpaceRepository } from '@app/common/modules/space/repositories';
import { DeviceService } from 'src/device/services'; import { DeviceService } from 'src/device/services';
import { DeviceRepository } from '@app/common/modules/device/repositories'; import { DeviceRepository } from '@app/common/modules/device/repositories';
import { ProductRepository } from '@app/common/modules/product/repositories'; import { ProductRepository } from '@app/common/modules/product/repositories';
import { DeviceStatusFirebaseModule } from '@app/common/firebase/devices-status/devices-status.module';
@Module({ @Module({
imports: [ConfigModule, SpaceRepositoryModule], imports: [ConfigModule, SpaceRepositoryModule, DeviceStatusFirebaseModule],
controllers: [AutomationController], controllers: [AutomationController],
providers: [ providers: [
AutomationService, AutomationService,

View File

@ -4,21 +4,13 @@ import { BuildingController } from './controllers/building.controller';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module'; import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
import { SpaceRepository } from '@app/common/modules/space/repositories'; import { SpaceRepository } from '@app/common/modules/space/repositories';
import { SpaceTypeRepositoryModule } from '@app/common/modules/space-type/space.type.repository.module'; import { SpaceTypeRepository } from '@app/common/modules/space/repositories';
import { SpaceTypeRepository } from '@app/common/modules/space-type/repositories'; import { UserSpaceRepository } from '@app/common/modules/user/repositories';
import { UserSpaceRepositoryModule } from '@app/common/modules/user-space/user.space.repository.module';
import { UserSpaceRepository } from '@app/common/modules/user-space/repositories';
import { UserRepository } from '@app/common/modules/user/repositories'; import { UserRepository } from '@app/common/modules/user/repositories';
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module'; import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
@Module({ @Module({
imports: [ imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
ConfigModule,
SpaceRepositoryModule,
SpaceTypeRepositoryModule,
UserSpaceRepositoryModule,
UserRepositoryModule,
],
controllers: [BuildingController], controllers: [BuildingController],
providers: [ providers: [
BuildingService, BuildingService,

View File

@ -1,5 +1,5 @@
import { GetBuildingChildDto } from '../dtos/get.building.dto'; import { GetBuildingChildDto } from '../dtos/get.building.dto';
import { SpaceTypeRepository } from '../../../libs/common/src/modules/space-type/repositories/space.type.repository'; import { SpaceTypeRepository } from '../../../libs/common/src/modules/space/repositories/space.repository';
import { import {
Injectable, Injectable,
HttpException, HttpException,
@ -17,7 +17,7 @@ import {
} from '../interface/building.interface'; } from '../interface/building.interface';
import { SpaceEntity } from '@app/common/modules/space/entities'; import { SpaceEntity } from '@app/common/modules/space/entities';
import { UpdateBuildingNameDto } from '../dtos/update.building.dto'; import { UpdateBuildingNameDto } from '../dtos/update.building.dto';
import { UserSpaceRepository } from '@app/common/modules/user-space/repositories'; import { UserSpaceRepository } from '@app/common/modules/user/repositories';
@Injectable() @Injectable()
export class BuildingService { export class BuildingService {

Some files were not shown because too many files have changed in this diff Show More