remove unused packages
This commit is contained in:
Generated
+15698
-16888
File diff suppressed because it is too large
Load Diff
+1
-5
@@ -69,14 +69,10 @@
|
||||
"class-validator": "^0.14.2",
|
||||
"dayjs": "^1.11.19",
|
||||
"fastify": "^5.6.1",
|
||||
"firebase-admin": "^13.6.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1",
|
||||
"sanitize-html": "^2.17.0",
|
||||
"slugify": "^1.6.6",
|
||||
"socket.io": "^4.8.1",
|
||||
"ulid": "^3.0.1",
|
||||
"uuid": "^13.0.0"
|
||||
"ulid": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
|
||||
Generated
-14002
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
import { ApiProperty, PartialType } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsUUID } from "class-validator";
|
||||
|
||||
import { CommonMessage } from "../enums/message.enum";
|
||||
|
||||
export class ParamDto {
|
||||
@IsNotEmpty({ message: CommonMessage.ID_REQUIRED })
|
||||
@IsUUID("4", { message: CommonMessage.ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Id of the entity", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" })
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class OptionalParamDto extends PartialType(ParamDto) {}
|
||||
|
||||
export class ParamNumberIdDto {
|
||||
@IsNotEmpty({ message: CommonMessage.ID_REQUIRED })
|
||||
@ApiProperty({ description: "Id of the entity", example: "20" })
|
||||
id: string;
|
||||
}
|
||||
@@ -5,9 +5,7 @@ import { JwtModule } from '@nestjs/jwt';
|
||||
import { Notification } from './entities/notification.entity';
|
||||
import { NotificationService } from './services/notification.service';
|
||||
import { NotificationQueueService } from './services/notification-queue.service';
|
||||
import { PushNotificationService } from './services/push-notification.service';
|
||||
import { SmsProcessor } from './processors/sms.processor';
|
||||
import { PushProcessor } from './processors/push.processor';
|
||||
import { NotificationsController } from './controllers/notifications.controller';
|
||||
import { User } from '../user/entities/user.entity';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
@@ -53,8 +51,6 @@ import { SmsListeners } from './listeners/sms.listeners';
|
||||
providers: [
|
||||
NotificationService,
|
||||
NotificationQueueService,
|
||||
PushNotificationService,
|
||||
PushProcessor,
|
||||
SmsProcessor,
|
||||
InAppProcessor,
|
||||
NotificationsGateway,
|
||||
@@ -65,6 +61,6 @@ import { SmsListeners } from './listeners/sms.listeners';
|
||||
SmsListeners,
|
||||
],
|
||||
exports: [NotificationService, NotificationQueueService,
|
||||
PushNotificationService, SmsService, NotificationsGateway],
|
||||
SmsService, NotificationsGateway],
|
||||
})
|
||||
export class NotificationsModule { }
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import { Processor, WorkerHost, OnWorkerEvent } from '@nestjs/bullmq';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { Job } from 'bullmq';
|
||||
import { InjectRepository } from '@mikro-orm/nestjs';
|
||||
import { EntityRepository, EntityManager } from '@mikro-orm/postgresql';
|
||||
import { Notification } from '../entities/notification.entity';
|
||||
import { PushNotificationQueueJob } from '../interfaces/jobs-queue.interface';
|
||||
import { NotificationQueueNameEnum } from '../constants/queue';
|
||||
import { PushNotificationService } from '../services/push-notification.service';
|
||||
|
||||
@Processor(NotificationQueueNameEnum.PUSH)
|
||||
export class PushProcessor extends WorkerHost {
|
||||
private readonly logger = new Logger(PushProcessor.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(Notification)
|
||||
private readonly notificationRepository: EntityRepository<Notification>,
|
||||
private readonly em: EntityManager,
|
||||
private readonly pushNotificationService: PushNotificationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async process(job: Job<PushNotificationQueueJob>) {
|
||||
const { title, content, action, pushToken, pushTokens } = job.data;
|
||||
|
||||
this.logger.log(`Processing push notification job: ${job.id} - Title: ${title},`);
|
||||
|
||||
try {
|
||||
// Get push token from job data
|
||||
const pushToken = job.data.pushToken;
|
||||
const pushTokens = job.data.pushTokens;
|
||||
|
||||
if (!pushToken && (!pushTokens || pushTokens.length === 0)) {
|
||||
this.logger.warn(`Push token(s) not provided for notification `);
|
||||
throw new Error('Push token or pushTokens array is required for push notifications');
|
||||
}
|
||||
|
||||
// Send push notification
|
||||
// Convert NotificationTitle enum to a readable string for the notification title
|
||||
const notificationTitle = String(title)
|
||||
.replace(/\./g, ' ')
|
||||
.replace(/\b\w/g, l => l.toUpperCase());
|
||||
|
||||
let pushResult;
|
||||
if (pushTokens && pushTokens.length > 0) {
|
||||
// Send to multiple tokens
|
||||
pushResult = await this.pushNotificationService.sendToMultipleTokens({
|
||||
title: notificationTitle,
|
||||
body: content,
|
||||
tokens: pushTokens,
|
||||
data: {
|
||||
action,
|
||||
},
|
||||
});
|
||||
} else if (pushToken) {
|
||||
// Send to single token
|
||||
pushResult = await this.pushNotificationService.sendToToken({
|
||||
title: notificationTitle,
|
||||
body: content,
|
||||
token: pushToken,
|
||||
data: {
|
||||
action,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
throw new Error('Push token or pushTokens array is required');
|
||||
}
|
||||
|
||||
if (!pushResult.success) {
|
||||
throw new Error(pushResult.error || 'Failed to send push notification');
|
||||
}
|
||||
|
||||
this.logger.log(`Push notification sent successfully`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
providerResponse: { messageId: pushResult.messageId },
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(`Error processing push notification job ${job.id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@OnWorkerEvent('completed')
|
||||
onCompleted(job: Job) {
|
||||
this.logger.log(`Notification job ${job.id} completed`);
|
||||
}
|
||||
|
||||
@OnWorkerEvent('failed')
|
||||
onFailed(job: Job, error: Error) {
|
||||
this.logger.error(`Notification job ${job.id} failed:`, error);
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
import { Injectable, Logger, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as admin from 'firebase-admin';
|
||||
|
||||
export interface PushNotificationPayload {
|
||||
title: string;
|
||||
body: string;
|
||||
data?: Record<string, unknown>;
|
||||
token?: string;
|
||||
tokens?: string[];
|
||||
}
|
||||
|
||||
export interface PushNotificationResponse {
|
||||
success: boolean;
|
||||
messageId?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PushNotificationService {
|
||||
private readonly logger = new Logger(PushNotificationService.name);
|
||||
private firebaseApp: admin.app.App | null = null;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.initializeFirebase();
|
||||
}
|
||||
|
||||
private initializeFirebase() {
|
||||
try {
|
||||
const firebaseConfig = this.configService.get<string>('FIREBASE_SERVICE_ACCOUNT');
|
||||
|
||||
if (!firebaseConfig) {
|
||||
this.logger.warn('Firebase service account not configured. Push notifications will be disabled.');
|
||||
return;
|
||||
}
|
||||
|
||||
const serviceAccount = JSON.parse(firebaseConfig);
|
||||
|
||||
if (!this.firebaseApp) {
|
||||
this.firebaseApp = admin.initializeApp({
|
||||
credential: admin.credential.cert(serviceAccount),
|
||||
});
|
||||
this.logger.log('Firebase initialized successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to initialize Firebase:', error);
|
||||
this.logger.warn('Push notifications will be disabled');
|
||||
}
|
||||
}
|
||||
|
||||
async sendToToken(payload: PushNotificationPayload): Promise<PushNotificationResponse> {
|
||||
if (!this.firebaseApp || !payload.token) {
|
||||
throw new HttpException(
|
||||
'Push notification service not configured or token missing',
|
||||
HttpStatus.SERVICE_UNAVAILABLE,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const message: admin.messaging.Message = {
|
||||
notification: {
|
||||
title: payload.title,
|
||||
body: payload.body,
|
||||
},
|
||||
data: this.convertDataToString(payload.data || {}),
|
||||
token: payload.token,
|
||||
android: {
|
||||
priority: 'high',
|
||||
},
|
||||
apns: {
|
||||
headers: {
|
||||
'apns-priority': '10',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const response = await admin.messaging().send(message);
|
||||
this.logger.log(`Push notification sent successfully: ${response}`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
messageId: response,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to send push notification: ${error}`);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async sendToMultipleTokens(payload: PushNotificationPayload): Promise<PushNotificationResponse> {
|
||||
if (!this.firebaseApp || !payload.tokens || payload.tokens.length === 0) {
|
||||
throw new HttpException(
|
||||
'Push notification service not configured or tokens missing',
|
||||
HttpStatus.SERVICE_UNAVAILABLE,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const message: admin.messaging.MulticastMessage = {
|
||||
notification: {
|
||||
title: payload.title,
|
||||
body: payload.body,
|
||||
},
|
||||
data: this.convertDataToString(payload.data || {}),
|
||||
tokens: payload.tokens,
|
||||
android: {
|
||||
priority: 'high',
|
||||
},
|
||||
apns: {
|
||||
headers: {
|
||||
'apns-priority': '10',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const response = await admin.messaging().sendEachForMulticast(message);
|
||||
this.logger.log(`Push notifications sent: ${response.successCount} successful, ${response.failureCount} failed`);
|
||||
|
||||
return {
|
||||
success: response.successCount > 0,
|
||||
messageId: response.responses[0]?.messageId,
|
||||
error: response.failureCount > 0 ? `${response.failureCount} notifications failed` : undefined,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to send push notifications: ${error}`);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private convertDataToString(data: Record<string, unknown>): Record<string, string> {
|
||||
const result: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
result[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
isConfigured(): boolean {
|
||||
return this.firebaseApp !== null;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
/**
|
||||
* Sanitizes user input to prevent XSS attacks and remove malicious content
|
||||
* Allows only safe text content, removing all HTML tags and scripts
|
||||
* @param input - The string to sanitize
|
||||
* @returns Sanitized string with all HTML tags and scripts removed
|
||||
*/
|
||||
export function sanitizeText(input: string | undefined | null): string | undefined | null {
|
||||
if (!input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return sanitizeHtml(input, {
|
||||
allowedTags: [], // No HTML tags allowed
|
||||
allowedAttributes: {}, // No attributes allowed
|
||||
allowedSchemes: [], // No URL schemes allowed
|
||||
}).trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user