From 6094878e0eb33ff7882733ba1ecaa4d3fc8e42cc Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 12 Dec 2025 23:14:48 +0330 Subject: [PATCH] update --- .../interfaces/notification.interface.ts | 15 ++---- .../notifications/notifications.gateway.ts | 39 +++++++++++++--- .../notifications/processors/sms.processor.ts | 46 +++++++++---------- .../services/notification.service.ts | 11 +++-- .../notifications/services/sms.adaptor.ts | 6 +-- test-notifications-socket.html | 2 +- 6 files changed, 70 insertions(+), 49 deletions(-) diff --git a/src/modules/notifications/interfaces/notification.interface.ts b/src/modules/notifications/interfaces/notification.interface.ts index 431ab72..c6488ef 100644 --- a/src/modules/notifications/interfaces/notification.interface.ts +++ b/src/modules/notifications/interfaces/notification.interface.ts @@ -53,18 +53,11 @@ interface INotifySms { phone: string; subject: NotifTitleEnum; } -// Sub intefaces -// 1. Order Created Sms Notify Payload -interface IOrderCreatedSmsNotifyPayload extends INotifySmsPayload { - orderNumber: string; - orderAmount: number; - orderDate: Date; +export interface IInAppNotificationPayload { + subject: NotifTitleEnum; + body: string; } -interface IOrderCreatedSmsNotify extends INotifySms { - subject: NotifTitleEnum.ORDER_CREATED; - payload: IOrderCreatedSmsNotifyPayload; -} // 2. Payment Success interface IPaymentSuccessSmsNotifyPayload extends INotifySmsPayload { amount: number; @@ -76,4 +69,4 @@ interface IPaymentSuccessSmsNotify extends INotifySms { payload: IPaymentSuccessSmsNotifyPayload; } -export type ISmsNotifyPayload = IOrderCreatedSmsNotify | IPaymentSuccessSmsNotify; +export type ISmsNotifyPayload = IPaymentSuccessSmsNotify; diff --git a/src/modules/notifications/notifications.gateway.ts b/src/modules/notifications/notifications.gateway.ts index d925f22..93671e5 100644 --- a/src/modules/notifications/notifications.gateway.ts +++ b/src/modules/notifications/notifications.gateway.ts @@ -12,14 +12,15 @@ import { Logger, UseGuards, Inject, forwardRef } from '@nestjs/common'; // import { WsRestId } from './decorators/ws-rest-id.decorator'; import { NotificationService } from './services/notification.service'; import { WsAdminAuthGuard, type AuthenticatedSocket } from './guards/ws-admin-auth.guard'; +import { ModuleRef } from '@nestjs/core'; +import { ExecutionContext } from '@nestjs/common'; +import { IInAppNotificationPayload } from './interfaces/notification.interface'; -@UseGuards(WsAdminAuthGuard) @WebSocketGateway({ cors: { origin: true, credentials: true, }, - // connectionGuard: WsAdminAuthGuard, namespace: '/notifications', transports: ['websocket', 'polling'], }) @@ -32,21 +33,31 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco constructor( @Inject(forwardRef(() => NotificationService)) private readonly notificationService: NotificationService, + private readonly moduleRef: ModuleRef, ) {} - handleConnection(client: AuthenticatedSocket) { - this.logger.log(`Admin connected: ${client.adminId}`); - this.handleJoinRoom(client); + async handleConnection(client: Socket) { + try { + await this.authenticateConnection(client); + const authenticatedClient = client as AuthenticatedSocket; + this.logger.log(`Admin connected: ${authenticatedClient.adminId}`); + this.handleJoinRoom(authenticatedClient); + } catch (error) { + this.logger.error( + `Connection authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`, + ); + client.disconnect(); + } } handleDisconnect(client: Socket) { this.logger.log(`Client disconnected: ${client.id}`); } - sendInAppNotification(repipient: { adminId: string; restaurantId: string }, event: string, data: any) { + sendInAppNotification(repipient: { adminId: string; restaurantId: string }, payload: IInAppNotificationPayload) { this.logger.log(`Sending in app notification to admin: ${repipient.adminId}`); const room = this.getRoom(repipient.adminId, repipient.restaurantId); - this.server.to(room).emit(event, data); + this.server.to(room).emit('notifications', payload); this.logger.log(`In app notification sent to admin: ${repipient.adminId}`); } @@ -251,4 +262,18 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco // }); // this.logger.log(`Emitted pager:status:updated to room: ${cookieRoom}`); // } + + private async authenticateConnection(client: Socket): Promise { + const guard = this.moduleRef.get(WsAdminAuthGuard); + const context = { + switchToWs: () => ({ getClient: () => client }), + getClass: () => NotificationsGateway, + getHandler: () => this.handleConnection, + } as unknown as ExecutionContext; + + const canActivate = await guard.canActivate(context); + if (!canActivate) { + throw new Error('Authentication failed'); + } + } } diff --git a/src/modules/notifications/processors/sms.processor.ts b/src/modules/notifications/processors/sms.processor.ts index cecbb75..77ac826 100644 --- a/src/modules/notifications/processors/sms.processor.ts +++ b/src/modules/notifications/processors/sms.processor.ts @@ -44,30 +44,30 @@ export class SmsProcessor extends WorkerHost { // Send SMS notification let smsResult: ISmsResponse; - if (title === NotifTitleEnum.ORDER_CREATED) { - smsResult = await this.smsAdaptorService.sendNotifySms({ - phone: user.phone, - subject: NotifTitleEnum.ORDER_CREATED, - payload: { - orderNumber: '1234567890', - orderAmount: 100000, - orderDate: new Date(), - }, - }); - } else { - smsResult = await this.smsAdaptorService.sendNotifySms({ - phone: user.phone, - subject: NotifTitleEnum.PAYMENT_SUCCESS, - payload: { - amount: 100000, - date: new Date(), - }, - }); - } + // if (title === NotifTitleEnum.ORDER_CREATED) { + // smsResult = await this.smsAdaptorService.sendNotifySms({ + // phone: user.phone, + // subject: NotifTitleEnum.ORDER_CREATED, + // payload: { + // orderNumber: '1234567890', + // orderAmount: 100000, + // orderDate: new Date(), + // }, + // }); + // } else { + // smsResult = await this.smsAdaptorService.sendNotifySms({ + // phone: user.phone, + // subject: NotifTitleEnum.PAYMENT_SUCCESS, + // payload: { + // amount: 100000, + // date: new Date(), + // }, + // }); + // } - if (smsResult.status !== 1) { - throw new Error(smsResult.message ?? 'Failed to send SMS notification'); - } + // if (smsResult.status !== 1) { + // throw new Error(smsResult.message ?? 'Failed to send SMS notification'); + // } // Mark notification as sent diff --git a/src/modules/notifications/services/notification.service.ts b/src/modules/notifications/services/notification.service.ts index 3280f66..7c934a2 100644 --- a/src/modules/notifications/services/notification.service.ts +++ b/src/modules/notifications/services/notification.service.ts @@ -46,10 +46,13 @@ export class NotificationService { if (preference?.channels?.includes(NotifChannelEnum.IN_APP)) { recipients.forEach(recipient => { if ('adminId' in recipient) { - this.notificationGateway.sendInAppNotification({ adminId: recipient.adminId, restaurantId }, 'notification', { - title: message.subject, - content: message.body, - }); + this.notificationGateway.sendInAppNotification( + { adminId: recipient.adminId, restaurantId }, + { + subject: message.subject, + body: message.body, + }, + ); } }); } diff --git a/src/modules/notifications/services/sms.adaptor.ts b/src/modules/notifications/services/sms.adaptor.ts index 2885fe1..8fbdd1a 100644 --- a/src/modules/notifications/services/sms.adaptor.ts +++ b/src/modules/notifications/services/sms.adaptor.ts @@ -20,9 +20,9 @@ export class SmsAdaptorService { const { phone, subject, payload } = params; let templateId!: string; switch (subject) { - case NotifTitleEnum.ORDER_CREATED: - templateId = this.smsPatternOrderCreated; - break; + // case NotifTitleEnum.ORDER_CREATED: + // templateId = this.smsPatternOrderCreated; + // break; case NotifTitleEnum.PAYMENT_SUCCESS: templateId = this.smsPatternPaymentSuccess; break; diff --git a/test-notifications-socket.html b/test-notifications-socket.html index ecdf2c7..e010896 100644 --- a/test-notifications-socket.html +++ b/test-notifications-socket.html @@ -370,7 +370,7 @@ addEvent('ERROR', `Connection error: ${error.message}`); }); - socket.on('notifications:list', data => { + socket.on('notifications', data => { addEvent('SUCCESS', `Received ${data.notifications?.length || 0} notifications`, data); displayNotifications(data.notifications || []); });