homelab-personal-cloud/core/src/persistence/identity-auth-device.dao.ts

89 lines
2.3 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { IdentityAuthDevice } from '@prisma/client';
import { PrismaService } from './prisma.service';
import { Identity } from '../domain/identity.types';
import { safeJsonParse } from '../utils';
import * as Joi from 'joi';
const eligibleForTwoFactor: Identity.AuthDevice.Type[] = [
]
@Injectable()
export class IdentityAuthDeviceDao {
constructor(
private readonly prismaService: PrismaService,
) {}
async findByRealmAndUsername(realm: string, username: string): Promise<Identity.AuthDevice[]> {
const devices = await this.prismaService.identityAuthDevice.findMany({
where: {
user: {
username: username.toLowerCase(),
realm: {
name: realm.toLowerCase(),
},
},
},
});
return devices.map(d => IdentityAuthDeviceDao.modelToEntity(d));
}
async findOneByUrn(urn: string): Promise<Identity.AuthDevice | null> {
const device = await this.prismaService.identityAuthDevice.findFirst({
where: {
id: urn.replace('urn:identity:auth-device:', ''),
},
});
if (!device) {
return null;
}
return IdentityAuthDeviceDao.modelToEntity(device);
}
private static modelToEntity(model: IdentityAuthDevice, skipAttributes = false): Identity.AuthDevice {
const entity: Identity.AuthDevice = {
urn: `urn:identity:auth-device:${model.id}`,
userId: model.userId,
deviceType: model.deviceType as Identity.AuthDevice.Type,
preferred: model.preferred,
twoFactorEligible: eligibleForTwoFactor.includes(model.deviceType as Identity.AuthDevice.Type),
createdAt: new Date(model.createdAt),
}
if (skipAttributes || !model.attributes) {
return entity;
}
if (model.deviceType === Identity.AuthDevice.Type.Password) {
const [_, attributes] = safeJsonParse<Identity.AuthDevice.PasswordAttributes>(model.attributes);
const { error, value } = Joi.object<Identity.AuthDevice.PasswordAttributes, true>({
expiry: Joi.date().required(),
passwordHashString: Joi.string().required(),
locked: Joi.boolean().required(),
}).validate(attributes);
if (error) {
return entity;
}
return {
...entity,
...value,
}
}
return entity;
}
}