From 1d1f27607f6ee9f4a1389a776160e3070ddfa742 Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Thu, 2 Apr 2026 12:14:56 +0530 Subject: [PATCH] feat: caller cache invalidation endpoint + worklist auth fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - POST /api/caller/invalidate — clears Redis cache for a phone number - WorklistController: resolves agent name from login cache (avoids currentUser query) - AuthController: caches agent name in Redis during login (keyed by token suffix) - WorklistModule: imports AuthModule (forwardRef for circular dep) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/auth/auth.controller.ts | 6 ++++++ src/caller/caller-resolution.controller.ts | 10 ++++++++++ src/worklist/worklist.controller.ts | 10 +++++++++- src/worklist/worklist.module.ts | 3 ++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 33287fa..6ba6486 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -166,6 +166,12 @@ export class AuthController { } } + // Cache agent name for worklist resolution (avoids re-querying currentUser with user JWT) + const agentFullName = `${workspaceMember?.name?.firstName ?? ''} ${workspaceMember?.name?.lastName ?? ''}`.trim(); + if (agentFullName) { + await this.sessionService.setCache(`agent:name:${accessToken.slice(-16)}`, agentFullName, 86400); + } + return { accessToken, refreshToken: tokens.refreshToken.token, diff --git a/src/caller/caller-resolution.controller.ts b/src/caller/caller-resolution.controller.ts index 112f8cd..35f2487 100644 --- a/src/caller/caller-resolution.controller.ts +++ b/src/caller/caller-resolution.controller.ts @@ -23,4 +23,14 @@ export class CallerResolutionController { const result = await this.resolution.resolve(phone, auth); return result; } + + @Post('invalidate') + async invalidate(@Body('phone') phone: string) { + if (!phone) { + throw new HttpException('phone is required', HttpStatus.BAD_REQUEST); + } + this.logger.log(`[RESOLVE] Invalidating cache for: ${phone}`); + await this.resolution.invalidate(phone); + return { status: 'ok' }; + } } diff --git a/src/worklist/worklist.controller.ts b/src/worklist/worklist.controller.ts index de3b9d5..8fb771c 100644 --- a/src/worklist/worklist.controller.ts +++ b/src/worklist/worklist.controller.ts @@ -2,6 +2,7 @@ import { Controller, Get, Patch, Headers, Param, Body, HttpException, Logger } f import { PlatformGraphqlService } from '../platform/platform-graphql.service'; import { WorklistService } from './worklist.service'; import { MissedQueueService } from './missed-queue.service'; +import { SessionService } from '../auth/session.service'; @Controller('api/worklist') export class WorklistController { @@ -11,6 +12,7 @@ export class WorklistController { private readonly worklist: WorklistService, private readonly missedQueue: MissedQueueService, private readonly platform: PlatformGraphqlService, + private readonly session: SessionService, ) {} @Get() @@ -44,6 +46,12 @@ export class WorklistController { } private async resolveAgentName(authHeader: string): Promise { + // Check cached name from login (avoids currentUser query that CC agents can't access) + const token = authHeader.replace(/^Bearer\s+/i, ''); + const cached = await this.session.getCache(`agent:name:${token.slice(-16)}`); + if (cached) return cached; + + // Fallback: try querying platform (works for admin/supervisor tokens) try { const data = await this.platform.queryWithAuth( `{ currentUser { workspaceMember { name { firstName lastName } } } }`, @@ -54,7 +62,7 @@ export class WorklistController { const full = `${name?.firstName ?? ''} ${name?.lastName ?? ''}`.trim(); if (full) return full; } catch (err) { - this.logger.warn(`Failed to resolve agent name: ${err}`); + this.logger.warn(`Failed to resolve agent name via platform: ${err}`); } throw new HttpException('Could not determine agent identity', 400); } diff --git a/src/worklist/worklist.module.ts b/src/worklist/worklist.module.ts index 036bc0b..0b492c1 100644 --- a/src/worklist/worklist.module.ts +++ b/src/worklist/worklist.module.ts @@ -1,6 +1,7 @@ import { Module, forwardRef } from '@nestjs/common'; import { PlatformModule } from '../platform/platform.module'; import { OzonetelAgentModule } from '../ozonetel/ozonetel-agent.module'; +import { AuthModule } from '../auth/auth.module'; import { RulesEngineModule } from '../rules-engine/rules-engine.module'; import { WorklistController } from './worklist.controller'; import { WorklistService } from './worklist.service'; @@ -9,7 +10,7 @@ import { MissedCallWebhookController } from './missed-call-webhook.controller'; import { KookooCallbackController } from './kookoo-callback.controller'; @Module({ - imports: [PlatformModule, forwardRef(() => OzonetelAgentModule), RulesEngineModule], + imports: [PlatformModule, forwardRef(() => OzonetelAgentModule), forwardRef(() => AuthModule), RulesEngineModule], controllers: [WorklistController, MissedCallWebhookController, KookooCallbackController], providers: [WorklistService, MissedQueueService], exports: [MissedQueueService],