Fix: Todo Multi refresh ...

fix some promises problem
This commit is contained in:
Paolo Arena
2019-02-14 19:01:41 +01:00
parent 0b4ac6391d
commit f6fa45a9e9
13 changed files with 191 additions and 121 deletions

View File

@@ -7,10 +7,11 @@ URLBASE_APP1=https://freeplanet.app
PORT_APP1="0" PORT_APP1="0"
DOMAIN=mongodb://localhost:27017/ DOMAIN=mongodb://localhost:27017/
SIGNCODE=abc123 SIGNCODE=abc123
EMAIL_FROM=perseo774.un@gmail.com EMAIL_FROM=perseo.774un@gmail.com
EMAIL_PW=passpao1UNOK EMAIL_PW=passpao1UNOK
DEBUG=0 DEBUG=0
PATH_CERT_KEY=/etc/letsencrypt/live/freeplanet.app/privkey.pem PATH_CERT_KEY=/etc/letsencrypt/live/freeplanet.app/privkey.pem
PATH_SERVER_CRT=/etc/letsencrypt/live/freeplanet.app/fullchain.pem PATH_SERVER_CRT=/etc/letsencrypt/live/freeplanet.app/fullchain.pem
PUBLIC_VAPI_KEY=BJGWIAlFXXQWqdBIEujrDJ7ZQeQmcwTOXr1kPfYy2ZCI6hvV9jhfquW2uHVoOiSYpoF6HeqnaydsIV5SeEpFbCk PUBLIC_VAPI_KEY="BNM-cEpTbPVc_ujXf3QOC8ggf7b-X44P44esfJUWqNOFq1XhWCoZJpOi71_cbXC5SnfO9HassQ6OouAYgtBA9Pw"
PRIVATE_VAPI_KEY=40Cn-P-j8iPs5RRR4VsH2lgmYSXqA5xK-nppK_HCbgA PRIVATE_VAPI_KEY="DtG3R-jzQiOSV8BJe6zSPUIIXoe5xcJ69U9o0wGLZxs"
GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8"

View File

@@ -34,6 +34,7 @@
"nodemailer": "^4.6.8", "nodemailer": "^4.6.8",
"preview-email": "0.0.8", "preview-email": "0.0.8",
"pug": "^2.0.3", "pug": "^2.0.3",
"url-parse": "^1.4.4",
"validator": "^5.6.0", "validator": "^5.6.0",
"web-push": "^3.3.3", "web-push": "^3.3.3",
"xoauth2": "^1.2.0" "xoauth2": "^1.2.0"

View File

@@ -15,6 +15,3 @@ require('dotenv').config({path: file});
process.env.DATABASE = process.env.DATABASE || 'FreePlanet'; process.env.DATABASE = process.env.DATABASE || 'FreePlanet';
process.env.MONGODB_URI = process.env.DOMAIN + process.env.DATABASE; 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);

View File

@@ -7,9 +7,7 @@ const tools = require('../tools/general');
var authenticate = (req, res, next) => { var authenticate = (req, res, next) => {
var token = req.header('x-auth'); var token = req.header('x-auth');
const useragent = req.get('User-Agent'); const access = 'auth';
const access = 'auth ' + useragent;
User.findByToken(token, access).then((user) => { User.findByToken(token, access).then((user) => {
if (!user) { if (!user) {

View File

@@ -17,6 +17,7 @@ const SubscriberSchema = new Schema({
keys: Schema.Types.Mixed, keys: Schema.Types.Mixed,
userId: String, userId: String,
access: String, access: String,
browser: String,
createDate: { createDate: {
type: Date, type: Date,
default: Date.now default: Date.now

View File

@@ -61,6 +61,10 @@ var UserSchema = new mongoose.Schema({
type: String, type: String,
required: true required: true
}, },
browser: {
type: String,
required: true
},
token: { token: {
type: String, type: String,
required: true required: true
@@ -92,13 +96,14 @@ UserSchema.methods.generateAuthToken = function (req) {
const useragent = req.get('User-Agent'); const useragent = req.get('User-Agent');
tools.mylog("GENERATE USER-AGENT = ", useragent); 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 token = jwt.sign({ _id: user._id.toHexString(), access }, process.env.SIGNCODE).toString();
var date_login = new Date(); var date_login = new Date();
// CANCELLA IL PRECEDENTE ! // CANCELLA IL PRECEDENTE !
user.tokens = user.tokens.filter(function(tok) { return tok.access !== access; }); user.tokens = user.tokens.filter(function(tok) { return (tok.access !== access) || ((tok.access === access) && (tok.browser !== browser) ) ; });
user.tokens.push({ access, token, date_login }); user.tokens.push({ access, browser, token, date_login });
return user.save() return user.save()
.then(() => { .then(() => {

View File

@@ -2,7 +2,6 @@ const express = require('express');
const router = express.Router(); const router = express.Router();
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers'); const Subscription = mongoose.model('subscribers');
const webpush = require('web-push');
const tools = require('../tools/general'); 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); console.log('req.body.others', req.body.others);
if (!isValidSaveRequest(req, res)) { if (!isValidSaveRequest(req, res)) {
@@ -37,9 +36,10 @@ router.post('/', (req, res) => {
let subscriptionModel = new Subscription(req.body.subs); let subscriptionModel = new Subscription(req.body.subs);
subscriptionModel.userId = req.body.others.userId; subscriptionModel.userId = req.body.others.userId;
subscriptionModel.access = req.body.others.access; subscriptionModel.access = req.body.others.access;
subscriptionModel.browser = req.get('User-Agent');
// Find if already exist // 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 => { .then(itemsub => {
return itemsub return itemsub
}) })
@@ -67,8 +67,10 @@ router.post('/', (req, res) => {
// res.status(201).json({ data: 'Subscription saved.' }); // res.status(201).json({ data: 'Subscription saved.' });
res.send({ data: 'Subscription saved.' }); res.send({ data: 'Subscription saved.' });
if (req.body.options !== null) {
tools.sendBackNotif(subscription, req.body.options) tools.sendBackNotif(subscription, req.body.options)
} }
}
}); });
}); });
@@ -78,7 +80,8 @@ router.post('/', (req, res) => {
router.delete('/del', authenticate, (req, res) => { router.delete('/del', authenticate, (req, res) => {
// tools.mylog("TOKENREM = " + req.token); // 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(200).send();
}, () => { }, () => {
res.status(400).send(); res.status(400).send();

View File

@@ -1,14 +1,6 @@
const express = require('express'); const express = require('express');
const router = express.Router(); 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'); const tools = require('../tools/general');
var server_constants = require('../tools/server_constants'); var server_constants = require('../tools/server_constants');
@@ -58,7 +50,7 @@ router.post('/', authenticate, (req, res) => {
.then(record => { .then(record => {
tools.mylog('REC SAVED :', record.descr); 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 => { .then(ris => {
if (ris) { if (ris) {
res.send({ record }); 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) => { router.patch('/:id', authenticate, (req, res) => {
var id = req.params.id; var id = req.params.id;

View File

@@ -18,8 +18,8 @@ var { authenticate } = require('../middleware/authenticate');
var mongoose = require('mongoose'); var mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers'); const Subscription = mongoose.model('subscribers');
function existSubScribe(userId, access) { function existSubScribe(userId, access, browser) {
return Subscription.findOne({ userId, access }) return Subscription.findOne({ userId, access, browser })
.then(itemsub => { .then(itemsub => {
return itemsub return itemsub
}) })
@@ -126,11 +126,11 @@ router.post('/login', (req, res) => {
}) })
.then((myris) => { .then((myris) => {
const useragent = req.get('User-Agent'); const access = 'auth';
const access = 'auth ' + useragent; const browser = req.get('User-Agent');
// Check if already exist Subscribe // 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) return (subscribe !== null)
}).then(subsExistonDb => { }).then(subsExistonDb => {
return { usertosend: myris.usertosend, token: myris.token, subsExistonDb } return { usertosend: myris.usertosend, token: myris.token, subsExistonDb }

View File

@@ -11,6 +11,7 @@ const express = require('express');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const path = require('path'); const path = require('path');
i18n = require("i18n"); i18n = require("i18n");
if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test')) { 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(); var app = express();
const tools = require('./tools/general');
// app.use(express.static(path.join(__dirname, 'client'))); // app.use(express.static(path.join(__dirname, 'client')));
app.use(bodyParser.json()); app.use(bodyParser.json());
@@ -66,7 +69,6 @@ app.use(bodyParser.json());
app.use(i18n.init); app.use(i18n.init);
// Use Routes // Use Routes
app.use('/', index_router); app.use('/', index_router);
app.use('/subscribe', subscribe_router); app.use('/subscribe', subscribe_router);
@@ -109,6 +111,27 @@ if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test')
httpServer.listen(port); 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, () => { //app.listen(port, () => {
// console.log(`Server started at port ${port}`); // console.log(`Server started at port ${port}`);
//}); //});

View File

@@ -38,8 +38,9 @@ const users = [{
username: 'paoloar77B', username: 'paoloar77B',
password: mypwdcrypted, password: mypwdcrypted,
tokens: [{ tokens: [{
access: 'auth ' + useragent, access: 'auth',
token: jwt.sign({ _id: userOneId, access: 'auth ' + useragent }, process.env.SIGNCODE).toString(), browser: useragent,
token: jwt.sign({ _id: userOneId, access: 'auth' }, process.env.SIGNCODE).toString(),
date_login date_login
}] }]
}, },
@@ -52,8 +53,9 @@ const users = [{
password: mypwdcrypted, password: mypwdcrypted,
username: 'paoloar77C', username: 'paoloar77C',
tokens: [{ tokens: [{
access: 'auth ' + useragent, access: 'auth',
token: jwt.sign({ _id: userTwoId, access: 'auth ' + useragent }, process.env.SIGNCODE).toString(), browser: useragent,
token: jwt.sign({ _id: userTwoId, access: 'auth' }, process.env.SIGNCODE).toString(),
date_login date_login
}] }]
}, { }, {

View File

@@ -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 = "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 useragent = "node-superagent/2.3.0";
const testsingolo = true; const testsingolo = false;
if (testsingolo) { if (testsingolo) {
describe('POST /users/login', () => { describe('POST /users/login', () => {
@@ -63,7 +63,7 @@ if (testsingolo) {
User.findById(users[0]._id).then((user) => { User.findById(users[0]._id).then((user) => {
expect(user.tokens[0]).toInclude({ expect(user.tokens[0]).toInclude({
access: 'auth ' + useragent, access: 'auth',
// token: res.headers['x-auth'], // token: res.headers['x-auth'],
date_login: date_login date_login: date_login
}); });
@@ -160,7 +160,7 @@ if (testsingolo) {
User.findById(users[0]._id).then((user) => { User.findById(users[0]._id).then((user) => {
expect(user.tokens[0]).toInclude({ expect(user.tokens[0]).toInclude({
access: 'auth ' + useragent, access: 'auth',
// token: res.headers['x-auth'], // token: res.headers['x-auth'],
date_login: date_login date_login: date_login
}); });

View File

@@ -1,11 +1,25 @@
var os = require("os"); var os = require("os");
require('../models/subscribers');
var Url = require('url-parse');
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');
// SETTINGS WebPush Configuration // SETTINGS WebPush Configuration
const webpush = require('web-push'); const webpush = require('web-push');
const subject = process.env.URLBASE_APP1; //'mailto:' + process.env.EMAIL_FROM
const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const publicVapidKey = process.env.PUBLIC_VAPI_KEY;
const privateVapidKey = process.env.PRIVATE_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 = { module.exports = {
getHostname: function () { getHostname: function () {
@@ -45,8 +59,120 @@ module.exports = {
console.log('sendBackNotif:', subscription, payload); console.log('sendBackNotif:', subscription, payload);
// Pass object into sendNotification // 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
}; };