Plugin admin partial
Ryan Blenis committed
Nov 2, 2019 at 06:27 UTC
bbb402b533594354cc1478aabfe5dcd917b87171
5 files changed
+126
-13
meshuser.js
+1
@@ -3147,6 +3147,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3147
parent.parent.pluginHandler.disablePlugin(command.id, function(){
3148
parent.db.getPlugins(function(err, docs) {
3149
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
3150
+ // @TODO delete plugin object from handler
3151
});
3152
});
3153
break;
pluginHandler.js
+25
-10
@@ -54,21 +54,15 @@ module.exports.pluginHandler = function (parent) {
54
});
55
}
56
57
- obj.prepExportsForPlugin = function(plugin) {
58
- var str = '';
59
- str += ' obj.' + plugin + ' = {};\r\n';
60
- for (const l of Object.values(obj.exports[plugin])) {
61
- str += ' obj.' + plugin + '.' + l + ' = ' + obj.plugins[plugin][l].toString() + '\r\n';
62
- }
63
- return str;
64
- };
65
-
57
obj.prepExports = function () {
58
var str = 'function() {\r\n';
59
str += ' var obj = {};\r\n';
60
61
for (const p of Object.keys(obj.plugins)) {
71
- str += obj.prepExportsForPlugin(p);
62
+ str += ' obj.' + p + ' = {};\r\n';
63
+ for (const l of Object.values(obj.exports[p])) {
64
+ str += ' obj.' + p + '.' + l + ' = ' + obj.plugins[p][l].toString() + '\r\n';
65
+ }
66
}
67
68
str += `obj.onDeviceRefeshEnd = function(nodeid, panel, refresh, event) {
@@ -371,5 +365,26 @@ module.exports.pluginHandler = function (parent) {
365
});
366
};
367
368
+ obj.handleAdminReq = function (req, res, serv) {
369
+ var path = obj.path.join(obj.pluginPath, req.query.pin, 'views');
370
+ serv.app.set('views', path);
371
+ if (obj.plugins[req.query.pin] != null && typeof obj.plugins[req.query.pin].handleAdminReq == 'function') {
372
+ obj.plugins[req.query.pin].handleAdminReq(req, res);
373
+ }
374
+ else {
375
+ res.sendStatus(401);
376
+ }
377
+ }
378
+
379
+ obj.handleAdminPostReq = function(req, res, serv) {
380
+ var path = obj.path.join(obj.pluginPath, req.query.pin, 'views');
381
+ serv.app.set('views', path);
382
+ if (obj.plugins[req.query.pin] != null && typeof obj.plugins[req.query.pin].handleAdminPostReq == 'function') {
383
+ obj.plugins[req.query.pin].handleAdminPostReq(req, res);
384
+ }
385
+ else {
386
+ res.sendStatus(401);
387
+ }
388
+ }
389
return obj;
390
};
\ No newline at end of file
public/styles/style.css
+41
@@ -2627,4 +2627,45 @@ a {
2627
text-align: center;
2628
padding: 14px;
2629
margin: 50px auto;
2630
+}
2631
+
2632
+.pluginOverlayBg {
2633
+ width: 95%; /* Full width (cover the whole page) */
2634
+ height: 95%; /* Full height (cover the whole page) */
2635
+ margin: 10px;
2636
+ background-color: rgba(0,0,0,0.8); /* Black background with opacity */
2637
+ z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
2638
+ position: absolute;
2639
+ cursor: pointer; /* Add a pointer on hover */
2640
+ filter:blur(4px);
2641
+ -o-filter:blur(4px);
2642
+ -ms-filter:blur(4px);
2643
+ -moz-filter:blur(4px);
2644
+ -webkit-filter:blur(4px);
2645
+}
2646
+
2647
+.pluginOverlay {
2648
+ width: 95%; /* Full width (cover the whole page) */
2649
+ height: 95%; /* Full height (cover the whole page) */
2650
+ margin: 10px;
2651
+ background-color: #FFFFFF; /* Black background with opacity */
2652
+ z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
2653
+ position: absolute;
2654
+ cursor: pointer; /* Add a pointer on hover */
2655
+}
2656
+
2657
+.pluginTitleBar {
2658
+ padding: 4px;
2659
+ height: 25px;
2660
+ border-bottom: double;
2661
+ font-size: 20px;
2662
+}
2663
+
2664
+.pluginCloseBtn {
2665
+ border: none;
2666
+ outline: none;
2667
+ cursor: pointer;
2668
+ float: right;
2669
+ position: relative;
2670
+ padding: 0;
2671
}
\ No newline at end of file
views/default.handlebars
+35
-3
@@ -9408,7 +9408,7 @@
9408
// Fetch the server timeline stats if needed
9409
if ((x == 40) && (serverTimelineStats == null)) { refreshServerTimelineStats(); }
9410
9411
- if (x == 7) refreshPluginLatest();
9411
+ if (x == 7) refreshPluginLatest(); else noGoPlugin();
9412
9413
// Update the web page title
9414
if ((currentNode) && (x >= 10) && (x < 20)) {
@@ -9456,7 +9456,7 @@
9456
installedPluginList.forEach(function(p){
9457
var cant_action = [];
9458
if (p.hasAdminPanel == true) {
9459
- p.name = `<a onclick="return goPlugin('${p._id}');">${p.name}</a>`;
9459
+ p.nameHtml = `<a onclick="return goPlugin('${p.shortName}', '${p.name}');">${p.name}</a>`;
9460
}
9461
p.statusText = statusMap[p.status].text;
9462
p.statusColor = statusMap[p.status].color;
@@ -9490,7 +9490,7 @@
9490
}
9491
p.actions += '</select>';
9492
9493
- let tpl = `<td>${p.name}</td><td>${p.description}</td><td><a href="${p.homepage}" target="_blank">Homepage</a></td><td>${p.version}</td><td class="pluginUpgradeAvailable">${p.upgradeAvail}</td><td style="color: #${p.statusColor}">${p.statusText}</td><td class="pluginAction">${p.actions}</td>`;
9493
+ let tpl = `<td>${p.nameHtml}</td><td>${p.description}</td><td><a href="${p.homepage}" target="_blank">Homepage</a></td><td>${p.version}</td><td class="pluginUpgradeAvailable">${p.upgradeAvail}</td><td style="color: #${p.statusColor}">${p.statusText}</td><td class="pluginAction">${p.actions}</td>`;
9494
let tr = tbl.insertRow(-1);
9495
tr.innerHTML = tpl;
9496
tr.classList.add('p7tblRow');
@@ -9532,6 +9532,38 @@
9532
elem.value = '';
9533
}
9534
9535
+ 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>`
9537
+ let dif = document.createElement('div');
9538
+ dif.classList.add('pluginOverlay');
9539
+ dif.innerHTML = xwin;
9540
+ let pif = document.createElement('iframe');
9541
+ pif.src = '/pluginadmin.ashx?pin='+pname;
9542
+ pif.setAttribute('frameBorder', '0');
9543
+ pif.style.width = '100%';
9544
+ pif.style.height = '100%';
9545
+ pif.setAttribute('frameBorder', '0');
9546
+
9547
+ dif.append(pif);
9548
+ let x = Q('p7');
9549
+ x.parentNode.insertBefore(dif, x.nextSibling);
9550
+ Q('p7').classList.add('pluginOverlayBg');
9551
+ }
9552
+
9553
+ function noGoPlugin(el) {
9554
+ if (el == null) {
9555
+ var boxes = document.querySelectorAll('.pluginOverlay');
9556
+ for (const b in Object.values(boxes)) {
9557
+ boxes[b].parentNode.removeChild(boxes[b]);
9558
+ }
9559
+ Q('p7').classList.remove('pluginOverlayBg');
9560
+ return;
9561
+ }
9562
+ var box = document.querySelector('.pluginOverlay').closest(".pluginOverlay");
9563
+ box.parentNode.removeChild(box);
9564
+ Q('p7').classList.remove('pluginOverlayBg');
9565
+ }
9566
+
9567
// Generic methods
9568
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
9569
function putstore(name, val) {
webserver.js
+24
@@ -3188,6 +3188,26 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3188
}
3189
});
3190
}
3191
+
3192
+ obj.handlePluginAdminReq = function(req, res) {
3193
+ const domain = checkUserIpAddress(req, res);
3194
+ if (domain == null) { res.sendStatus(404); return; }
3195
+ if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
3196
+ var user = obj.users[req.session.userid];
3197
+ if ((user == null) || ((user.siteadmin & 0xFFFFFFFF) == 0)) { res.sendStatus(401); return; }
3198
+
3199
+ parent.pluginHandler.handleAdminReq(req, res, obj);
3200
+ }
3201
+
3202
+ obj.handlePluginAdminPostReq = function(req, res) {
3203
+ const domain = checkUserIpAddress(req, res);
3204
+ if (domain == null) { res.sendStatus(404); return; }
3205
+ if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
3206
+ var user = obj.users[req.session.userid];
3207
+ if ((user == null) || ((user.siteadmin & 0xFFFFFFFF) == 0)) { res.sendStatus(401); return; }
3208
+
3209
+ parent.pluginHandler.handleAdminPostReq(req, res, obj);
3210
+ }
3211
3212
// Starts the HTTPS server, this should be called after the user/mesh tables are loaded
3213
function serverStart() {
@@ -3311,6 +3331,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3331
obj.app.get(url + 'logo.png', handleLogoRequest);
3332
obj.app.get(url + 'welcome.jpg', handleWelcomeImageRequest);
3333
obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket);
3334
+ if (parent.pluginHandler != null) {
3335
+ obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq);
3336
+ obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq);
3337
+ }
3338
3339
// Server redirects
3340
if (parent.config.domains[i].redirects) { for (var j in parent.config.domains[i].redirects) { if (j[0] != '_') { obj.app.get(url + j, obj.handleDomainRedirect); } } }