diff --git a/src/spicedb/spicedb-entitlements.client.ts b/src/spicedb/spicedb-entitlements.client.ts index 79dd373..d4aa093 100644 --- a/src/spicedb/spicedb-entitlements.client.ts +++ b/src/spicedb/spicedb-entitlements.client.ts @@ -38,7 +38,7 @@ export class SpiceDBEntitlementsClient { v1.ClientSecurity.INSECURE_PLAINTEXT_CREDENTIALS ).promises; - this.spiceDBQueryClient = new SpiceDBQueryClient(this.spiceClient); + this.spiceDBQueryClient = new SpiceDBQueryClient(this.spiceClient, this.loggingClient, this.logResults); } catch (initError) { void this.loggingClient.error({ action: 'SpiceDBClient:init:error', @@ -55,7 +55,22 @@ export class SpiceDBEntitlementsClient { requestContext: RequestContext ): Promise { try { + if (this.logResults) { + await this.loggingClient.logRequest( + { action: 'SpiceDB:isEntitledTo:request', subjectContext, requestContext }, + null + ); + } + const res = await this.spiceDBQueryClient.spiceDBQuery(subjectContext, requestContext); + + if (this.logResults) { + await this.loggingClient.logRequest( + { action: 'SpiceDB:isEntitledTo:response', subjectContext, requestContext }, + res + ); + } + if (res.result.monitoring || this.logResults) { await this.loggingClient.log(subjectContext, requestContext, res); } diff --git a/src/spicedb/spicedb-queries/entitlements-spicedb.query.ts b/src/spicedb/spicedb-queries/entitlements-spicedb.query.ts index 1810c0a..ec01b2b 100644 --- a/src/spicedb/spicedb-queries/entitlements-spicedb.query.ts +++ b/src/spicedb/spicedb-queries/entitlements-spicedb.query.ts @@ -9,6 +9,7 @@ import { import { SpiceDBResponse } from '../../types/spicedb.dto'; import { SpiceDBEntities } from '../../types/spicedb-consts'; import { encodeObjectId } from './base64.utils'; +import { LoggingClient } from '../../logging'; export interface HashOptions { hashResourceId: boolean; @@ -16,7 +17,11 @@ export interface HashOptions { } export abstract class EntitlementsSpiceDBQuery { - protected constructor(protected readonly client: v1.ZedPromiseClientInterface) {} + protected constructor( + protected readonly client: v1.ZedPromiseClientInterface, + protected readonly loggingClient?: LoggingClient, + protected readonly logResults: boolean = false + ) {} abstract query( entitlementsQuery: EntitlementsDynamicQuery @@ -128,7 +133,23 @@ export abstract class EntitlementsSpiceDBQuery { const context = subjectContext; const caveatContext = this.createCaveatContext(context); const request = this.createBulkPermissionsRequest(objectType, objectId, context, caveatContext); + + if (this.logResults) { + await this.loggingClient?.logRequest( + { action: 'SpiceDB:checkBulkPermissions:request', objectType, objectId, subjectContext }, + { request } + ); + } + const res = await this.client.checkBulkPermissions(request); + + if (this.logResults) { + await this.loggingClient?.logRequest( + { action: 'SpiceDB:checkBulkPermissions:response', objectType, objectId }, + { response: res } + ); + } + const result = this.processCheckBulkPermissionsResponse(res); return { diff --git a/src/spicedb/spicedb-queries/features-spicedb.query.ts b/src/spicedb/spicedb-queries/features-spicedb.query.ts index eba4c42..689e542 100644 --- a/src/spicedb/spicedb-queries/features-spicedb.query.ts +++ b/src/spicedb/spicedb-queries/features-spicedb.query.ts @@ -3,10 +3,15 @@ import { EntitlementsDynamicQuery, EntitlementsResult, RequestContextType, UserS import { SpiceDBResponse } from '../../types/spicedb.dto'; import { v1 } from '@authzed/authzed-node'; import { SpiceDBEntities } from '../../types/spicedb-consts'; +import { LoggingClient } from '../../logging'; export class FeaturesSpiceDBQuery extends EntitlementsSpiceDBQuery { - constructor(protected readonly client: v1.ZedPromiseClientInterface) { - super(client); + constructor( + protected readonly client: v1.ZedPromiseClientInterface, + loggingClient?: LoggingClient, + logResults: boolean = false + ) { + super(client, loggingClient, logResults); } async query({ diff --git a/src/spicedb/spicedb-queries/fga-spicedb.query.ts b/src/spicedb/spicedb-queries/fga-spicedb.query.ts index f8f2b5b..6d7a760 100644 --- a/src/spicedb/spicedb-queries/fga-spicedb.query.ts +++ b/src/spicedb/spicedb-queries/fga-spicedb.query.ts @@ -3,10 +3,15 @@ import { EntitlementsDynamicQuery, EntitlementsResult, FGASubjectContext, Reques import { SpiceDBResponse } from '../../types/spicedb.dto'; import { v1 } from '@authzed/authzed-node'; import { encodeObjectId } from './base64.utils'; +import { LoggingClient } from '../../logging'; export class FgaSpiceDBQuery extends EntitlementsSpiceDBQuery { - constructor(protected readonly client: v1.ZedPromiseClientInterface) { - super(client); + constructor( + protected readonly client: v1.ZedPromiseClientInterface, + loggingClient?: LoggingClient, + logResults: boolean = false + ) { + super(client, loggingClient, logResults); } async query({ diff --git a/src/spicedb/spicedb-queries/permission-spicedb.query.ts b/src/spicedb/spicedb-queries/permission-spicedb.query.ts index b872a46..ba8ef34 100644 --- a/src/spicedb/spicedb-queries/permission-spicedb.query.ts +++ b/src/spicedb/spicedb-queries/permission-spicedb.query.ts @@ -3,10 +3,15 @@ import { EntitlementsDynamicQuery, EntitlementsResult, RequestContextType, UserS import { SpiceDBResponse } from '../../types/spicedb.dto'; import { v1 } from '@authzed/authzed-node'; import { SpiceDBEntities } from '../../types/spicedb-consts'; +import { LoggingClient } from '../../logging'; export class PermissionSpiceDBQuery extends EntitlementsSpiceDBQuery { - constructor(protected readonly client: v1.ZedPromiseClientInterface) { - super(client); + constructor( + protected readonly client: v1.ZedPromiseClientInterface, + loggingClient?: LoggingClient, + logResults: boolean = false + ) { + super(client, loggingClient, logResults); } public async query({ diff --git a/src/spicedb/spicedb-queries/route-spicedb.query.ts b/src/spicedb/spicedb-queries/route-spicedb.query.ts index 0a7fd6b..edfa74a 100644 --- a/src/spicedb/spicedb-queries/route-spicedb.query.ts +++ b/src/spicedb/spicedb-queries/route-spicedb.query.ts @@ -5,13 +5,18 @@ import { v1 } from '@authzed/authzed-node'; import { LRUCache } from 'lru-cache'; import { SpiceDBEntities } from '../../types/spicedb-consts'; import { encodeObjectId } from './base64.utils'; +import { LoggingClient } from '../../logging'; export class RouteSpiceDBQuery extends EntitlementsSpiceDBQuery { private readonly cache: LRUCache; private static readonly CACHE_TTL = 30 * 1000; - constructor(protected readonly client: v1.ZedPromiseClientInterface) { - super(client); + constructor( + protected readonly client: v1.ZedPromiseClientInterface, + loggingClient?: LoggingClient, + logResults: boolean = false + ) { + super(client, loggingClient, logResults); this.cache = new LRUCache({ max: 100, ttl: RouteSpiceDBQuery.CACHE_TTL }); } diff --git a/src/spicedb/spicedb-queries/spicedb-query.client.ts b/src/spicedb/spicedb-queries/spicedb-query.client.ts index e74f7b9..40d9747 100644 --- a/src/spicedb/spicedb-queries/spicedb-query.client.ts +++ b/src/spicedb/spicedb-queries/spicedb-query.client.ts @@ -6,16 +6,21 @@ import { FeaturesSpiceDBQuery } from './features-spicedb.query'; import { FgaSpiceDBQuery } from './fga-spicedb.query'; import { RouteSpiceDBQuery } from './route-spicedb.query'; import { v1 } from '@authzed/authzed-node'; +import { LoggingClient } from '../../logging'; export class SpiceDBQueryClient { private readonly strategy: Record; - constructor(private readonly client: v1.ZedPromiseClientInterface) { + constructor( + private readonly client: v1.ZedPromiseClientInterface, + loggingClient?: LoggingClient, + logResults: boolean = false + ) { this.strategy = { - [RequestContextType.Permission]: new PermissionSpiceDBQuery(client), - [RequestContextType.Feature]: new FeaturesSpiceDBQuery(client), - [RequestContextType.Entity]: new FgaSpiceDBQuery(client), - [RequestContextType.Route]: new RouteSpiceDBQuery(client) + [RequestContextType.Permission]: new PermissionSpiceDBQuery(client, loggingClient, logResults), + [RequestContextType.Feature]: new FeaturesSpiceDBQuery(client, loggingClient, logResults), + [RequestContextType.Entity]: new FgaSpiceDBQuery(client, loggingClient, logResults), + [RequestContextType.Route]: new RouteSpiceDBQuery(client, loggingClient, logResults) }; }