Promisifying and error handling
Ryan Blenis committed
Nov 5, 2019 at 00:11 UTC
ed701dff392857f374186fd1d0b4cd8e197f16c7
4 files changed
+104
-55
meshuser.js
+16
-2
@@ -3122,14 +3122,28 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3122
}
3123
case 'pluginLatestCheck': {
3124
if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin with plugins enabled
3125
- parent.parent.pluginHandler.getPluginLatest(function(latest) {
3125
+ parent.parent.pluginHandler.getPluginLatest()
3126
+ .then(function(latest) {
3127
try { ws.send(JSON.stringify({ action: 'pluginVersionsAvailable', list: latest })); } catch (ex) { }
3128
});
3129
break;
3130
}
3131
case 'addplugin': {
3132
if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
3132
- parent.parent.pluginHandler.addPlugin(command.url);
3133
+ try {
3134
+ //parent.parent.pluginHandler.addPlugin(command.url)
3135
+ parent.parent.pluginHandler.getPluginConfig(command.url)
3136
+ .then(parent.parent.pluginHandler.addPlugin)
3137
+ .then(function(docs){ console.log('landed');
3138
+ var targets = ['*', 'server-users'];
3139
+ parent.parent.DispatchEvent(targets, obj, { action: 'updatePluginList', list: docs });
3140
+ })
3141
+ .catch(function(err) {
3142
+ if (typeof err == 'object') err = err.message;
3143
+ try { ws.send(JSON.stringify({ action: 'pluginError', msg: err })); } catch (er) { }
3144
+ });
3145
+
3146
+ } catch(e) { console.log('Cannot add plugin: ' + e); }
3147
break;
3148
}
3149
case 'installplugin': {
pluginHandler.js
+68
-50
@@ -13,6 +13,7 @@
13
/*jshint strict: false */
14
/*jshint esversion: 6 */
15
"use strict";
16
+require('promise');
17
18
module.exports.pluginHandler = function (parent) {
19
var obj = {};
@@ -214,54 +215,72 @@ module.exports.pluginHandler = function (parent) {
215
return plugins;
216
}
217
217
- obj.getPluginConfig = function(configUrl, func) {
218
- var https = require('https');
219
- if (configUrl.indexOf('://') === -1) return; // @TODO error here
220
- https.get(configUrl, function(res) {
221
- var configStr = '';
222
- res.on('data', function(chunk){
223
- configStr += chunk;
224
- });
225
- res.on('end', function(){
226
- if (configStr[0] == '{') { // let's be sure we're JSON
227
- try {
228
- var pluginConfig = JSON.parse(configStr);
229
- if (Array.isArray(pluginConfig) && pluginConfig.length == 1) pluginConfig = pluginConfig[0];
230
- if (obj.isValidConfig(pluginConfig, configUrl)) {
231
- func(pluginConfig);
232
- }
233
-
234
- } catch (e) { console.log('Error getting plugin config. Check that you have valid JSON.', e.stack); }
235
- }
236
- });
237
-
238
- }).on('error', function(e) {
239
- console.log("Error getting plugin config. Check that the URL is correct.: " + e.message);
240
- });
218
+ obj.getPluginConfig = function(configUrl) {
219
+ return new Promise(function(resolve, reject) {
220
+ var https = require('https');
221
+ if (configUrl.indexOf('://') === -1) reject('Unable to fetch the config: Bad URL (' + configUrl + ')');
222
+ https.get(configUrl, function(res) {
223
+ var configStr = '';
224
+ res.on('data', function(chunk){
225
+ configStr += chunk;
226
+ });
227
+ res.on('end', function(){
228
+ if (configStr[0] == '{') { // let's be sure we're JSON
229
+ try {
230
+ var pluginConfig = JSON.parse(configStr);
231
+ if (Array.isArray(pluginConfig) && pluginConfig.length == 1) pluginConfig = pluginConfig[0];
232
+ if (obj.isValidConfig(pluginConfig, configUrl)) {
233
+ resolve(pluginConfig);
234
+ } else {
235
+ reject("This does not appear to be a valid plugin configuration.");
236
+ }
237
+
238
+ } catch (e) { reject('Error getting plugin config. Check that you have valid JSON.'); }
239
+ } else {
240
+ reject('Error getting plugin config. Check that you have valid JSON.');
241
+ }
242
+ });
243
+
244
+ }).on('error', function(e) {
245
+ reject("Error getting plugin config: " + e.message);
246
+ });
247
+ })
248
};
249
243
- obj.getPluginLatest = function(func) {
244
- parent.db.getPlugins(function(err, plugins){
245
- plugins.forEach(function(curconf){
246
- obj.getPluginConfig(curconf.configUrl, function(newconf){
247
- var s = require('semver');
248
- func({
249
- "id": curconf._id,
250
- "installedVersion": curconf.version,
251
- "version": newconf.version,
252
- "hasUpdate": s.gt(newconf.version, curconf.version),
253
- "meshCentralCompat": s.satisfies(s.coerce(parent.currentVer), newconf.meshCentralCompat),
254
- "changelogUrl": curconf.changelogUrl,
255
- "status": curconf.status
256
- });
257
- });
258
- });
250
+ obj.getPluginLatest = function() {
251
+ return new Promise(function(resolve, reject) {
252
+ parent.db.getPlugins(function(err, plugins) {
253
+ var proms = [];
254
+ plugins.forEach(function(curconf) {
255
+ proms.push(obj.getPluginConfig(curconf.configUrl));
256
+ });
257
+ var latestRet = [];
258
+ Promise.all(proms).then(function(newconfs) {
259
+ newconfs.forEach(function(newconf) {
260
+ var curconf = null;
261
+ plugins.forEach(function(conf) {
262
+ if (conf.configUrl == newconf.configUrl) curconf = conf;
263
+ });
264
+ if (curconf == null) reject('Some plugin configs could not be parsed');
265
+ var s = require('semver');
266
+ latestRet.push({
267
+ "id": curconf._id,
268
+ "installedVersion": curconf.version,
269
+ "version": newconf.version,
270
+ "hasUpdate": s.gt(newconf.version, curconf.version),
271
+ "meshCentralCompat": s.satisfies(s.coerce(parent.currentVer), newconf.meshCentralCompat),
272
+ "changelogUrl": curconf.changelogUrl,
273
+ "status": curconf.status
274
+ });
275
+ resolve(latestRet);
276
+ });
277
+ }).catch((e) => { console.log('Error reaching plugins, update call aborted. ', e)});
278
+ });
279
});
260
-
280
};
281
263
- obj.addPlugin = function(url) {
264
- obj.getPluginConfig(url, function(pluginConfig){
282
+ obj.addPlugin = function(pluginConfig) {
283
+ return new Promise(function(resolve, reject) {
284
parent.db.addPlugin({
285
"name": pluginConfig.name,
286
"shortName": pluginConfig.shortName,
@@ -279,13 +298,12 @@ module.exports.pluginHandler = function (parent) {
298
"meshCentralCompat": pluginConfig.meshCentralCompat,
299
"status": 0 // 0: disabled, 1: enabled
300
}, function() {
282
- parent.db.getPlugins(function(err, docs){
283
- var targets = ['*', 'server-users'];
284
- parent.DispatchEvent(targets, obj, { action: 'updatePluginList', list: docs });
285
-
286
- });
287
- });
288
- });
301
+ parent.db.getPlugins(function(err, docs){
302
+ if (err) reject(err);
303
+ else resolve(docs);
304
+ });
305
+ });
306
+ });
307
};
308
309
obj.installPlugin = function(id, func) {
public/styles/style.css
+7
@@ -2653,6 +2653,13 @@ a {
2653
position: absolute;
2654
cursor: pointer; /* Add a pointer on hover */
2655
}
2656
+.pluginOverlayContent {
2657
+ width: 100%; /* Full width (cover the whole page) */
2658
+ height: 100%; /* Full height (cover the whole page) */
2659
+ background-color: #FFFFFF; /* Black background with opacity */
2660
+ z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
2661
+ position: relative;
2662
+}
2663
2664
.pluginTitleBar {
2665
padding: 4px;
views/default.handlebars
+13
-3
@@ -2368,6 +2368,10 @@
2368
updatePluginList(message.list);
2369
break;
2370
}
2371
+ case 'pluginError': {
2372
+ setDialogMode(2, 'Oops!', 1, null, message.msg);
2373
+ break;
2374
+ }
2375
case 'plugin': {
2376
if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
2377
try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
@@ -9419,6 +9423,9 @@
9423
}
9424
9425
function updatePluginList(versInfo) {
9426
+ if (Array.isArray(versInfo)) {
9427
+ versInfo.forEach(function(v) { updatePluginList(v); });
9428
+ }
9429
if (installedPluginList.length) {
9430
if (versInfo != null) {
9431
if (installedPluginList['version_info'] == null) installedPluginList['version_info'] = [];
@@ -9479,6 +9486,7 @@
9486
if (!vin.meshCentralCompat) {
9487
p.upgradeAvail += vers_not_compat;
9488
cant_action.push('install');
9489
+ cant_action.push('upgrade');
9490
}
9491
}
9492
@@ -9533,8 +9541,9 @@
9541
}
9542
9543
function goPlugin(pname, title) {
9536
- let xwin = `<div class="pluginTitleBar"><span>${title}</span><span class="pluginCloseBtn"><button onclick="return noGoPlugin(this);">X</button></span></div>`
9544
+ let xwin = `<div class="pluginTitleBar"><span>${title}</span><span class="pluginCloseBtn"><button onclick="return noGoPlugin(this);">X</button></span></div>`;
9545
let dif = document.createElement('div');
9546
+ let cdif = document.createElement('div');
9547
dif.classList.add('pluginOverlay');
9548
dif.innerHTML = xwin;
9549
let pif = document.createElement('iframe');
@@ -9543,8 +9552,9 @@
9552
pif.style.width = '100%';
9553
pif.style.height = '100%';
9554
pif.setAttribute('frameBorder', '0');
9546
-
9547
- dif.append(pif);
9555
+ cdif.classList.add('pluginOverlayContent');
9556
+ cdif.append(pif);
9557
+ dif.append(cdif);
9558
let x = Q('p7');
9559
x.parentNode.insertBefore(dif, x.nextSibling);
9560
Q('p7').classList.add('pluginOverlayBg');