From 35043bb75f6289e1bb75c8d5e1ac0179aa61a22a Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 18 Mar 2024 17:44:20 +0100 Subject: [PATCH] Add evaluation service per client --- .../engine/core/service/evaluation.service.ts | 39 +++++++++++++++++++ .../src/tenant/core/service/tenant.service.ts | 4 +- 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 apps/policy-engine/src/engine/core/service/evaluation.service.ts diff --git a/apps/policy-engine/src/engine/core/service/evaluation.service.ts b/apps/policy-engine/src/engine/core/service/evaluation.service.ts new file mode 100644 index 000000000..775fa4587 --- /dev/null +++ b/apps/policy-engine/src/engine/core/service/evaluation.service.ts @@ -0,0 +1,39 @@ +import { EvaluationRequest, EvaluationResponse } from '@narval/policy-engine-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { OpenPolicyAgentEngine } from '../../../open-policy-agent/core/open-policy-agent.engine' +import { ApplicationException } from '../../../shared/exception/application.exception' +import { TenantService } from '../../../tenant/core/service/tenant.service' + +@Injectable() +export class EvaluationService { + constructor(private tenantService: TenantService) {} + + async evaluate(clientId: string, evaluation: EvaluationRequest): Promise { + const [entityStore, policyStore] = await Promise.all([ + this.tenantService.findEntityStore(clientId), + this.tenantService.findPolicyStore(clientId) + ]) + + if (!entityStore) { + throw new ApplicationException({ + message: 'Missing client entity store', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { clientId } + }) + } + + if (!policyStore) { + throw new ApplicationException({ + message: 'Missing client entity store', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { clientId } + }) + } + + // WARN: Loading a new engine is an IO bounded process due to the Rego + // transpilation and WASM build. + const engine = await new OpenPolicyAgentEngine(policyStore.data, entityStore.data).load() + + return engine.evaluate(evaluation) + } +} diff --git a/apps/vault/src/tenant/core/service/tenant.service.ts b/apps/vault/src/tenant/core/service/tenant.service.ts index a721a037e..f2bcc2e6d 100644 --- a/apps/vault/src/tenant/core/service/tenant.service.ts +++ b/apps/vault/src/tenant/core/service/tenant.service.ts @@ -1,12 +1,10 @@ -import { HttpStatus, Injectable, Logger } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' import { ApplicationException } from '../../../shared/exception/application.exception' import { Tenant } from '../../../shared/type/domain.type' import { TenantRepository } from '../../persistence/repository/tenant.repository' @Injectable() export class TenantService { - private logger = new Logger(TenantService.name) - constructor(private tenantRepository: TenantRepository) {} async findByClientId(clientId: string): Promise {