update
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<void> {
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 || []);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user