push notification

fix implemented
This commit is contained in:
dimitar committed 2026-02-22 04:00:20 +01:00
1 parent 0bbf2ab56f
commit 57864e00da
15 files changed
+5126 -26

No files matched your search

+32 -1
View File
@@ -6,12 +6,17 @@ import {
Body,
HttpCode,
HttpStatus,
UseGuards,
} from '@nestjs/common';
import { PushService } from './push.service';
import { SubscribeDto, UnsubscribeDto } from './push.dto';
import { SubscribeDto, UnsubscribeDto, SendNotificationDto } from './push.dto';
import { Public } from '../auth/public.decorator';
import { Roles } from '../auth/roles.decorator';
import { RolesGuard } from '../auth/roles.guard';
import { UserRole } from '../entities';
@Controller('push')
@UseGuards(RolesGuard)
export class PushController {
constructor(private readonly pushService: PushService) {}
@@ -25,6 +30,12 @@ export class PushController {
@Post('subscribe')
@HttpCode(HttpStatus.CREATED)
async subscribe(@Body() dto: SubscribeDto): Promise<{ success: boolean }> {
console.log('Received push subscription:', {
endpoint: dto.endpoint?.substring(0, 50) + '...',
hasP256dh: !!dto.p256dh,
hasAuth: !!dto.auth,
userId: dto.userId,
});
await this.pushService.subscribe(dto);
return { success: true };
}
@@ -35,4 +46,24 @@ export class PushController {
async unsubscribe(@Body() dto: UnsubscribeDto): Promise<void> {
await this.pushService.unsubscribe(dto);
}
@Roles(UserRole.ADMIN)
@Get('stats')
getStats(): Promise<{ totalSubscribers: number }> {
return this.pushService.getStats();
}
@Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
@Post('send')
@HttpCode(HttpStatus.OK)
async sendNotification(
@Body() dto: SendNotificationDto,
): Promise<{ sent: number; failed: number }> {
return this.pushService.sendToAll({
title: dto.title,
body: dto.body,
url: dto.url,
tag: 'admin-notification',
});
}
}
+17 -3
View File
@@ -1,7 +1,7 @@
import { IsString, IsNotEmpty, IsOptional, IsUrl } from 'class-validator';
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
export class SubscribeDto {
@IsUrl()
@IsString()
@IsNotEmpty()
endpoint: string;
@@ -19,7 +19,21 @@ export class SubscribeDto {
}
export class UnsubscribeDto {
@IsUrl()
@IsString()
@IsNotEmpty()
endpoint: string;
}
export class SendNotificationDto {
@IsString()
@IsNotEmpty()
title: string;
@IsString()
@IsNotEmpty()
body: string;
@IsOptional()
@IsString()
url?: string;
}
+13 -1
View File
@@ -49,11 +49,15 @@ export class PushService implements OnModuleInit {
}
async subscribe(dto: SubscribeDto): Promise<PushSubscriptionEntity> {
this.logger.log('Subscribing push notification...');
this.logger.debug(`Endpoint: ${dto.endpoint?.substring(0, 50)}...`);
const existing = await this.subscriptionRepo.findOne({
where: { endpoint: dto.endpoint },
});
if (existing) {
this.logger.log('Subscription already exists, updating...');
if (dto.userId && existing.userId !== dto.userId) {
existing.userId = dto.userId;
return this.subscriptionRepo.save(existing);
@@ -61,6 +65,7 @@ export class PushService implements OnModuleInit {
return existing;
}
this.logger.log('Creating new subscription...');
const subscription = this.subscriptionRepo.create({
endpoint: dto.endpoint,
p256dh: dto.p256dh,
@@ -68,7 +73,9 @@ export class PushService implements OnModuleInit {
userId: dto.userId ?? null,
});
return this.subscriptionRepo.save(subscription);
const saved = await this.subscriptionRepo.save(subscription);
this.logger.log(`Subscription saved with ID: ${saved.id}`);
return saved;
}
async unsubscribe(dto: UnsubscribeDto): Promise<void> {
@@ -170,4 +177,9 @@ export class PushService implements OnModuleInit {
tag: `live-blog-${blogSlug}`,
});
}
async getStats(): Promise<{ totalSubscribers: number }> {
const totalSubscribers = await this.subscriptionRepo.count();
return { totalSubscribers };
}
}