From 267175a8aa4ba49341ad69eedf5fc0173e162fc3 Mon Sep 17 00:00:00 2001 From: ebelcrom Date: Sun, 9 Feb 2020 19:48:17 +0100 Subject: [PATCH] first working version --- app.js | 12 +-- lib/{dblib.js => db.js} | 0 lib/gpio.js | 118 +++++++++++++++++++++++ package-lock.json | 43 ++++++++- package.json | 2 + routes/v1/control.js | 81 +++++++++++++++- routes/v1/events.js | 123 ++++++++++++++++++++++-- routes/v1/notification.js | 171 ++++++++++++++++++++++++++++++++- routes/v1/status.js | 85 +++++++++++++++- routes/v1/test/control.js | 8 +- routes/v1/test/events.js | 2 +- routes/v1/test/notification.js | 12 +-- routes/v1/test/settings.js | 45 +++++---- routes/v1/test/status.js | 10 +- 14 files changed, 645 insertions(+), 67 deletions(-) rename lib/{dblib.js => db.js} (100%) create mode 100644 lib/gpio.js diff --git a/app.js b/app.js index 22038bf..38455b2 100644 --- a/app.js +++ b/app.js @@ -11,7 +11,7 @@ const indexRouter = require('./routes/index'); // routes const prodStatus = require('./routes/' + ver + '/status'); -const prodEvents = require('./routes/' + ver + '/events'); +const prodEvents = require('./routes/' + ver + '/events').router; const prodControl = require('./routes/' + ver + '/control'); const prodNotification = require('./routes/' + ver + '/notification'); const testStatus = require('./routes/' + ver + '/test/status'); @@ -65,14 +65,4 @@ app.use('/' + ver + '/test/settings', testSettings); // api-docs app.use('/' + ver + '/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); -/* -app.use((err, req, res, next) => { -log.error(err); - res.status(err.status).json({ - message: err.message, - errors: err.errors, - }); -}); -*/ - module.exports = app; diff --git a/lib/dblib.js b/lib/db.js similarity index 100% rename from lib/dblib.js rename to lib/db.js diff --git a/lib/gpio.js b/lib/gpio.js new file mode 100644 index 0000000..ebb3cfd --- /dev/null +++ b/lib/gpio.js @@ -0,0 +1,118 @@ +const rpio = require('rpio'); +const log = require('./logger')(__filename.slice(__dirname.length + 1)); + +const RELAIS = 16; // GPIO 23 +const REED = 11; // GPIO 17 +const UNKNOWN = 2; +const DELAY = 10; +var reedState; +var controlCallback = null; +var notificationCallback = null; +var apiKey = null; +var timer = null; + +function init() { + rpio.open(RELAIS, rpio.OUTPUT); + rpio.write(RELAIS, rpio.LOW); + rpio.open(REED, rpio.INPUT); + + reedState = readDebounced(REED); +} + +init(); + +function trigger() { + rpio.write(RELAIS, rpio.HIGH); + rpio.msleep(500); + rpio.write(RELAIS, rpio.LOW); + + log.debug('relais triggered'); +} + +function readDebounced(pin) { + const state = rpio.read(pin); + + rpio.msleep(1000); + + if (state != rpio.read(pin)) { + log.debug('state unknown'); + return UNKNOWN; + } else { + log.debug('state :', state); + return state; + } +} + +function pollcb(pin) +{ + const state = readDebounced(pin); + + if (state != UNKNOWN && reedState != UNKNOWN) { + if (state != reedState) { + log.debug('reed state changed, now:', state); + + if (controlCallback != null) { + // handle callbacks + if (state == rpio.LOW) { + controlCallback('closed'); + controlCallback = null; + } else { + controlCallback('open'); + controlCallback = null; + } + } + + // evaluate state + evaluation(state); + } + reedState = state; + } +} + +rpio.poll(REED, pollcb); + +function register(callback) { + controlCallback = callback; +} + +function read() { + const state = readDebounced(REED); + + switch (state) { + case rpio.LOW: + return 'closed' + break; + case rpio.HIGH: + return 'open' + break; + case rpio.LOW: + default: + return 'unknown' + break; + } +} + +function subscribe(callback, key) { + notificationCallback = callback; + apiKey = key; +} + +function evaluation(state) { + if (notificationCallback != null) { + if (state == rpio.HIGH) { + timer = setTimeout(notificationCallback, DELAY * 1000, apiKey); + log.debug('Open door evaluation started'); + } else { + clearTimeout(timer); + timer = null; + log.debug('Open door evaluation stopped'); + } + } +} + +module.exports = { + trigger, + register, + read, + subscribe, +} diff --git a/package-lock.json b/package-lock.json index 78be1d5..3a4ead9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "garnod", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -73,6 +73,14 @@ "safe-buffer": "5.1.2" } }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", @@ -252,6 +260,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -440,6 +457,11 @@ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", @@ -788,6 +810,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -804,6 +831,11 @@ "validate-npm-package-license": "^3.0.1" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1004,6 +1036,15 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, + "rpio": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/rpio/-/rpio-2.1.1.tgz", + "integrity": "sha512-0Pluzy3s77JXxpUVE3zs25TAYIjYb3q1yOJVkK6taH/idzDohZH6whqp5owgYeawxs767nc8y9TdbAv0Q1xL7w==", + "requires": { + "bindings": "~1.5.0", + "nan": "~2.14.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", diff --git a/package.json b/package.json index 56ab0b7..3198139 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,14 @@ "license": "GPL-2.0-or-later", "dependencies": { "cookie-parser": "~1.4.4", + "cors": "^2.8.5", "dateformat": "1.0.11", "debug": "~2.6.9", "express": "~4.16.1", "mongodb": "^2.2.36", "morgan": "~1.9.1", "query-string": "^6.8.3", + "rpio": "^2.1.1", "swagger-ui-express": "^4.1.2", "web-push": "^3.4.1", "winston": "1.1.2", diff --git a/routes/v1/control.js b/routes/v1/control.js index 8cc3399..8b5285d 100644 --- a/routes/v1/control.js +++ b/routes/v1/control.js @@ -1,9 +1,80 @@ -var express = require('express'); -var router = express.Router(); +const express = require('express'); +const log = require('./../../lib/logger')(__filename.slice(__dirname.length + 1)); +const qStr = require('query-string'); +const router = express.Router(); +const db = require('./../../lib/db'); +const ev = require('./events'); +const gpio = require('./../../lib/gpio'); -/* GET */ -router.get('/', function(req, res, next) { - res.status(500).send; +const events = ev.events; +var timer = null; + +/* Disables caching in client */ +function nocache(req, res, next) { + res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); + res.header('Expires', '-1'); + res.header('Pragma', 'no-cache'); + next(); +} + +/* POST /vN/control */ +router.post('/', nocache, function(req, res, next) { + // check header + if (typeof req.header('X-API-Key') === 'undefined') { + log.info('API key not set in request header'); + res.status(401).send(); + return; + } else { + log.debug('API key set in request header'); + } + + // check query parameter + if (typeof req.query.command != 'undefined') { + if (typeof req.query.command == 'string') { + switch (req.query.command) { + case 'move': + break; + default: + log.info('Value of command query parameter unknown'); + res.status(400).send(); + return; + } + } + } + + // read settings + db.getSettings({ + area: 'prod', + key: req.header('X-API-Key') + }, (err, data) => { + if (err) { + switch (err) { + case db.msg.dbError: + log.info('Server error response'); + res.status(500).send(); + break; + case db.msg.keyMismatch: + log.info('Unauthorized access'); + res.status(401).send(); + break; + default: + log.error('Error result unexpected'); + res.status(500).send(); + break; + } + } else { + // register callback + gpio.register(onStateChanged); + gpio.trigger(); + log.debug('Door closing triggered and state change event subscribed'); + // send response + res.status(200).send(); + } + }); }); +function onStateChanged(state) { + events.emit('stateChanged', state); +} + module.exports = router; diff --git a/routes/v1/events.js b/routes/v1/events.js index 8cc3399..cfcd85d 100644 --- a/routes/v1/events.js +++ b/routes/v1/events.js @@ -1,9 +1,120 @@ -var express = require('express'); -var router = express.Router(); +const express = require('express'); +const log = require('./../../lib/logger')(__filename.slice(__dirname.length + 1)); +const qStr = require('query-string'); +const router = express.Router(); +const db = require('./../../lib/db'); +const EventEmitter = require('events'); +const fs = require('fs'); -/* GET */ -router.get('/', function(req, res, next) { - res.status(500).send; +const events = new EventEmitter(); +var response = null; +var request = null; +var timer = null; +const delayMin = -1; +const delayMax = 300; + +function nocache(req, res, next) { + res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); + res.header('Expires', '-1'); + res.header('Pragma', 'no-cache'); + next(); +} + +/* GET /vN/events */ +router.get('/', nocache, function(req, res, next) { + // check header + if (typeof req.header('X-API-Key') === 'undefined') { + log.info('API key not set in request header'); + res.status(401).send(); + return; + } else { + log.debug('API key set in request header'); + } + + // TODO: dequeue? + + // check query parameter + var timeout = 30; + if (typeof req.query.timeout != 'undefined') { + var delay = parseInt(req.query.timeout); + if (!isNaN(delay)) { + if (delay < delayMin || delay > delayMax) { + log.info('Value of timeout query parameter not in range'); + res.status(400).send(); + return; + } else { + timeout = delay; + } + } + } + + // schedule resonse on timeout + response = res; + request = req; + if (timer === null && timeout !== delayMin) { + timer = setTimeout(processTimeout, timeout * 1000); + log.debug('Response timeout scheduled'); + } else { + log.todo('not implemented'); + } }); -module.exports = router; +events.on('stateChanged', (state) => { + log.debug('Event ready for sending'); + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + + // read settings + log.debug('Got state:', state); + var image = true; + if (request !== null) { + if (typeof request.query.image != 'undefined') { + if (request.query.image === 'false') { + image = false; + } + } + request = null; + } + + // TODO: enqueue? + + // response + if (response !== null) { + var content = { + 'state': state + }; + if (image) { + var file = null; + switch (state) { + case 'open': + file = fs.readFileSync(__dirname + '/../../public/images/open.jpg', 'base64'); + break; + case 'closed': + file = fs.readFileSync(__dirname + '/../../public/images/closed.jpg', 'base64'); + break; + default: + log.error('Unexpected status from state'); + response.status(500).send(); + return; + } + content['image'] = file; + } + response.json(content); + response = null; + } +}); + +function processTimeout() { + log.debug('Timeout, no events'); + clearTimeout(timer); + timer = null; + response.status(304).end(''); + response = null; +} + +module.exports = { + router, + events +} diff --git a/routes/v1/notification.js b/routes/v1/notification.js index 8cc3399..cf2c699 100644 --- a/routes/v1/notification.js +++ b/routes/v1/notification.js @@ -1,9 +1,170 @@ -var express = require('express'); -var router = express.Router(); +const express = require('express'); +const log = require('./../../lib/logger')(__filename.slice(__dirname.length + 1)); +const qStr = require('query-string'); +const router = express.Router(); +const db = require('./../../lib/db'); +const gpio = require('./../../lib/gpio'); +const fs = require('fs'); +const webpush = require('web-push'); -/* GET */ -router.get('/', function(req, res, next) { - res.status(500).send; +/* Disables caching in client */ +function nocache(req, res, next) { + res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); + res.header('Expires', '-1'); + res.header('Pragma', 'no-cache'); + next(); +} + +/* POST /vN/notification */ +router.post('/', nocache, function(req, res, next) { + // check header + if (typeof req.header('X-API-Key') === 'undefined') { + log.info('API key not set in request header'); + res.status(401).send(); + return; + } else { + log.debug('API key set in request header'); + } + + // check body + if (typeof req.body != 'object') { + log.info('Request body is not JSON'); + res.status(400).send(); + return; + } else{ + // check endpoint + if (typeof req.body.endpoint != 'string' ) { + log.info('Type of endpoint in content invalid'); + res.status(400).send(); + return; + } + + // check expirationTime + if (req.body.expirationTime !== null) { + if (typeof req.body.expirationTime != 'string' ) { + log.info('Type of expirationTime in content invalid'); + res.status(400).send(); + return; + } + } + + // check keys + if (typeof req.body.keys == 'object' ) { + if (typeof req.body.keys.p256dh != 'string' ) { + log.info('Type of keys.p256dh in content invalid'); + res.status(400).send(); + return; + } + if (typeof req.body.keys.auth != 'string' ) { + log.info('Type of keys.auth in content invalid'); + res.status(400).send(); + return; + } + } + + // save to DB + db.setNotification({ + area: 'prod', + key: req.header('X-API-Key'), + notification: req.body + }, (err, data) => { + if (err) { + switch (err) { + case db.msg.dbError: + log.info('Server error response'); + res.status(500).send(); + break; + case db.msg.keyMismatch: + log.info('Unauthorized access'); + res.status(401).send(); + break; + default: + log.error('Error result unexpected'); + res.status(500).send(); + break; + } + } else { + // subscribe notification + gpio.subscribe(onDoorOpen, req.header('X-API-Key')); + log.debug('Open door event subscribed'); + res.status(200).send(); + } + }); + } }); +function onDoorOpen(key) { + // get settings + db.getNotification({ + area: 'prod', + key: key + }, (err, data) => { + if (err) { + switch (err) { + case db.msg.dbError: + log.info('Server error response'); + res.status(500).send(); + break; + case db.msg.keyMismatch: + log.info('Unauthorized access'); + res.status(401).send(); + break; + default: + log.error('Error result unexpected'); + res.status(500).send(); + break; + } + } else { + executeNotification(data); + } + }); +} + +function executeNotification(notification) { + const pushSubscription = { + endpoint: notification.endpoint, + keys: { + auth: notification.keys.auth, + p256dh: notification.keys.p256dh + } + }; + + const options = { + gcmAPIKey: 'AAAAUtHuYco:APA91bEBTxCRGaez9_glljXAlit3PY5HMwhLSqWYMC1j-jFSp6' + + 'nvnNqjI42jAVFApQbM0oyAOQjCUilIovB76cwTFxyZTP96wm9n09XwiMRXJjhwiJX1hO3' + + '2mBB2zwK6X-w7epE1V67K', + vapidDetails: { + subject: 'mailto:ebelcrom@gmail.com', + publicKey: 'BLDSdGasI5sLks30brbIWvlLMFqzoxxkOs7aW_E9PDBzIO_mDs6-tvtb2U0-' + + 'BVFDafNd58DJgoXxdK5711FF29c', + privateKey: '_AFTIegzYV_l_5RYwzOCc22cpYcMUmpkA8bLbrlNq9I' + }, + headers: { + 'Urgency': 'high' + }, + contentEncoding: 'aes128gcm' + }; + + const icon = 'data:image/png;base64,' + + fs.readFileSync(__dirname + '/../../public/images/icon.png', 'base64'); + const payload = { + message: 'The garage door is open!', + icon: icon + }; + log.debug('Paylod length:', JSON.stringify(payload).length); + + const details = webpush.generateRequestDetails(pushSubscription, JSON.stringify(payload), options); + log.debug('Request details:', JSON.stringify(details)); + + webpush.sendNotification(pushSubscription, JSON.stringify(payload), options) + .then(data => { + if (data) { + log.info('sent, data:', JSON.stringify(data)); + } + }) + .catch(err => { + log.info('sent, err:', JSON.stringify(err)); + }); +} + module.exports = router; diff --git a/routes/v1/status.js b/routes/v1/status.js index 8cc3399..d132241 100644 --- a/routes/v1/status.js +++ b/routes/v1/status.js @@ -1,9 +1,84 @@ -var express = require('express'); -var router = express.Router(); +const express = require('express'); +const log = require('./../../lib/logger')(__filename.slice(__dirname.length + 1)); +const qStr = require('query-string'); +const router = express.Router(); +const db = require('./../../lib/db'); +const fs = require('fs'); +const gpio = require('./../../lib/gpio'); -/* GET */ -router.get('/', function(req, res, next) { - res.status(500).send; +/* Disables caching in client */ +function nocache(req, res, next) { + res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); + res.header('Expires', '-1'); + res.header('Pragma', 'no-cache'); + next(); +} + +/* GET /vN/status */ +router.get('/', nocache, function(req, res, next) { + // check header + if (typeof req.header('X-API-Key') === 'undefined') { + log.info('API key not set in request header'); + res.status(401).send(); + return; + } else { + log.debug('API key set in request header'); + } + + // check query parameter + var image = true; + if (typeof req.query.image != 'undefined') { + if (req.query.image === 'false') { + image = false; + } + } + + // read settings + db.getSettings({ + area: 'prod', + key: req.header('X-API-Key') + }, (err, data) => { + if (err) { + switch (err) { + case db.msg.dbError: + log.info('Server error response'); + res.status(500).send(); + break; + case db.msg.keyMismatch: + log.info('Unauthorized access'); + res.status(401).send(); + break; + default: + log.error('Error result unexpected'); + res.status(500).send(); + break; + } + } else { + // response + const state = gpio.read(); + + var content = { + 'state': state + }; + if (image) { + var file = null; + switch (state) { + case 'open': + file = fs.readFileSync(__dirname + '/../../public/images/open.jpg', 'base64'); + break; + case 'closed': + file = fs.readFileSync(__dirname + '/../../public/images/closed.jpg', 'base64'); + break; + default: + log.error('Unexpected status from settings'); + res.status(500).send(); + return; + } + content['image'] = file; + } + res.json(content); + } + }); }); module.exports = router; diff --git a/routes/v1/test/control.js b/routes/v1/test/control.js index ec700d7..4b89e6a 100644 --- a/routes/v1/test/control.js +++ b/routes/v1/test/control.js @@ -2,7 +2,7 @@ const express = require('express'); const log = require('./../../../lib/logger')(__filename.slice(__dirname.length + 1)); const qStr = require('query-string'); const router = express.Router(); -const dblib = require('./../../../lib/dblib'); +const db = require('./../../../lib/db'); const ev = require('./events'); const events = ev.events; @@ -49,17 +49,17 @@ router.post('/', nocache, function(req, res, next) { function move(req, res, next) { // get settings - dblib.getSettings({ + db.getSettings({ area: 'test', key: req.header('X-API-Key-Test') }, (err, data) => { if (err) { switch (err) { - case dblib.msg.dbError: + case db.msg.dbError: log.info('Server error response'); res.status(500).send(); break; - case dblib.msg.keyMismatch: + case db.msg.keyMismatch: log.info('Unauthorized access'); res.status(401).send(); break; diff --git a/routes/v1/test/events.js b/routes/v1/test/events.js index bd31a75..45362e5 100644 --- a/routes/v1/test/events.js +++ b/routes/v1/test/events.js @@ -2,7 +2,7 @@ const express = require('express'); const log = require('./../../../lib/logger')(__filename.slice(__dirname.length + 1)); const qStr = require('query-string'); const router = express.Router(); -const dblib = require('./../../../lib/dblib'); +const db = require('./../../../lib/db'); const EventEmitter = require('events'); const fs = require('fs'); diff --git a/routes/v1/test/notification.js b/routes/v1/test/notification.js index c2db2e0..8295a96 100644 --- a/routes/v1/test/notification.js +++ b/routes/v1/test/notification.js @@ -2,9 +2,9 @@ const express = require('express'); const log = require('./../../../lib/logger')(__filename.slice(__dirname.length + 1)); const qStr = require('query-string'); const router = express.Router(); -const dblib = require('./../../../lib/dblib'); +const db = require('./../../../lib/db'); -/* Disables caching in client */ +/* Disables caching in client */ function nocache(req, res, next) { res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); res.header('Expires', '-1'); @@ -12,7 +12,7 @@ function nocache(req, res, next) { next(); } -/* POST /vN/test/notification */ +/* POST /vN/notification */ router.post('/', nocache, function(req, res, next) { // check header if (typeof req.header('X-API-Key-Test') === 'undefined') { @@ -60,18 +60,18 @@ router.post('/', nocache, function(req, res, next) { } // save to DB - dblib.setNotification({ + db.setNotification({ area: 'test', key: req.header('X-API-Key-Test'), notification: req.body }, (err, data) => { if (err) { switch (err) { - case dblib.msg.dbError: + case db.msg.dbError: log.info('Server error response'); res.status(500).send(); break; - case dblib.msg.keyMismatch: + case db.msg.keyMismatch: log.info('Unauthorized access'); res.status(401).send(); break; diff --git a/routes/v1/test/settings.js b/routes/v1/test/settings.js index 423c1f6..27e3f13 100644 --- a/routes/v1/test/settings.js +++ b/routes/v1/test/settings.js @@ -2,7 +2,7 @@ const express = require('express'); const log = require('./../../../lib/logger')(__filename.slice(__dirname.length + 1)); const qStr = require('query-string'); const router = express.Router(); -const dblib = require('./../../../lib/dblib'); +const db = require('./../../../lib/db'); const fs = require('fs'); const webpush = require('web-push'); @@ -129,18 +129,18 @@ router.post('/', function(req, res, next) { } // save to DB - dblib.setSettings({ + db.setSettings({ area: 'test', key: req.header('X-API-Key-Test'), settings: settings }, (err, data) => { if (err) { switch (err) { - case dblib.msg.dbError: + case db.msg.dbError: log.info('Server error response'); res.status(500).send(); break; - case dblib.msg.keyMismatch: + case db.msg.keyMismatch: log.info('Unauthorized access'); res.status(401).send(); break; @@ -166,17 +166,17 @@ router.post('/', function(req, res, next) { function notify(req, res, next, delay) { // get settings - dblib.getNotification({ + db.getNotification({ area: 'test', key: req.header('X-API-Key-Test') }, (err, data) => { if (err) { switch (err) { - case dblib.msg.dbError: + case db.msg.dbError: log.info('Server error response'); res.status(500).send(); break; - case dblib.msg.keyMismatch: + case db.msg.keyMismatch: log.info('Unauthorized access'); res.status(401).send(); break; @@ -206,16 +206,6 @@ function executeNotification(notification) { clearTimeout(timer); timer = null; - // web push - webpush.setGCMAPIKey('AAAAUtHuYco:APA91bEBTxCRGaez9_glljXAlit3PY5HMwhLSqWYMC1j-jFSp6nvnNqj' + - 'I42jAVFApQbM0oyAOQjCUilIovB76cwTFxyZTP96wm9n09XwiMRXJjhwiJX1hO32mBB2zwK6X-w7epE1V67K'); - webpush.setVapidDetails( - 'mailto:ebelcrom@gmail.com', - 'BLDSdGasI5sLks30brbIWvlLMFqzoxxkOs7aW_E9PDBzIO_mDs6-tvtb2U0-BVFDafNd58DJgoXxdK5711FF29c', - '_AFTIegzYV_l_5RYwzOCc22cpYcMUmpkA8bLbrlNq9I' - ); - - log.debug('Notification data:', JSON.stringify(notification)) const pushSubscription = { endpoint: notification.endpoint, keys: { @@ -224,6 +214,22 @@ function executeNotification(notification) { } }; + const options = { + gcmAPIKey: 'AAAAUtHuYco:APA91bEBTxCRGaez9_glljXAlit3PY5HMwhLSqWYMC1j-jFSp6' + + 'nvnNqjI42jAVFApQbM0oyAOQjCUilIovB76cwTFxyZTP96wm9n09XwiMRXJjhwiJX1hO3' + + '2mBB2zwK6X-w7epE1V67K', + vapidDetails: { + subject: 'mailto:ebelcrom@gmail.com', + publicKey: 'BLDSdGasI5sLks30brbIWvlLMFqzoxxkOs7aW_E9PDBzIO_mDs6-tvtb2U0-' + + 'BVFDafNd58DJgoXxdK5711FF29c', + privateKey: '_AFTIegzYV_l_5RYwzOCc22cpYcMUmpkA8bLbrlNq9I' + }, + headers: { + 'Urgency': 'high' + }, + contentEncoding: 'aes128gcm' + }; + const icon = 'data:image/png;base64,' + fs.readFileSync(__dirname + '/../../../public/images/icon.png', 'base64'); const payload = { @@ -232,7 +238,10 @@ function executeNotification(notification) { }; log.debug('Paylod length:', JSON.stringify(payload).length); - webpush.sendNotification(pushSubscription, JSON.stringify(payload)) + const details = webpush.generateRequestDetails(pushSubscription, JSON.stringify(payload), options); + log.debug('Request details:', JSON.stringify(details)); + + webpush.sendNotification(pushSubscription, JSON.stringify(payload), options) .then(data => { if (data) { log.info('sent, data:', JSON.stringify(data)); diff --git a/routes/v1/test/status.js b/routes/v1/test/status.js index 3edfb91..a4b71ed 100644 --- a/routes/v1/test/status.js +++ b/routes/v1/test/status.js @@ -2,10 +2,10 @@ const express = require('express'); const log = require('./../../../lib/logger')(__filename.slice(__dirname.length + 1)); const qStr = require('query-string'); const router = express.Router(); -const dblib = require('./../../../lib/dblib'); +const db = require('./../../../lib/db'); const fs = require('fs'); -/* Disables caching in client */ +/* Disables caching in client */ function nocache(req, res, next) { res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); res.header('Expires', '-1'); @@ -33,17 +33,17 @@ router.get('/', nocache, function(req, res, next) { } // read settings - dblib.getSettings({ + db.getSettings({ area: 'test', key: req.header('X-API-Key-Test') }, (err, data) => { if (err) { switch (err) { - case dblib.msg.dbError: + case db.msg.dbError: log.info('Server error response'); res.status(500).send(); break; - case dblib.msg.keyMismatch: + case db.msg.keyMismatch: log.info('Unauthorized access'); res.status(401).send(); break; -- 2.30.2