diff --git a/.env.production b/.env.production index ab95a70..6332ea1 100644 --- a/.env.production +++ b/.env.production @@ -7,10 +7,11 @@ URLBASE_APP1=https://freeplanet.app PORT_APP1="0" DOMAIN=mongodb://localhost:27017/ SIGNCODE=abc123 -EMAIL_FROM=perseo774.un@gmail.com +EMAIL_FROM=perseo.774un@gmail.com EMAIL_PW=passpao1UNOK DEBUG=0 PATH_CERT_KEY=/etc/letsencrypt/live/freeplanet.app/privkey.pem PATH_SERVER_CRT=/etc/letsencrypt/live/freeplanet.app/fullchain.pem -PUBLIC_VAPI_KEY=BJGWIAlFXXQWqdBIEujrDJ7ZQeQmcwTOXr1kPfYy2ZCI6hvV9jhfquW2uHVoOiSYpoF6HeqnaydsIV5SeEpFbCk -PRIVATE_VAPI_KEY=40Cn-P-j8iPs5RRR4VsH2lgmYSXqA5xK-nppK_HCbgA +PUBLIC_VAPI_KEY="BNM-cEpTbPVc_ujXf3QOC8ggf7b-X44P44esfJUWqNOFq1XhWCoZJpOi71_cbXC5SnfO9HassQ6OouAYgtBA9Pw" +PRIVATE_VAPI_KEY="DtG3R-jzQiOSV8BJe6zSPUIIXoe5xcJ69U9o0wGLZxs" +GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" diff --git a/package.json b/package.json index fb243fa..4ea34a6 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "nodemailer": "^4.6.8", "preview-email": "0.0.8", "pug": "^2.0.3", + "url-parse": "^1.4.4", "validator": "^5.6.0", "web-push": "^3.3.3", "xoauth2": "^1.2.0" diff --git a/server/config/config.js b/server/config/config.js index 6c2fef8..40a38d2 100644 --- a/server/config/config.js +++ b/server/config/config.js @@ -15,6 +15,3 @@ require('dotenv').config({path: file}); process.env.DATABASE = process.env.DATABASE || 'FreePlanet'; process.env.MONGODB_URI = process.env.DOMAIN + process.env.DATABASE; - -// console.log("priv", process.env.PRIVATE_VAPI_KEY); -// console.log("pub", process.env.PUBLIC_VAPI_KEY); diff --git a/server/middleware/authenticate.js b/server/middleware/authenticate.js index d48f1f2..27716ed 100644 --- a/server/middleware/authenticate.js +++ b/server/middleware/authenticate.js @@ -7,9 +7,7 @@ const tools = require('../tools/general'); var authenticate = (req, res, next) => { var token = req.header('x-auth'); - const useragent = req.get('User-Agent'); - const access = 'auth ' + useragent; - + const access = 'auth'; User.findByToken(token, access).then((user) => { if (!user) { diff --git a/server/models/subscribers.js b/server/models/subscribers.js index d2843b3..61e3340 100644 --- a/server/models/subscribers.js +++ b/server/models/subscribers.js @@ -17,6 +17,7 @@ const SubscriberSchema = new Schema({ keys: Schema.Types.Mixed, userId: String, access: String, + browser: String, createDate: { type: Date, default: Date.now diff --git a/server/models/user.js b/server/models/user.js index 8bab6fa..d379304 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -61,6 +61,10 @@ var UserSchema = new mongoose.Schema({ type: String, required: true }, + browser: { + type: String, + required: true + }, token: { type: String, required: true @@ -92,13 +96,14 @@ UserSchema.methods.generateAuthToken = function (req) { const useragent = req.get('User-Agent'); tools.mylog("GENERATE USER-AGENT = ", useragent); - var access = 'auth ' + useragent; + var access = 'auth'; + const browser = useragent; var token = jwt.sign({ _id: user._id.toHexString(), access }, process.env.SIGNCODE).toString(); var date_login = new Date(); // CANCELLA IL PRECEDENTE ! - user.tokens = user.tokens.filter(function(tok) { return tok.access !== access; }); - user.tokens.push({ access, token, date_login }); + user.tokens = user.tokens.filter(function(tok) { return (tok.access !== access) || ((tok.access === access) && (tok.browser !== browser) ) ; }); + user.tokens.push({ access, browser, token, date_login }); return user.save() .then(() => { diff --git a/server/router/subscribe_router.js b/server/router/subscribe_router.js index 55767b9..5275636 100644 --- a/server/router/subscribe_router.js +++ b/server/router/subscribe_router.js @@ -2,7 +2,6 @@ const express = require('express'); const router = express.Router(); const mongoose = require('mongoose'); const Subscription = mongoose.model('subscribers'); -const webpush = require('web-push'); const tools = require('../tools/general'); @@ -27,7 +26,7 @@ const isValidSaveRequest = (req, res) => { } }; -router.post('/', (req, res) => { +router.post('/', authenticate, (req, res) => { console.log('req.body.others', req.body.others); if (!isValidSaveRequest(req, res)) { @@ -37,9 +36,10 @@ router.post('/', (req, res) => { let subscriptionModel = new Subscription(req.body.subs); subscriptionModel.userId = req.body.others.userId; subscriptionModel.access = req.body.others.access; + subscriptionModel.browser = req.get('User-Agent'); // Find if already exist - Subscription.findOne( {userId: subscriptionModel.userId, access: subscriptionModel.access}) + Subscription.findOne( {userId: subscriptionModel.userId, access: subscriptionModel.access, browser: subscriptionModel.browser}) .then(itemsub => { return itemsub }) @@ -67,7 +67,9 @@ router.post('/', (req, res) => { // res.status(201).json({ data: 'Subscription saved.' }); res.send({ data: 'Subscription saved.' }); - tools.sendBackNotif(subscription, req.body.options) + if (req.body.options !== null) { + tools.sendBackNotif(subscription, req.body.options) + } } }); @@ -78,7 +80,8 @@ router.post('/', (req, res) => { router.delete('/del', authenticate, (req, res) => { // tools.mylog("TOKENREM = " + req.token); - Subscription.findOneAndRemove( { userId: req.user._id, access: req.access } ).then(() => { + const browser = req.get('User-Agent'); + Subscription.findOneAndRemove( { userId: req.user._id, access: req.access, browser } ).then(() => { res.status(200).send(); }, () => { res.status(400).send(); diff --git a/server/router/todos_router.js b/server/router/todos_router.js index e79bb00..7fdcd44 100644 --- a/server/router/todos_router.js +++ b/server/router/todos_router.js @@ -1,14 +1,6 @@ const express = require('express'); const router = express.Router(); - -// SETTINGS WebPush Configuration -const webpush = require('web-push'); - -const publicVapidKey = process.env.PUBLIC_VAPI_KEY; -const privateVapidKey = process.env.PRIVATE_VAPI_KEY; -webpush.setVapidDetails('mailto:' + process.env.EMAIL_FROM, publicVapidKey, privateVapidKey); - const tools = require('../tools/general'); var server_constants = require('../tools/server_constants'); @@ -58,7 +50,7 @@ router.post('/', authenticate, (req, res) => { .then(record => { tools.mylog('REC SAVED :', record.descr); - sendNotificationToUser(todo.userId, 'Todo: ' + record.descr, record.descr, '/todo/' + todo.category, 'todo') + tools.sendNotificationToUser(todo.userId, 'Todo: ' + record.descr, record.descr, '/todo/' + todo.category, 'todo') .then(ris => { if (ris) { res.send({ record }); @@ -74,85 +66,6 @@ router.post('/', authenticate, (req, res) => { }); -function sendNotificationToUser(userId, title, content, openUrl, tag) { - - const payload = { - title: title, - message: content, - url: openUrl, - tag, - // ttl: req.body.ttl, - // icon: req.body.icon, - // image: req.body.image, - // badge: req.body.badge, - // tag: req.body.tag - }; - - return Subscription.find({ userId }, (err, subscriptions) => { - if (err) { - console.error(`Error occurred while getting subscriptions`); - res.status(500).json({ - error: 'Technical error occurred' - }); - return false; - } else { - let parallelSubscriptionCalls = subscriptions.map((subscription) => { - return new Promise((resolve, reject) => { - const pushSubscription = { - endpoint: subscription.endpoint, - keys: { - p256dh: subscription.keys.p256dh, - auth: subscription.keys.auth - } - }; - - const pushPayload = JSON.stringify(payload); - const pushOptions = { - vapidDetails: { - subject: process.env.URLBASE_APP1, - privateKey: process.env.PRIVATE_VAPI_KEY, - publicKey: process.env.PUBLIC_VAPI_KEY, - }, - TTL: payload.ttl, - headers: {} - }; - - // console.log('pushSubscription', pushSubscription); - // console.log('pushOptions', pushOptions); - // console.log('pushPayload', pushPayload); - - webpush.sendNotification( - pushSubscription, - pushPayload, - pushOptions - ).then((value) => { - resolve({ - status: true, - endpoint: subscription.endpoint, - data: value - }); - }).catch((err) => { - reject({ - status: false, - endpoint: subscription.endpoint, - data: err - }); - }); - }).catch(error => { - console.log('ERROR: sendNotificationToUser', error.data) - }); - }); - // q.allSettled(parallelSubscriptionCalls).then((pushResults) => { - // console.info(pushResults); - // }); - // res.json({ - // data: 'Push triggered' - // }); - return true; - } - }); - -} router.patch('/:id', authenticate, (req, res) => { var id = req.params.id; diff --git a/server/router/users_router.js b/server/router/users_router.js index 8bc404f..122e9f1 100644 --- a/server/router/users_router.js +++ b/server/router/users_router.js @@ -18,8 +18,8 @@ var { authenticate } = require('../middleware/authenticate'); var mongoose = require('mongoose'); const Subscription = mongoose.model('subscribers'); -function existSubScribe(userId, access) { - return Subscription.findOne({ userId, access }) +function existSubScribe(userId, access, browser) { + return Subscription.findOne({ userId, access, browser }) .then(itemsub => { return itemsub }) @@ -126,11 +126,11 @@ router.post('/login', (req, res) => { }) .then((myris) => { - const useragent = req.get('User-Agent'); - const access = 'auth ' + useragent; + const access = 'auth'; + const browser = req.get('User-Agent'); // Check if already exist Subscribe - return existSubScribe(myris.usertosend.userId, access).then(subscribe => { + return existSubScribe(myris.usertosend.userId, access, browser).then(subscribe => { return (subscribe !== null) }).then(subsExistonDb => { return { usertosend: myris.usertosend, token: myris.token, subsExistonDb } diff --git a/server/server.js b/server/server.js index 7bed679..9a36749 100644 --- a/server/server.js +++ b/server/server.js @@ -11,6 +11,7 @@ const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); + i18n = require("i18n"); if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test')) { @@ -42,6 +43,8 @@ console.log("MONGODB_URI: " + process.env.MONGODB_URI); var app = express(); +const tools = require('./tools/general'); + // app.use(express.static(path.join(__dirname, 'client'))); app.use(bodyParser.json()); @@ -66,7 +69,6 @@ app.use(bodyParser.json()); app.use(i18n.init); - // Use Routes app.use('/', index_router); app.use('/subscribe', subscribe_router); @@ -91,7 +93,7 @@ if (app.get('env') === 'development') { app.use(function (err, req, res, next) { console.log('Error: ', err.message); // console.trace(); - res.status(err.status || 500).send({error: err.message}); + res.status(err.status || 500).send({ error: err.message }); // res.render('error', { // message: err.message, // error: err @@ -109,6 +111,27 @@ if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test') httpServer.listen(port); } +testmsgwebpush(); + +function testmsgwebpush() { + var { User } = require('./models/user'); + // const tools = require('./tools/general'); + + User.findOne().then((user) => { + if (user !== null) { + tools.sendNotificationToUser(user._id, 'Titolo msg Test', 'Test Messaggio', '/', 'msg') + .then(ris => { + if (ris) { + + } else { + // already sent the error on calling sendNotificationToUser + } + }) + } + }) + +} + //app.listen(port, () => { // console.log(`Server started at port ${port}`); //}); diff --git a/server/tests/seed/seed.js b/server/tests/seed/seed.js index 951c9d1..4613049 100644 --- a/server/tests/seed/seed.js +++ b/server/tests/seed/seed.js @@ -38,8 +38,9 @@ const users = [{ username: 'paoloar77B', password: mypwdcrypted, tokens: [{ - access: 'auth ' + useragent, - token: jwt.sign({ _id: userOneId, access: 'auth ' + useragent }, process.env.SIGNCODE).toString(), + access: 'auth', + browser: useragent, + token: jwt.sign({ _id: userOneId, access: 'auth' }, process.env.SIGNCODE).toString(), date_login }] }, @@ -52,8 +53,9 @@ const users = [{ password: mypwdcrypted, username: 'paoloar77C', tokens: [{ - access: 'auth ' + useragent, - token: jwt.sign({ _id: userTwoId, access: 'auth ' + useragent }, process.env.SIGNCODE).toString(), + access: 'auth', + browser: useragent, + token: jwt.sign({ _id: userTwoId, access: 'auth' }, process.env.SIGNCODE).toString(), date_login }] }, { diff --git a/server/tests/server.test.js b/server/tests/server.test.js index 4e8fc3e..9c7c72c 100644 --- a/server/tests/server.test.js +++ b/server/tests/server.test.js @@ -36,7 +36,7 @@ const IndexTodoToCreate = 3; // const useragent = "auth Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36"; const useragent = "node-superagent/2.3.0"; -const testsingolo = true; +const testsingolo = false; if (testsingolo) { describe('POST /users/login', () => { @@ -63,7 +63,7 @@ if (testsingolo) { User.findById(users[0]._id).then((user) => { expect(user.tokens[0]).toInclude({ - access: 'auth ' + useragent, + access: 'auth', // token: res.headers['x-auth'], date_login: date_login }); @@ -160,7 +160,7 @@ if (testsingolo) { User.findById(users[0]._id).then((user) => { expect(user.tokens[0]).toInclude({ - access: 'auth ' + useragent, + access: 'auth', // token: res.headers['x-auth'], date_login: date_login }); diff --git a/server/tools/general.js b/server/tools/general.js index dfbfc64..232c91b 100644 --- a/server/tools/general.js +++ b/server/tools/general.js @@ -1,11 +1,25 @@ var os = require("os"); +require('../models/subscribers'); + +var Url = require('url-parse'); + +const mongoose = require('mongoose'); +const Subscription = mongoose.model('subscribers'); + // SETTINGS WebPush Configuration const webpush = require('web-push'); +const subject = process.env.URLBASE_APP1; //'mailto:' + process.env.EMAIL_FROM const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const privateVapidKey = process.env.PRIVATE_VAPI_KEY; -webpush.setVapidDetails('mailto:' + process.env.EMAIL_FROM, publicVapidKey, privateVapidKey); + +if (process.env.GCM_API_KEY !== "") + webpush.setGCMAPIKey(process.env.GCM_API_KEY); + +webpush.setVapidDetails(subject, publicVapidKey, privateVapidKey); +console.log('setVapidDetails... config...'); + module.exports = { getHostname: function () { @@ -45,8 +59,120 @@ module.exports = { console.log('sendBackNotif:', subscription, payload); // Pass object into sendNotification - webpush.sendNotification(subscription, JSON.stringify(payload)).catch(err => console.error(err)); + webpush.sendNotification(subscription, JSON.stringify(payload)).catch(err => console.error(err)) + .catch(err => { + if (err.statusCode === 410) { + // Gone: is not valid anymore (Expired probably!), so I have to delete from my db + return Subscription.findOneAndRemove( { _id:subscription._id } ) + } else { + console.log('Subscription is no longer valid: ', err); + } + }) + }, + + sendNotificationToUser: function (userId, title, content, openUrl, tag) { + + let payload = { + title: title, + message: content, + url: openUrl, + tag, + // ttl: req.body.ttl, + // icon: req.body.icon, + // image: req.body.image, + // badge: req.body.badge, + // tag: req.body.tag + }; + + return Subscription.find({ userId }, (err, subscriptions) => { + if (err) { + console.error(`Error occurred while getting subscriptions`); + res.status(500).json({ + error: 'Technical error occurred' + }); + return false; + } else { + let conta = 0 + let parallelSubscriptionCalls = subscriptions.map((subscription) => { + const trovati = subscriptions.length + return new Promise((resolve, reject) => { + const pushSubscription = { + endpoint: subscription.endpoint, + keys: { + p256dh: subscription.keys.p256dh, + auth: subscription.keys.auth + } + }; + + conta++; + + + const parse = require('url-parse'); + const parsedUrl = parse(subscription.endpoint); + const audience = parsedUrl.protocol + '//' + parsedUrl.hostname; + + const vapidHeaders = webpush.getVapidHeaders( + audience, + process.env.URLBASE_APP1, + process.env.PUBLIC_VAPI_KEY, + process.env.PRIVATE_VAPI_KEY, + 'aes128gcm' + ); + + const pushOptions = { + vapidDetails: { + subject: process.env.URLBASE_APP1, + privateKey: process.env.PRIVATE_VAPI_KEY, + publicKey: process.env.PUBLIC_VAPI_KEY, + }, + TTL: payload.ttl, + headers: vapidHeaders + }; + + console.log('************ INVIO WEBPUSH.SENDNOTIFICATION N° ', conta, '/', trovati, 'A', subscription.browser); + console.log('vapidDetails', pushOptions.vapidDetails); + + payload.title = process.env.URLBASE_APP1 + ' Msg n° ' + conta +'/' + trovati; + // payload.message += subscription.browser ; + + const pushPayload = JSON.stringify(payload); + + console.log('A1) SUBS: pushSubscription', pushSubscription); + console.log('A2) OPZIONI: pushOptions', pushOptions); + console.log('A3) MSG_TO_SEND: pushPayload', pushPayload); + + webpush.sendNotification( + pushSubscription, + pushPayload, + // pushOptions + ).then((value) => { + resolve({ + status: true, + endpoint: subscription.endpoint, + data: value + }); + }).catch((err) => { + reject({ + status: false, + endpoint: subscription.endpoint, + data: err + }); + }); + }).catch(error => { + console.log('ERROR: sendNotificationToUser', error) + }); + }); + // q.allSettled(parallelSubscriptionCalls).then((pushResults) => { + // console.info(pushResults); + // }); + // res.json({ + // data: 'Push triggered' + // }); + return true; + } + }); } + // Test };