mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 08:44:54 +00:00
Add Comprehensive Door Lock Module Enhancements
This commit is contained in:
@ -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 {}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user