mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-11 18:08:16 +00:00
feat: caller cache invalidation endpoint + worklist auth fix
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -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 {
|
return {
|
||||||
accessToken,
|
accessToken,
|
||||||
refreshToken: tokens.refreshToken.token,
|
refreshToken: tokens.refreshToken.token,
|
||||||
|
|||||||
@@ -23,4 +23,14 @@ export class CallerResolutionController {
|
|||||||
const result = await this.resolution.resolve(phone, auth);
|
const result = await this.resolution.resolve(phone, auth);
|
||||||
return result;
|
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' };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Controller, Get, Patch, Headers, Param, Body, HttpException, Logger } f
|
|||||||
import { PlatformGraphqlService } from '../platform/platform-graphql.service';
|
import { PlatformGraphqlService } from '../platform/platform-graphql.service';
|
||||||
import { WorklistService } from './worklist.service';
|
import { WorklistService } from './worklist.service';
|
||||||
import { MissedQueueService } from './missed-queue.service';
|
import { MissedQueueService } from './missed-queue.service';
|
||||||
|
import { SessionService } from '../auth/session.service';
|
||||||
|
|
||||||
@Controller('api/worklist')
|
@Controller('api/worklist')
|
||||||
export class WorklistController {
|
export class WorklistController {
|
||||||
@@ -11,6 +12,7 @@ export class WorklistController {
|
|||||||
private readonly worklist: WorklistService,
|
private readonly worklist: WorklistService,
|
||||||
private readonly missedQueue: MissedQueueService,
|
private readonly missedQueue: MissedQueueService,
|
||||||
private readonly platform: PlatformGraphqlService,
|
private readonly platform: PlatformGraphqlService,
|
||||||
|
private readonly session: SessionService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@@ -44,6 +46,12 @@ export class WorklistController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async resolveAgentName(authHeader: string): Promise<string> {
|
private async resolveAgentName(authHeader: string): Promise<string> {
|
||||||
|
// 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 {
|
try {
|
||||||
const data = await this.platform.queryWithAuth<any>(
|
const data = await this.platform.queryWithAuth<any>(
|
||||||
`{ currentUser { workspaceMember { name { firstName lastName } } } }`,
|
`{ currentUser { workspaceMember { name { firstName lastName } } } }`,
|
||||||
@@ -54,7 +62,7 @@ export class WorklistController {
|
|||||||
const full = `${name?.firstName ?? ''} ${name?.lastName ?? ''}`.trim();
|
const full = `${name?.firstName ?? ''} ${name?.lastName ?? ''}`.trim();
|
||||||
if (full) return full;
|
if (full) return full;
|
||||||
} catch (err) {
|
} 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);
|
throw new HttpException('Could not determine agent identity', 400);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Module, forwardRef } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
import { PlatformModule } from '../platform/platform.module';
|
import { PlatformModule } from '../platform/platform.module';
|
||||||
import { OzonetelAgentModule } from '../ozonetel/ozonetel-agent.module';
|
import { OzonetelAgentModule } from '../ozonetel/ozonetel-agent.module';
|
||||||
|
import { AuthModule } from '../auth/auth.module';
|
||||||
import { RulesEngineModule } from '../rules-engine/rules-engine.module';
|
import { RulesEngineModule } from '../rules-engine/rules-engine.module';
|
||||||
import { WorklistController } from './worklist.controller';
|
import { WorklistController } from './worklist.controller';
|
||||||
import { WorklistService } from './worklist.service';
|
import { WorklistService } from './worklist.service';
|
||||||
@@ -9,7 +10,7 @@ import { MissedCallWebhookController } from './missed-call-webhook.controller';
|
|||||||
import { KookooCallbackController } from './kookoo-callback.controller';
|
import { KookooCallbackController } from './kookoo-callback.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PlatformModule, forwardRef(() => OzonetelAgentModule), RulesEngineModule],
|
imports: [PlatformModule, forwardRef(() => OzonetelAgentModule), forwardRef(() => AuthModule), RulesEngineModule],
|
||||||
controllers: [WorklistController, MissedCallWebhookController, KookooCallbackController],
|
controllers: [WorklistController, MissedCallWebhookController, KookooCallbackController],
|
||||||
providers: [WorklistService, MissedQueueService],
|
providers: [WorklistService, MissedQueueService],
|
||||||
exports: [MissedQueueService],
|
exports: [MissedQueueService],
|
||||||
|
|||||||
Reference in New Issue
Block a user