Skip to content

Commit

Permalink
handle and use web push notification subscription object
Browse files Browse the repository at this point in the history
  • Loading branch information
gianlazz committed Jun 1, 2024
1 parent 86b634b commit de3d9fc
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/dal/entity/userDevice.entity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Entity, IdentifiedReference, ManyToOne, PrimaryKey, Property, Unique } from '@mikro-orm/core';
import { Field, ID, ObjectType } from '@nestjs/graphql';
import { User } from './user.entity';
import webpush from 'web-push';

@ObjectType()
@Entity()
Expand All @@ -14,6 +15,9 @@ export class UserDevice {
@Property({ fieldName: 'fcmPushUserToken' })
public fcmPushUserToken!: string;

@Property({ type: 'json', nullable: true })
webPushSubscription?: webpush.PushSubscription;

@ManyToOne({
entity: () => User,
fieldName: 'userId',
Expand Down
9 changes: 9 additions & 0 deletions src/dal/migrations/postgres/.snapshot-postgres.json
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,15 @@
"nullable": false,
"mappedType": "string"
},
"web_push_subscription": {
"name": "web_push_subscription",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"userId": {
"name": "userId",
"type": "int",
Expand Down
13 changes: 13 additions & 0 deletions src/dal/migrations/postgres/Migration20240601210639.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20240601210639 extends Migration {

async up(): Promise<void> {
this.addSql('alter table "user_device" add column "web_push_subscription" jsonb null;');
}

async down(): Promise<void> {
this.addSql('alter table "user_device" drop column "web_push_subscription";');
}

}
42 changes: 36 additions & 6 deletions src/notification/notification.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { InjectRepository } from '@mikro-orm/nestjs';
import { EntityRepository } from '@mikro-orm/core';
import webpush from 'web-push';
import _ from 'lodash';

@Service()
export class NotificationService {
Expand Down Expand Up @@ -76,6 +77,25 @@ export class NotificationService {
}
}

public async addUserWebPushNotificationSubscription(
userId: any,
subscription: webpush.PushSubscription,
): Promise<void> {
this.logger.debug(this.addUserFcmNotificationToken.name);
const user = await this.userRepository.findOne({ id: userId });

if (!(await user.userDevices.loadItems()).find((x) => _.isEqual(x.webPushSubscription, subscription))) {
const userDevice = this.userDeviceRepository.create({
user: { id: user.id },
webPushSubscription: subscription,
});
await this.userDeviceRepository.persistAndFlush(userDevice);
// TODO notify via email that a new device has been used on the account for security.
} else {
this.logger.warn('User device web push notification subscription already stored.');
}
}

/**
* Fetch a users in app notifications, with optional pagination
* @param userId users id
Expand Down Expand Up @@ -132,21 +152,31 @@ export class NotificationService {
notification: PushNotificationDto,
): Promise<void> {
this.logger.debug(this.sendPushToUser.name);

const user = await this.userRepository.findOne({ id: userId });

// native push notifications
const fcmUserTokens = (await user.userDevices.loadItems()).map(
(x) => x.fcmPushUserToken,
);

this.logger.debug(
`${fcmUserTokens.length} push notification tokens found for userId: ${userId}`,
);

for (const iterator of fcmUserTokens) {
await this.sendPushNotification(notification, iterator);

this.logger.debug(`Sent push notification to fcmToken ${iterator}`);
}

// web push notifications
const webPushSubscriptions = (await user.userDevices.loadItems()).map(
(x) => x.webPushSubscription,
);
this.logger.debug(
`${webPushSubscriptions.length} web push notification subscriptions found for userId: ${userId}`,
);
for (const subscription of webPushSubscriptions) {
await this.sendWebPushNotification(notification, subscription);
this.logger.debug(`Sent web push notification to subscription: ${JSON.stringify(subscription)}`);
}
}

private async sendPushNotification(
Expand All @@ -173,12 +203,12 @@ export class NotificationService {

private async sendWebPushNotification(
notification: PushNotificationDto,
to: string,
to: webpush.PushSubscription,
) {
this.logger.debug(this.sendWebPushNotification.name);
webpush
.sendNotification(
subscription,
to,
JSON.stringify({
notification
}),
Expand Down

0 comments on commit de3d9fc

Please sign in to comment.