Add Comprehensive Door Lock Module Enhancements

This commit is contained in:
faris Aljohari
2024-08-27 22:09:33 +03:00
parent ef4541a371
commit 2a596d3b33
2 changed files with 182 additions and 70 deletions

View File

@ -5,10 +5,24 @@ import { ConfigModule } from '@nestjs/config';
import { DeviceRepositoryModule } from '@app/common/modules/device'; import { DeviceRepositoryModule } from '@app/common/modules/device';
import { DeviceRepository } from '@app/common/modules/device/repositories'; import { DeviceRepository } from '@app/common/modules/device/repositories';
import { PasswordEncryptionService } from './services/encryption.services'; import { PasswordEncryptionService } from './services/encryption.services';
import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/repositories';
import { DeviceService } from 'src/device/services';
import { ProductRepository } from '@app/common/modules/product/repositories';
import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service';
import { SpaceRepository } from '@app/common/modules/space/repositories';
@Module({ @Module({
imports: [ConfigModule, DeviceRepositoryModule], imports: [ConfigModule, DeviceRepositoryModule],
controllers: [DoorLockController], controllers: [DoorLockController],
providers: [DoorLockService, PasswordEncryptionService, DeviceRepository], providers: [
DoorLockService,
PasswordEncryptionService,
DeviceRepository,
VisitorPasswordRepository,
DeviceService,
ProductRepository,
DeviceStatusFirebaseService,
SpaceRepository,
],
exports: [DoorLockService], exports: [DoorLockService],
}) })
export class DoorLockModule {} export class DoorLockModule {}

View File

@ -22,6 +22,8 @@ import { AddDoorLockOfflineTempMultipleTimeDto } from '../dtos/add.offline-temp.
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
import { UpdateDoorLockOfflineTempDto } from '../dtos/update.offline-temp.dto'; import { UpdateDoorLockOfflineTempDto } from '../dtos/update.offline-temp.dto';
import { defaultDoorLockPass } from '@app/common/constants/default.door-lock-pass'; import { defaultDoorLockPass } from '@app/common/constants/default.door-lock-pass';
import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/repositories';
import { DeviceService } from 'src/device/services';
@Injectable() @Injectable()
export class DoorLockService { export class DoorLockService {
@ -29,7 +31,9 @@ export class DoorLockService {
constructor( constructor(
private readonly configService: ConfigService, private readonly configService: ConfigService,
private readonly deviceRepository: DeviceRepository, private readonly deviceRepository: DeviceRepository,
private readonly deviceService: DeviceService,
private readonly passwordEncryptionService: PasswordEncryptionService, private readonly passwordEncryptionService: PasswordEncryptionService,
private readonly visitorPasswordRepository: VisitorPasswordRepository,
) { ) {
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY'); const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY'); const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
@ -105,6 +109,10 @@ export class DoorLockService {
HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST,
); );
} }
const deviceTuyaDetails =
await this.deviceService.getDeviceDetailsByDeviceIdTuya(
deviceDetails.deviceTuyaUuid,
);
const passwords = await this.getTemporaryOfflinePasswordsTuya( const passwords = await this.getTemporaryOfflinePasswordsTuya(
deviceDetails.deviceTuyaUuid, deviceDetails.deviceTuyaUuid,
'multiple', 'multiple',
@ -115,23 +123,37 @@ export class DoorLockService {
} }
if (passwords.result.records.length > 0) { if (passwords.result.records.length > 0) {
return fromVisitor return fromVisitor
? convertKeysToCamelCase(passwords.result.records).map((password) => { ? Promise.all(
const timestampInSeconds = Math.floor(Date.now() / 1000); convertKeysToCamelCase(passwords.result.records).map(
return { async (password) => {
passwordId: `${password.pwdId}`, const passwordFromDB = await this.getVisitorPasswordFromDB(
invalidTime: `${password.gmtExpired}`, password.pwdId,
effectiveTime: `${password.gmtStart}`, );
passwordCreated: `${password.gmtCreate}`, const timestampInSeconds = Math.floor(Date.now() / 1000);
createdTime: password.pwdName, return {
passwordType: 'OFFLINE_MULTIPLE', passwordId: `${password.pwdId}`,
deviceUuid: doorLockUuid, invalidTime: `${password.gmtExpired}`,
passwordStatus: isExpired effectiveTime: `${password.gmtStart}`,
? 'EXPIRED' passwordCreated: `${password.gmtCreate}`,
: timestampInSeconds > password.effectiveTime createdTime: password.pwdName,
? 'EFFECTIVE' passwordType: 'OFFLINE_MULTIPLE',
: 'TO_BE_EFFECTIVE', deviceUuid: doorLockUuid,
}; deviceName: deviceTuyaDetails.name,
}) passwordStatus: isExpired
? 'EXPIRED'
: timestampInSeconds > password.effectiveTime
? 'EFFECTIVE'
: 'TO_BE_EFFECTIVE',
authorizerEmail: passwordFromDB
? passwordFromDB.user.email
: 'OTHER',
authorizerDate: passwordFromDB
? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}`
: '',
};
},
),
)
: convertKeysToCamelCase(passwords.result.records); : convertKeysToCamelCase(passwords.result.records);
} }
return passwords; return passwords;
@ -158,6 +180,10 @@ export class DoorLockService {
HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST,
); );
} }
const deviceTuyaDetails =
await this.deviceService.getDeviceDetailsByDeviceIdTuya(
deviceDetails.deviceTuyaUuid,
);
const passwords = await this.getTemporaryOfflinePasswordsTuya( const passwords = await this.getTemporaryOfflinePasswordsTuya(
deviceDetails.deviceTuyaUuid, deviceDetails.deviceTuyaUuid,
'once', 'once',
@ -168,23 +194,38 @@ export class DoorLockService {
} }
if (passwords.result.records.length > 0) { if (passwords.result.records.length > 0) {
return fromVisitor return fromVisitor
? convertKeysToCamelCase(passwords.result.records).map((password) => { ? Promise.all(
const timestampInSeconds = Math.floor(Date.now() / 1000); convertKeysToCamelCase(passwords.result.records).map(
return { async (password) => {
passwordId: `${password.pwdId}`, const passwordFromDB = await this.getVisitorPasswordFromDB(
invalidTime: `${password.gmtExpired}`, password.pwdId,
effectiveTime: `${password.gmtStart}`, );
createdTime: `${password.gmtCreate}`,
passwordName: password.pwdName, const timestampInSeconds = Math.floor(Date.now() / 1000);
passwordType: 'OFFLINE_ONETIME', return {
deviceUuid: doorLockUuid, passwordId: `${password.pwdId}`,
passwordStatus: isExpired invalidTime: `${password.gmtExpired}`,
? 'EXPIRED' effectiveTime: `${password.gmtStart}`,
: timestampInSeconds > password.gmtStart createdTime: `${password.gmtCreate}`,
? 'EFFECTIVE' passwordName: password.pwdName,
: 'TO_BE_EFFECTIVE', passwordType: 'OFFLINE_ONETIME',
}; deviceUuid: doorLockUuid,
}) deviceName: deviceTuyaDetails.name,
passwordStatus: isExpired
? 'EXPIRED'
: timestampInSeconds > password.gmtStart
? 'EFFECTIVE'
: 'TO_BE_EFFECTIVE',
authorizerEmail: passwordFromDB
? passwordFromDB.user.email
: 'OTHER',
authorizerDate: passwordFromDB
? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}`
: '',
};
},
),
)
: convertKeysToCamelCase(passwords.result.records); : convertKeysToCamelCase(passwords.result.records);
} }
@ -212,6 +253,10 @@ export class DoorLockService {
HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST,
); );
} }
const deviceTuyaDetails =
await this.deviceService.getDeviceDetailsByDeviceIdTuya(
deviceDetails.deviceTuyaUuid,
);
const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya( const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya(
deviceDetails.deviceTuyaUuid, deviceDetails.deviceTuyaUuid,
isExpired, isExpired,
@ -240,24 +285,36 @@ export class DoorLockService {
}); });
return fromVisitor return fromVisitor
? convertKeysToCamelCase(passwordFiltered).map((password) => { ? Promise.all(
const timestampInSeconds = Math.floor(Date.now() / 1000); convertKeysToCamelCase(passwordFiltered).map(async (password) => {
return { const passwordFromDB = await this.getVisitorPasswordFromDB(
passwordId: `${password.id}`, password.id,
invalidTime: `${password.invalidTime}`, );
effectiveTime: `${password.effectiveTime}`, const timestampInSeconds = Math.floor(Date.now() / 1000);
createdTime: '', return {
scheduleList: password?.scheduleList, passwordId: `${password.id}`,
passwordName: password.name, invalidTime: `${password.invalidTime}`,
passwordType: 'ONLINE_MULTIPLE', effectiveTime: `${password.effectiveTime}`,
deviceUuid: doorLockUuid, createdTime: '',
passwordStatus: isExpired scheduleList: password?.scheduleList,
? 'EXPIRED' passwordName: password.name,
: timestampInSeconds > password.effectiveTime passwordType: 'ONLINE_MULTIPLE',
? 'EFFECTIVE' deviceUuid: doorLockUuid,
: 'TO_BE_EFFECTIVE', deviceName: deviceTuyaDetails.name,
}; passwordStatus: isExpired
}) ? 'EXPIRED'
: timestampInSeconds > password.effectiveTime
? 'EFFECTIVE'
: 'TO_BE_EFFECTIVE',
authorizerEmail: passwordFromDB
? passwordFromDB.user.email
: 'OTHER',
authorizerDate: passwordFromDB
? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}`
: '',
};
}),
)
: convertKeysToCamelCase(passwordFiltered); : convertKeysToCamelCase(passwordFiltered);
} }
if (fromVisitor) { if (fromVisitor) {
@ -271,12 +328,34 @@ export class DoorLockService {
); );
} }
} }
async getVisitorPasswordFromDB(passwordId: string) {
try {
return await this.visitorPasswordRepository.findOne({
where: {
passwordTuyaUuid: passwordId,
},
relations: ['user'],
select: {
user: {
email: true,
},
},
});
} catch (error) {
throw new HttpException(
error.message || 'Error retrieving visitor password from database',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getOnlineTemporaryPasswordsOneTime( async getOnlineTemporaryPasswordsOneTime(
doorLockUuid: string, doorLockUuid: string,
fromVisitor?: boolean, fromVisitor?: boolean,
isExpired?: boolean, isExpired?: boolean,
) { ) {
try { try {
// Retrieve device details
const deviceDetails = await this.getDeviceByDeviceUuid(doorLockUuid); const deviceDetails = await this.getDeviceByDeviceUuid(doorLockUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) { if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
@ -287,11 +366,17 @@ export class DoorLockService {
HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST,
); );
} }
const deviceTuyaDetails =
await this.deviceService.getDeviceDetailsByDeviceIdTuya(
deviceDetails.deviceTuyaUuid,
);
// Get online temporary passwords
const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya( const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya(
deviceDetails.deviceTuyaUuid, deviceDetails.deviceTuyaUuid,
isExpired, isExpired,
); );
if (passwords.result?.length > 0) { if (passwords.result?.length > 0) {
// Filter and map the passwords
const passwordFiltered = passwords.result const passwordFiltered = passwords.result
.filter((item) => item.type === 1) .filter((item) => item.type === 1)
.map((password: any) => { .map((password: any) => {
@ -314,24 +399,37 @@ export class DoorLockService {
return password; return password;
}); });
// Process passwords with optimized query handling
return fromVisitor return fromVisitor
? convertKeysToCamelCase(passwordFiltered).map((password) => { ? Promise.all(
const timestampInSeconds = Math.floor(Date.now() / 1000); convertKeysToCamelCase(passwordFiltered).map(async (password) => {
return { const passwordFromDB = await this.getVisitorPasswordFromDB(
passwordId: `${password.id}`, password.id,
invalidTime: `${password.invalidTime}`, );
effectiveTime: `${password.effectiveTime}`, const timestampInSeconds = Math.floor(Date.now() / 1000);
createdTime: '', return {
passwordName: password.name, passwordId: `${password.id}`,
passwordType: 'ONLINE_ONETIME', invalidTime: `${password.invalidTime}`,
deviceUuid: doorLockUuid, effectiveTime: `${password.effectiveTime}`,
passwordStatus: isExpired createdTime: '',
? 'EXPIRED' passwordName: password.name,
: timestampInSeconds > password.effectiveTime passwordType: 'ONLINE_ONETIME',
? 'EFFECTIVE' deviceUuid: doorLockUuid,
: 'TO_BE_EFFECTIVE', deviceName: deviceTuyaDetails.name,
}; passwordStatus: isExpired
}) ? 'EXPIRED'
: timestampInSeconds > password.effectiveTime
? 'EFFECTIVE'
: 'TO_BE_EFFECTIVE',
authorizerEmail: passwordFromDB
? passwordFromDB.user.email
: 'OTHER',
authorizerDate: passwordFromDB
? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}`
: '',
};
}),
)
: convertKeysToCamelCase(passwordFiltered); : convertKeysToCamelCase(passwordFiltered);
} }
if (fromVisitor) { if (fromVisitor) {