Merge pull request #1 from Cameleonapp/feature/keycloak-config
Feature/keycloak config
This commit is contained in:
commit
eb83c8dc1b
712
package-lock.json
generated
712
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,8 @@
|
|||||||
"amqplib": "^0.10.9",
|
"amqplib": "^0.10.9",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
|
"keycloak-connect": "^26.1.1",
|
||||||
|
"nest-keycloak-connect": "^1.10.1",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"swagger-ui-express": "^5.0.1"
|
"swagger-ui-express": "^5.0.1"
|
||||||
|
|||||||
@ -4,14 +4,55 @@ import { AppService } from './app.service';
|
|||||||
import { WebhookController } from './controllers/webhook.controller';
|
import { WebhookController } from './controllers/webhook.controller';
|
||||||
import { WebhookService } from './services/webhook.service';
|
import { WebhookService } from './services/webhook.service';
|
||||||
import { RabbitMQService } from './services/rabbit.service';
|
import { RabbitMQService } from './services/rabbit.service';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import rabbitmqConfig from './config/rabbitmq.config';
|
import appConfig from './config/app.config';
|
||||||
|
import {
|
||||||
|
AuthGuard,
|
||||||
|
KeycloakConnectModule,
|
||||||
|
PolicyEnforcementMode,
|
||||||
|
ResourceGuard,
|
||||||
|
RoleGuard,
|
||||||
|
TokenValidation,
|
||||||
|
} from 'nest-keycloak-connect';
|
||||||
|
import { APP_GUARD } from '@nestjs/core';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({ isGlobal: true,load: [rabbitmqConfig] }),
|
KeycloakConnectModule.registerAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
useFactory: (configService: ConfigService) => {
|
||||||
|
const keycloakConfig = configService.get('appConfig.keycloak');
|
||||||
|
return {
|
||||||
|
authServerUrl: keycloakConfig.authServerUrl,
|
||||||
|
realm: keycloakConfig.realm,
|
||||||
|
clientId: keycloakConfig.clientId,
|
||||||
|
secret: keycloakConfig.clientSecret,
|
||||||
|
policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
|
||||||
|
tokenValidation: TokenValidation.ONLINE,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
|
ConfigModule.forRoot({ isGlobal: true, load: [appConfig] }),
|
||||||
],
|
],
|
||||||
|
|
||||||
controllers: [AppController, WebhookController],
|
controllers: [AppController, WebhookController],
|
||||||
providers: [AppService, WebhookService, RabbitMQService],
|
providers: [
|
||||||
|
AppService,
|
||||||
|
WebhookService,
|
||||||
|
RabbitMQService,
|
||||||
|
{
|
||||||
|
provide: APP_GUARD,
|
||||||
|
useClass: AuthGuard,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: APP_GUARD,
|
||||||
|
useClass: ResourceGuard,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: APP_GUARD,
|
||||||
|
useClass: RoleGuard,
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { registerAs } from '@nestjs/config';
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('rabbitmq', () => ({
|
export default registerAs('appConfig', () => ({
|
||||||
user: process.env.RABBITMQ_USER,
|
user: process.env.RABBITMQ_USER,
|
||||||
pass: process.env.RABBITMQ_PASS,
|
pass: process.env.RABBITMQ_PASS,
|
||||||
host: process.env.RABBITMQ_HOST,
|
host: process.env.RABBITMQ_HOST,
|
||||||
@ -11,4 +11,10 @@ export default registerAs('rabbitmq', () => ({
|
|||||||
subscription: process.env.RABBITMQ_QUEUE_PAYMENT || 'subscription_queue',
|
subscription: process.env.RABBITMQ_QUEUE_PAYMENT || 'subscription_queue',
|
||||||
he: process.env.RABBITMQ_QUEUE_NOTIFICATION || 'he_queue',
|
he: process.env.RABBITMQ_QUEUE_NOTIFICATION || 'he_queue',
|
||||||
},
|
},
|
||||||
|
keycloak: {
|
||||||
|
authServerUrl: process.env.KEYCLOAK_AUTH_SERVER_URL,
|
||||||
|
clientId: process.env.KEYCLOAK_CLIENT_ID,
|
||||||
|
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
|
||||||
|
realm: process.env.KEYCLOAK_REALM,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
@ -10,18 +10,40 @@ import {
|
|||||||
HttpStatus,
|
HttpStatus,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
|
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import {
|
||||||
|
ApiBearerAuth,
|
||||||
|
ApiBody,
|
||||||
|
ApiCreatedResponse,
|
||||||
|
ApiOkResponse,
|
||||||
|
ApiOperation,
|
||||||
|
ApiTags,
|
||||||
|
} from '@nestjs/swagger';
|
||||||
|
import { Resource, Roles } from 'nest-keycloak-connect';
|
||||||
import { InboundSMSMessageNotificationWrapperDto } from 'src/dtos/sms.mo.dto';
|
import { InboundSMSMessageNotificationWrapperDto } from 'src/dtos/sms.mo.dto';
|
||||||
import { SubscriptionDto } from 'src/dtos/subscription.dto';
|
import { SubscriptionDto } from 'src/dtos/subscription.dto';
|
||||||
import { WebhookService } from 'src/services/webhook.service';
|
import { WebhookService } from 'src/services/webhook.service';
|
||||||
|
|
||||||
@Controller('webhook')
|
@Controller('webhook')
|
||||||
@ApiTags('webhook')
|
@ApiTags('webhook')
|
||||||
|
@ApiBearerAuth()
|
||||||
export class WebhookController {
|
export class WebhookController {
|
||||||
constructor(private readonly webhookService: WebhookService) {}
|
constructor(private readonly webhookService: WebhookService) {}
|
||||||
|
|
||||||
@Post('sms-mo/:operator/:country')
|
@Post('sms-mo/:operator/:country')
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
|
@Roles({ roles: ['admin_webhook'] })
|
||||||
|
@ApiOperation({ summary: 'Receive callback for SMS MO notification' })
|
||||||
|
@ApiBody({ type: InboundSMSMessageNotificationWrapperDto })
|
||||||
|
@ApiCreatedResponse({
|
||||||
|
description: 'SMS MO callback successfully queued',
|
||||||
|
schema: {
|
||||||
|
example: {
|
||||||
|
status: 'queued',
|
||||||
|
operator: 'Orange',
|
||||||
|
country: 'SN',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
async smsMoNotification(
|
async smsMoNotification(
|
||||||
@Param('country') country: string,
|
@Param('country') country: string,
|
||||||
@Param('operator') operator: string,
|
@Param('operator') operator: string,
|
||||||
@ -38,6 +60,19 @@ export class WebhookController {
|
|||||||
|
|
||||||
@Post('subscription/:operator/:country')
|
@Post('subscription/:operator/:country')
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
|
@Roles({ roles: ['admin_webhook'] })
|
||||||
|
@ApiOperation({ summary: 'Receive callback for management of subscription' })
|
||||||
|
@ApiBody({ type: SubscriptionDto })
|
||||||
|
@ApiCreatedResponse({
|
||||||
|
description: 'Subscription event successfully queued',
|
||||||
|
schema: {
|
||||||
|
example: {
|
||||||
|
status: 'queued',
|
||||||
|
operator: 'Orange',
|
||||||
|
country: 'EG',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
async manageSubscription(
|
async manageSubscription(
|
||||||
@Param('country') country: string,
|
@Param('country') country: string,
|
||||||
@Param('operator') operator: string,
|
@Param('operator') operator: string,
|
||||||
@ -53,6 +88,16 @@ export class WebhookController {
|
|||||||
|
|
||||||
@Get('he/:operator/:country')
|
@Get('he/:operator/:country')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Roles({ roles: ['admin_webhook'] })
|
||||||
|
@ApiOperation({ summary: 'Receive callback for HE notification' })
|
||||||
|
@ApiOkResponse({
|
||||||
|
description: 'HE notification successfully queued',
|
||||||
|
schema: {
|
||||||
|
example: {
|
||||||
|
status: 'queued',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
async heNotification(
|
async heNotification(
|
||||||
@Param('country') country: string,
|
@Param('country') country: string,
|
||||||
@Param('operator') operator: string,
|
@Param('operator') operator: string,
|
||||||
@ -69,6 +114,6 @@ export class WebhookController {
|
|||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { status: 'queued', operator, country, callback };
|
return { status: 'queued' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,38 +1,54 @@
|
|||||||
import { IsString, ValidateNested, IsNotEmpty, IsDateString } from 'class-validator';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import {
|
||||||
|
IsString,
|
||||||
|
ValidateNested,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsDateString,
|
||||||
|
} from 'class-validator';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
|
|
||||||
export class InboundSMSMessageDto {
|
export class InboundSMSMessageDto {
|
||||||
|
@ApiProperty({ example: '2025-10-30T14:00:00Z' })
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
dateTime: string;
|
dateTime: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: '+33612345678' })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
destinationAddress: string;
|
destinationAddress: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'mes1234' })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
messageId: string;
|
messageId: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'recipient id %% The content of the message we should send.',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'acr:token' })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
senderAddress: string;
|
senderAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InboundSMSMessageNotificationDto {
|
export class InboundSMSMessageNotificationDto {
|
||||||
|
@ApiProperty({ example: '12345' })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
callbackData: string;
|
callbackData: string;
|
||||||
|
|
||||||
|
@ApiProperty({ type: InboundSMSMessageDto })
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => InboundSMSMessageDto)
|
@Type(() => InboundSMSMessageDto)
|
||||||
inboundSMSMessage: InboundSMSMessageDto;
|
inboundSMSMessage: InboundSMSMessageDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InboundSMSMessageNotificationWrapperDto {
|
export class InboundSMSMessageNotificationWrapperDto {
|
||||||
|
@ApiProperty({ type: InboundSMSMessageNotificationDto })
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => InboundSMSMessageNotificationDto)
|
@Type(() => InboundSMSMessageNotificationDto)
|
||||||
inboundSMSMessageNotification: InboundSMSMessageNotificationDto;
|
inboundSMSMessageNotification: InboundSMSMessageNotificationDto;
|
||||||
|
|||||||
@ -16,6 +16,8 @@ async function bootstrap() {
|
|||||||
.setDescription(
|
.setDescription(
|
||||||
'This is a service dedicated to the reception of callback from external source and sending to rabbitMQ',
|
'This is a service dedicated to the reception of callback from external source and sending to rabbitMQ',
|
||||||
)
|
)
|
||||||
|
.addBearerAuth()
|
||||||
|
.addTag('auth')
|
||||||
.setVersion('1.0')
|
.setVersion('1.0')
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ async function bootstrap() {
|
|||||||
});
|
});
|
||||||
const port = process.env.PORT || 3000;
|
const port = process.env.PORT || 3000;
|
||||||
await app.listen(port);
|
await app.listen(port);
|
||||||
|
|
||||||
console.log(`Application is running on: http://localhost:${port}`);
|
console.log(`Application is running on: http://localhost:${port}`);
|
||||||
console.log(`Swagger docs: http://localhost:${port}/api/docs`);
|
console.log(`Swagger docs: http://localhost:${port}/api/docs`);
|
||||||
console.log(`Swagger docs: http://localhost:${port}/api/swagger-json`);
|
console.log(`Swagger docs: http://localhost:${port}/api/swagger-json`);
|
||||||
|
|||||||
@ -6,19 +6,24 @@ import { connect, Connection, Channel } from 'amqplib';
|
|||||||
export class RabbitMQService implements OnModuleInit {
|
export class RabbitMQService implements OnModuleInit {
|
||||||
private connection!: Connection;
|
private connection!: Connection;
|
||||||
private channel!: Channel;
|
private channel!: Channel;
|
||||||
|
private maxRetry: number;
|
||||||
|
private delay: number;
|
||||||
|
|
||||||
constructor(private configService: ConfigService) {}
|
constructor(private configService: ConfigService) {
|
||||||
|
this.maxRetry = 5;
|
||||||
|
this.delay = 500;
|
||||||
|
}
|
||||||
|
|
||||||
async onModuleInit() {
|
async onModuleInit() {
|
||||||
await this.connectWithRetry();
|
await this.connectWithRetry();
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(): Promise<void> {
|
async connect(): Promise<void> {
|
||||||
const user = this.configService.get<string>('rabbitmq.user');
|
const user = this.configService.get<string>('appConfig.user');
|
||||||
const pass = this.configService.get<string>('rabbitmq.pass');
|
const pass = this.configService.get<string>('appConfig.pass');
|
||||||
const host = this.configService.get<string>('rabbitmq.host');
|
const host = this.configService.get<string>('appConfig.host');
|
||||||
const port = this.configService.get<string>('rabbitmq.port');
|
const port = this.configService.get<string>('appConfig.port');
|
||||||
|
|
||||||
this.connection = await connect(`amqp://${user}:${pass}@${host}:${port}`);
|
this.connection = await connect(`amqp://${user}:${pass}@${host}:${port}`);
|
||||||
this.channel = await this.connection.createChannel();
|
this.channel = await this.connection.createChannel();
|
||||||
console.log('Connected to RabbitMQ');
|
console.log('Connected to RabbitMQ');
|
||||||
@ -39,10 +44,37 @@ export class RabbitMQService implements OnModuleInit {
|
|||||||
throw new Error('Could not connect to RabbitMQ after multiple attempts');
|
throw new Error('Could not connect to RabbitMQ after multiple attempts');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this method send the message to rabbitMQ queue
|
||||||
async sendToQueue(queue: string, message: any) {
|
async sendToQueue(queue: string, message: any) {
|
||||||
if (!this.channel) throw new Error('RabbitMQ channel not initialized');
|
if (!this.channel) throw new Error('RabbitMQ channel not initialized');
|
||||||
|
|
||||||
|
//check if the queue exist and create it if not
|
||||||
await this.channel.assertQueue(queue, { durable: true });
|
await this.channel.assertQueue(queue, { durable: true });
|
||||||
this.channel.sendToQueue(queue, Buffer.from(JSON.stringify(message)));
|
|
||||||
console.log(`Sent message to queue "${queue}"`);
|
for (let attempt = 1; attempt <= this.maxRetry; attempt++) {
|
||||||
|
try {
|
||||||
|
const sent = await this.channel.sendToQueue(
|
||||||
|
queue,
|
||||||
|
Buffer.from(JSON.stringify(message)),
|
||||||
|
);
|
||||||
|
if (!sent) {
|
||||||
|
throw new Error('Message not sent');
|
||||||
|
}
|
||||||
|
console.log(`Message sent to queue ${queue} attempt ${attempt}`);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
if (attempt === this.maxRetry) {
|
||||||
|
console.log('All attempts failed');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxDelay = Math.pow(2, attempt) * this.delay;
|
||||||
|
const delay = maxDelay / 2 + Math.random() * (maxDelay / 2);
|
||||||
|
console.warn(
|
||||||
|
`Attempt ${attempt} failed: ${error.message}. Retrying in ${Math.round(delay)}ms`,
|
||||||
|
);
|
||||||
|
await new Promise((res) => setTimeout(res, delay));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
117
src/services/webhok.service.spec.ts
Normal file
117
src/services/webhok.service.spec.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { WebhookService } from './webhook.service';
|
||||||
|
import { RabbitMQService } from './rabbit.service';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { InboundSMSMessageNotificationWrapperDto } from 'src/dtos/sms.mo.dto';
|
||||||
|
import {
|
||||||
|
EventType,
|
||||||
|
OrderState,
|
||||||
|
SubscriptionDto,
|
||||||
|
} from 'src/dtos/subscription.dto';
|
||||||
|
|
||||||
|
describe('WebhookService', () => {
|
||||||
|
let service: WebhookService;
|
||||||
|
const mockRabbitMQ = { sendToQueue: jest.fn() };
|
||||||
|
const mockConfigService = {
|
||||||
|
get: jest.fn((key: string) => {
|
||||||
|
const config = {
|
||||||
|
RABBITMQ_QUEUE_WEBHOOK: 'RABBITMQ_QUEUE_WEBHOOK',
|
||||||
|
RABBITMQ_QUEUE_NOTIFICATION: 'RABBITMQ_QUEUE_NOTIFICATION',
|
||||||
|
RABBITMQ_QUEUE_PAYMENT: 'RABBITMQ_QUEUE_PAYMENT',
|
||||||
|
};
|
||||||
|
return config[key];
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
WebhookService,
|
||||||
|
{ provide: RabbitMQService, useValue: mockRabbitMQ },
|
||||||
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<WebhookService>(WebhookService);
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
//unit test for sms-mo notification
|
||||||
|
it('should send SMS MO payload to the correct queue', async () => {
|
||||||
|
const dto: InboundSMSMessageNotificationWrapperDto = {
|
||||||
|
inboundSMSMessageNotification: {
|
||||||
|
callbackData: 'cb-123',
|
||||||
|
inboundSMSMessage: {
|
||||||
|
dateTime: new Date().toISOString(),
|
||||||
|
destinationAddress: '12345',
|
||||||
|
messageId: 'msg-001',
|
||||||
|
message: 'Hello world!',
|
||||||
|
senderAddress: '987654321',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await service.smsMoNotification('FR', 'Orange', '123', dto);
|
||||||
|
|
||||||
|
expect(mockRabbitMQ.sendToQueue).toHaveBeenCalledWith(
|
||||||
|
'webhook_queue',
|
||||||
|
expect.objectContaining({
|
||||||
|
operator: 'Orange',
|
||||||
|
country: 'FR',
|
||||||
|
ise2: '123',
|
||||||
|
data: dto,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
//unit test subscription mangement
|
||||||
|
it('should send subscription payload to the correct queue', async () => {
|
||||||
|
const dto: SubscriptionDto = {
|
||||||
|
note: { text: 'User subscribed' },
|
||||||
|
event: {
|
||||||
|
id: 1,
|
||||||
|
relatedParty: [{ id: '123', name: 'ISE2', role: 'subscriber' }],
|
||||||
|
order: {
|
||||||
|
id: 1,
|
||||||
|
state: OrderState.Completed,
|
||||||
|
orderItem: {
|
||||||
|
product: { id: 'WIDO access' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
eventType: EventType.creation,
|
||||||
|
eventTime: new Date().toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
await service.manageSubscription('FR', 'Orange', dto);
|
||||||
|
|
||||||
|
expect(mockRabbitMQ.sendToQueue).toHaveBeenCalledWith(
|
||||||
|
'payment_queue',
|
||||||
|
expect.objectContaining({
|
||||||
|
operator: 'Orange',
|
||||||
|
country: 'FR',
|
||||||
|
data: dto,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
//unit test for he notification
|
||||||
|
it('should send HE notification payload to the correct queue', async () => {
|
||||||
|
await service.handleHeNotification(
|
||||||
|
'FR',
|
||||||
|
'Orange',
|
||||||
|
'callbackURL',
|
||||||
|
'ISE2CODE',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mockRabbitMQ.sendToQueue).toHaveBeenCalledWith(
|
||||||
|
'notification_queue',
|
||||||
|
expect.objectContaining({
|
||||||
|
operator: 'Orange',
|
||||||
|
country: 'FR',
|
||||||
|
callback: 'callbackURL',
|
||||||
|
ise2: 'ISE2CODE',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -2,10 +2,22 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { RabbitMQService } from 'src/services/rabbit.service';
|
import { RabbitMQService } from 'src/services/rabbit.service';
|
||||||
import { InboundSMSMessageNotificationWrapperDto } from '../dtos/sms.mo.dto';
|
import { InboundSMSMessageNotificationWrapperDto } from '../dtos/sms.mo.dto';
|
||||||
import { SubscriptionDto } from '../dtos/subscription.dto';
|
import { SubscriptionDto } from '../dtos/subscription.dto';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WebhookService {
|
export class WebhookService {
|
||||||
constructor(private readonly rabbitMQService: RabbitMQService) {}
|
private smsMoQueue: string;
|
||||||
|
private heQueue: string;
|
||||||
|
private subscriptionEventQueue: string;
|
||||||
|
constructor(
|
||||||
|
private readonly rabbitMQService: RabbitMQService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
) {
|
||||||
|
const config = this.configService.get('appConfig.queues');
|
||||||
|
this.smsMoQueue = config.smsmo as string;
|
||||||
|
this.heQueue = config.he as string;
|
||||||
|
this.subscriptionEventQueue = config.subscription as string;
|
||||||
|
}
|
||||||
|
|
||||||
async smsMoNotification(
|
async smsMoNotification(
|
||||||
country: string,
|
country: string,
|
||||||
@ -21,7 +33,7 @@ export class WebhookService {
|
|||||||
receivedAt: new Date().toISOString(),
|
receivedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.rabbitMQService.sendToQueue('sms_mo', payload);
|
await this.rabbitMQService.sendToQueue(this.smsMoQueue, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
async manageSubscription(
|
async manageSubscription(
|
||||||
@ -37,7 +49,10 @@ export class WebhookService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// send message to queue "subscription_events"
|
// send message to queue "subscription_events"
|
||||||
await this.rabbitMQService.sendToQueue('subscription_events', payload);
|
await this.rabbitMQService.sendToQueue(
|
||||||
|
this.subscriptionEventQueue,
|
||||||
|
payload,
|
||||||
|
);
|
||||||
console.log('payload sent to rabbitMQ');
|
console.log('payload sent to rabbitMQ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +69,7 @@ export class WebhookService {
|
|||||||
callback,
|
callback,
|
||||||
receivedAt: new Date().toISOString(),
|
receivedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
await this.rabbitMQService.sendToQueue('he_notifications', payload);
|
await this.rabbitMQService.sendToQueue(this.heQueue, payload);
|
||||||
console.log('payload sent to rabbitMQ');
|
console.log('payload sent to rabbitMQ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user