Skip to content

Commit

Permalink
Merge pull request #175 from sayinmehmet47/notification-by-service-wo…
Browse files Browse the repository at this point in the history
…rkers-when-book-loaded

feat: book uploading notification for users
  • Loading branch information
sayinmehmet47 authored Mar 7, 2024
2 parents a580fa2 + 00bf3ad commit fefcda5
Show file tree
Hide file tree
Showing 56 changed files with 639 additions and 925 deletions.
3 changes: 3 additions & 0 deletions backend/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ app.use(json());
const books = require('./routes/api/books');
const user = require('./routes/api/user');
const messages = require('./routes/api/messages');
const subscription = require('./routes/api/subscription');

app.use(express.json());

Expand All @@ -31,6 +32,8 @@ app.use(cors(corsOptions));
app.use('/api/books', books);
app.use('/api/user', user);
app.use('/api/messages', messages);
app.use('/api/subscription', subscription);

app.use(updateMetrics);

app.all('*', (req: Request, res: Response) => {
Expand Down
4 changes: 0 additions & 4 deletions backend/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import jwt from 'jsonwebtoken';
export const auth = (req: Request, res: Response, next: NextFunction) => {
const token = req.header('Authorization')?.split(' ')[1];

// Check for token
if (!token)
return res.status(401).json({ msg: 'No token, authorization denied' });

Expand All @@ -17,12 +16,9 @@ export const auth = (req: Request, res: Response, next: NextFunction) => {
}
};

// is admin

export const isAdmin = (req: Request, res: Response, next: NextFunction) => {
const token = req.header('Authorization')?.split(' ')[1];

// Check for token
if (!token)
return res.status(401).json({ msg: 'No token, authorization denied' });

Expand Down
16 changes: 16 additions & 0 deletions backend/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ const userSchema = new Schema(
ref: 'Messages',
},
],
subscription: {
endpoint: {
type: String,
required: false,
},
keys: {
auth: {
type: String,
required: false,
},
p256dh: {
type: String,
required: false,
},
},
},
},
{
timestamps: true,
Expand Down
123 changes: 121 additions & 2 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"@types/node": "^18.17.12",
"@types/web-push": "^3.6.3",
"axios": "^1.5.0",
"axios-rate-limit": "^1.3.0",
"bcrypt": "^5.0.1",
Expand All @@ -42,7 +43,8 @@
"node-cron": "^3.0.2",
"node-url-shortener": "^2.0.3",
"prom-client": "^14.2.0",
"validator": "^13.7.0"
"validator": "^13.7.0",
"web-push": "^3.6.7"
},
"license": "MIT",
"devDependencies": {
Expand Down
59 changes: 38 additions & 21 deletions backend/routes/api/books.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
import { Error } from 'mongoose';
import axios from 'axios';
import express, { NextFunction, Request, Response } from 'express';
import { auth, isAdmin } from '../../middleware/auth';
import { NotFoundError } from '../../errors/not-found-error';
import { body } from 'express-validator';
import { validateRequest } from '../../middleware/validate-request';
import axios from 'axios';

import Bottleneck from 'bottleneck';
import { Books, IBook } from '../../models/Books';
import { Books } from '../../models/Books';
import { BooksData, Item } from './books.types';
import {
getUserSubscriptionsExcludingUser,
removeSubscription,
} from '../../web-push';
import * as webpush from 'web-push';

const router = express.Router();
const NodeCache = require('node-cache');
const cache = new NodeCache();

interface VolumeInfo {
categories: string[];
}

interface Item {
volumeInfo: VolumeInfo;
}
export interface BooksData {
results: IBook[];
total: number;
page: number;
next?: {
page: number;
};
previous?: {
page: number;
};
}

router.get('/allBooks', async (req: Request, res: Response) => {
try {
const page = parseInt(String(req.query.page)) || 1;
Expand Down Expand Up @@ -185,6 +174,34 @@ router.post(

await books.save();

const user = req.body.user;

const payload = JSON.stringify({
title: 'New Book Added',
body: `A new book "${req.body.name}" has been added!`,
});

const subscriptions = await getUserSubscriptionsExcludingUser(user.id);

subscriptions.forEach((subscription) => {
if (subscription?.subscription?.endpoint) {
webpush
.sendNotification(
subscription.subscription as webpush.PushSubscription,
payload
)
.catch((error) => {
if (error.statusCode === 410) {
removeSubscription(subscription.subscription);
} else {
console.error('Error sending push notification:', error);
}
});
} else {
console.error('Invalid subscription endpoint:', subscription);
}
});

res.status(201).json(books);
}
);
Expand Down
20 changes: 20 additions & 0 deletions backend/routes/api/books.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IBook } from '../../models/Books';

export interface VolumeInfo {
categories: string[];
}

export interface Item {
volumeInfo: VolumeInfo;
}
export interface BooksData {
results: IBook[];
total: number;
page: number;
next?: {
page: number;
};
previous?: {
page: number;
};
}
23 changes: 23 additions & 0 deletions backend/routes/api/subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import express, { Request, Response } from 'express';
import { User } from '../../models/User';

const router = express.Router();

router.post('/', async (req: Request, res: Response) => {
const sub = req.body.subscription;
const user = req.body.user;

if (!sub || !user) {
return res
.status(400)
.json({ message: 'Missing subscription information.' });
}

User.findByIdAndUpdate(user._id, {
$set: { subscription: sub },
}).catch((e) => console.error(e));

res.status(201).json({ message: 'Subscription added successfully.' });
});

module.exports = router;
Loading

0 comments on commit fefcda5

Please sign in to comment.