feat: wire sidecar to platform — auth proxy with workspace subdomain, GraphQL proxy, health check

This commit is contained in:
2026-03-18 07:15:47 +05:30
parent d488d551ed
commit a42d479f06
9 changed files with 281 additions and 25 deletions

View File

@@ -0,0 +1,43 @@
import { Controller, Post, Body, Logger, HttpException } from '@nestjs/common';
import { OzonetelAgentService } from './ozonetel-agent.service';
@Controller('api/ozonetel')
export class OzonetelAgentController {
private readonly logger = new Logger(OzonetelAgentController.name);
constructor(private readonly ozonetelAgent: OzonetelAgentService) {}
@Post('agent-login')
async agentLogin(
@Body() body: { agentId: string; password: string; phoneNumber: string; mode?: string },
) {
this.logger.log(`Agent login request for ${body.agentId}`);
try {
const result = await this.ozonetelAgent.loginAgent(body);
return result;
} catch (error: any) {
throw new HttpException(
error.response?.data?.message ?? 'Agent login failed',
error.response?.status ?? 500,
);
}
}
@Post('agent-logout')
async agentLogout(
@Body() body: { agentId: string; password: string },
) {
this.logger.log(`Agent logout request for ${body.agentId}`);
try {
const result = await this.ozonetelAgent.logoutAgent(body);
return result;
} catch (error: any) {
throw new HttpException(
error.response?.data?.message ?? 'Agent logout failed',
error.response?.status ?? 500,
);
}
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { OzonetelAgentController } from './ozonetel-agent.controller';
import { OzonetelAgentService } from './ozonetel-agent.service';
@Module({
controllers: [OzonetelAgentController],
providers: [OzonetelAgentService],
exports: [OzonetelAgentService],
})
export class OzonetelAgentModule {}

View File

@@ -0,0 +1,94 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
@Injectable()
export class OzonetelAgentService {
private readonly logger = new Logger(OzonetelAgentService.name);
private readonly apiDomain: string;
private readonly apiKey: string;
private readonly accountId: string;
constructor(private config: ConfigService) {
this.apiDomain = config.get<string>('exotel.subdomain') ?? 'in1-ccaas-api.ozonetel.com';
this.apiKey = config.get<string>('exotel.apiKey') ?? '';
this.accountId = config.get<string>('exotel.accountSid') ?? '';
}
async loginAgent(params: {
agentId: string;
password: string;
phoneNumber: string;
mode?: string;
}): Promise<{ status: string; message: string }> {
const url = `https://${this.apiDomain}/CAServices/AgentAuthenticationV2/index.php`;
this.logger.log(`Logging in agent ${params.agentId} with phone ${params.phoneNumber}`);
try {
const response = await axios.post(
url,
new URLSearchParams({
userName: this.accountId,
apiKey: this.apiKey,
phoneNumber: params.phoneNumber,
action: 'login',
mode: params.mode ?? 'blended',
state: 'Ready',
}).toString(),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
auth: {
username: params.agentId,
password: params.password,
},
},
);
this.logger.log(`Agent login response: ${JSON.stringify(response.data)}`);
return response.data;
} catch (error: any) {
this.logger.error(`Agent login failed: ${error.message}`);
throw error;
}
}
async logoutAgent(params: {
agentId: string;
password: string;
}): Promise<{ status: string; message: string }> {
const url = `https://${this.apiDomain}/CAServices/AgentAuthenticationV2/index.php`;
this.logger.log(`Logging out agent ${params.agentId}`);
try {
const response = await axios.post(
url,
new URLSearchParams({
userName: this.accountId,
apiKey: this.apiKey,
action: 'logout',
mode: 'blended',
state: 'Ready',
}).toString(),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
auth: {
username: params.agentId,
password: params.password,
},
},
);
this.logger.log(`Agent logout response: ${JSON.stringify(response.data)}`);
return response.data;
} catch (error: any) {
this.logger.error(`Agent logout failed: ${error.message}`);
throw error;
}
}
}