71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { createHash, randomBytes } from 'node:crypto';
|
|
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
|
import { DefaultUserService } from '../users/default-user.service';
|
|
import {
|
|
DeviceHeartbeatRequestDto,
|
|
DeviceHeartbeatResponseDto,
|
|
RegisterDeviceRequestDto,
|
|
RegisterDeviceResponseDto,
|
|
} from './devices.dto';
|
|
|
|
@Injectable()
|
|
export class DevicesService {
|
|
constructor(
|
|
private readonly prismaService: PrismaService,
|
|
private readonly defaultUserService: DefaultUserService,
|
|
) {}
|
|
|
|
async register(
|
|
body: RegisterDeviceRequestDto,
|
|
): Promise<RegisterDeviceResponseDto> {
|
|
const bootstrapToken = randomBytes(24).toString('hex');
|
|
const installTokenHash = createHash('sha256')
|
|
.update(bootstrapToken)
|
|
.digest('hex');
|
|
const defaultUser = await this.defaultUserService.getOrCreateDefaultUser();
|
|
|
|
const device = await this.prismaService.device.create({
|
|
data: {
|
|
userId: defaultUser.id,
|
|
platform: body.platform,
|
|
deviceName: body.deviceName,
|
|
appVersion: body.appVersion,
|
|
installTokenHash,
|
|
lastSeenAt: new Date(),
|
|
},
|
|
});
|
|
|
|
return {
|
|
deviceId: device.id,
|
|
bootstrapToken,
|
|
serverTime: new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
async heartbeat(
|
|
body: DeviceHeartbeatRequestDto,
|
|
): Promise<DeviceHeartbeatResponseDto> {
|
|
const existing = await this.prismaService.device.findUnique({
|
|
where: { id: body.deviceId },
|
|
});
|
|
|
|
if (!existing) {
|
|
throw new NotFoundException('Device not found');
|
|
}
|
|
|
|
await this.prismaService.device.update({
|
|
where: { id: body.deviceId },
|
|
data: {
|
|
appVersion: body.appVersion,
|
|
lastSeenAt: new Date(),
|
|
},
|
|
});
|
|
|
|
return {
|
|
ok: true,
|
|
serverTime: new Date().toISOString(),
|
|
};
|
|
}
|
|
}
|