Tweaks to plugin install/removal so server does not require a restart. Initial support for downgrading plugins.
This commit is contained in:
parent
11f2721533
commit
145c898c70
4
db.js
4
db.js
|
@ -766,6 +766,8 @@ module.exports.CreateDB = function (parent, func) {
|
||||||
|
|
||||||
obj.setPluginStatus = function(id, status, func) { id = require('mongodb').ObjectID(id); obj.pluginsfile.updateOne({ _id: id }, { $set: {status: status } }, func); };
|
obj.setPluginStatus = function(id, status, func) { id = require('mongodb').ObjectID(id); obj.pluginsfile.updateOne({ _id: id }, { $set: {status: status } }, func); };
|
||||||
|
|
||||||
|
obj.updatePlugin = function(id, args, func) { delete args._id; id = require('mongodb').ObjectID(id); obj.pluginsfile.updateOne({ _id: id }, { $set: args }, func); };
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Database actions on the main collection (NeDB and MongoJS)
|
// Database actions on the main collection (NeDB and MongoJS)
|
||||||
obj.Set = function (data, func) {
|
obj.Set = function (data, func) {
|
||||||
|
@ -910,6 +912,8 @@ module.exports.CreateDB = function (parent, func) {
|
||||||
|
|
||||||
obj.setPluginStatus = function(id, status, func) { obj.pluginsfile.update({ _id: id }, { $set: {status: status } }, func); };
|
obj.setPluginStatus = function(id, status, func) { obj.pluginsfile.update({ _id: id }, { $set: {status: status } }, func); };
|
||||||
|
|
||||||
|
obj.updatePlugin = function(id, args, func) { delete args._id; obj.pluginsfile.update({ _id: id }, { $set: args }, func); };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func(obj); // Completed function setup
|
func(obj); // Completed function setup
|
||||||
|
|
20
meshuser.js
20
meshuser.js
|
@ -3147,11 +3147,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
}
|
}
|
||||||
case 'installplugin': {
|
case 'installplugin': {
|
||||||
if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
|
if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
|
||||||
parent.parent.pluginHandler.installPlugin(command.id, function(){
|
parent.parent.pluginHandler.installPlugin(command.id, command.version_only, function(){
|
||||||
parent.parent.updateMeshCore();
|
|
||||||
parent.db.getPlugins(function(err, docs) {
|
parent.db.getPlugins(function(err, docs) {
|
||||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||||
});
|
});
|
||||||
|
var targets = ['*', 'server-users'];
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { action: 'pluginStateChange' });
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3160,7 +3161,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
parent.parent.pluginHandler.disablePlugin(command.id, function(){
|
parent.parent.pluginHandler.disablePlugin(command.id, function(){
|
||||||
parent.db.getPlugins(function(err, docs) {
|
parent.db.getPlugins(function(err, docs) {
|
||||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||||
// @TODO delete plugin object from handler
|
var targets = ['*', 'server-users'];
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { action: 'pluginStateChange' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -3174,6 +3176,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'getpluginversions': {
|
||||||
|
if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
|
||||||
|
parent.parent.pluginHandler.getPluginVersions(command.id)
|
||||||
|
.then(function (versionInfo) {
|
||||||
|
try { ws.send(JSON.stringify({ action: 'downgradePluginVersions', info: versionInfo, error: null })); } catch (ex) { }
|
||||||
|
})
|
||||||
|
.catch(function (e) {
|
||||||
|
try { ws.send(JSON.stringify({ action: 'pluginError', msg: e })); } catch (ex) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'plugin': {
|
case 'plugin': {
|
||||||
if (parent.parent.pluginHandler == null) break; // If the plugin's are not supported, reject this command.
|
if (parent.parent.pluginHandler == null) break; // If the plugin's are not supported, reject this command.
|
||||||
command.userid = user._id;
|
command.userid = user._id;
|
||||||
|
|
107
pluginHandler.js
107
pluginHandler.js
|
@ -38,6 +38,11 @@ module.exports.pluginHandler = function (parent) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error loading plugin: " + plugin.shortName + " (" + e + "). It has been disabled.", e.stack);
|
console.log("Error loading plugin: " + plugin.shortName + " (" + e + "). It has been disabled.", e.stack);
|
||||||
}
|
}
|
||||||
|
try { // try loading local info about plugin to database (if it changed locally)
|
||||||
|
var plugin_config = obj.fs.readFileSync(obj.pluginPath + '/' + plugin.shortName + '/config.json');
|
||||||
|
plugin_config = JSON.parse(plugin_config);
|
||||||
|
parent.db.updatePlugin(plugin._id, plugin_config);
|
||||||
|
} catch (e) { console.log('Plugin config file for '+ plugin.name +' could not be parsed.'); }
|
||||||
}
|
}
|
||||||
obj.parent.updateMeshCore(); // db calls are delayed, lets inject here once we're ready
|
obj.parent.updateMeshCore(); // db calls are delayed, lets inject here once we're ready
|
||||||
});
|
});
|
||||||
|
@ -93,10 +98,21 @@ module.exports.pluginHandler = function (parent) {
|
||||||
setDialogMode(2, "Plugin Config URL", 3, obj.addPluginEx, '<input type=text id=pluginurlinput style=width:100% />');
|
setDialogMode(2, "Plugin Config URL", 3, obj.addPluginEx, '<input type=text id=pluginurlinput style=width:100% />');
|
||||||
focusTextBox('pluginurlinput');
|
focusTextBox('pluginurlinput');
|
||||||
};
|
};
|
||||||
|
obj.refreshPluginHandler = function() {
|
||||||
|
let st = document.createElement('script');
|
||||||
|
st.src = '/pluginHandler.js';
|
||||||
|
document.body.appendChild(st);
|
||||||
|
};
|
||||||
return obj; };`;
|
return obj; };`;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj.refreshJS = function(req, res) {
|
||||||
|
// to minimize server reboots when installing new plugins, we call the new data and overwrite the old pluginHandler on the front end
|
||||||
|
res.set('Content-Type', 'text/javascript');
|
||||||
|
res.send('pluginHandlerBuilder = '+obj.prepExports() + ' pluginHandler = new pluginHandlerBuilder();');
|
||||||
|
}
|
||||||
|
|
||||||
obj.callHook = function (hookName, ...args) {
|
obj.callHook = function (hookName, ...args) {
|
||||||
for (var p in obj.plugins) {
|
for (var p in obj.plugins) {
|
||||||
if (typeof obj.plugins[p][hookName] == 'function') {
|
if (typeof obj.plugins[p][hookName] == 'function') {
|
||||||
|
@ -182,7 +198,7 @@ module.exports.pluginHandler = function (parent) {
|
||||||
typeof conf.name == 'string'
|
typeof conf.name == 'string'
|
||||||
&& typeof conf.shortName == 'string'
|
&& typeof conf.shortName == 'string'
|
||||||
&& typeof conf.version == 'string'
|
&& typeof conf.version == 'string'
|
||||||
&& typeof conf.author == 'string'
|
// && typeof conf.author == 'string'
|
||||||
&& typeof conf.description == 'string'
|
&& typeof conf.description == 'string'
|
||||||
&& typeof conf.hasAdminPanel == 'boolean'
|
&& typeof conf.hasAdminPanel == 'boolean'
|
||||||
&& typeof conf.homepage == 'string'
|
&& typeof conf.homepage == 'string'
|
||||||
|
@ -290,6 +306,7 @@ module.exports.pluginHandler = function (parent) {
|
||||||
"url": pluginConfig.repository.url
|
"url": pluginConfig.repository.url
|
||||||
},
|
},
|
||||||
"meshCentralCompat": pluginConfig.meshCentralCompat,
|
"meshCentralCompat": pluginConfig.meshCentralCompat,
|
||||||
|
"versionHistoryUrl": pluginConfig.versionHistoryUrl,
|
||||||
"status": 0 // 0: disabled, 1: enabled
|
"status": 0 // 0: disabled, 1: enabled
|
||||||
}, function() {
|
}, function() {
|
||||||
parent.db.getPlugins(function(err, docs){
|
parent.db.getPlugins(function(err, docs){
|
||||||
|
@ -300,16 +317,32 @@ module.exports.pluginHandler = function (parent) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.installPlugin = function(id, func) {
|
obj.installPlugin = function(id, version_only, func) {
|
||||||
parent.db.getPlugin(id, function(err, docs){
|
parent.db.getPlugin(id, function(err, docs){
|
||||||
var http = require('https');
|
|
||||||
// the "id" would probably suffice, but is probably an sanitary issue, generate a random instead
|
// the "id" would probably suffice, but is probably an sanitary issue, generate a random instead
|
||||||
var randId = Math.random().toString(32).replace('0.', '');
|
var randId = Math.random().toString(32).replace('0.', '');
|
||||||
var fileName = obj.parent.path.join(require('os').tmpdir(), 'Plugin_'+randId+'.zip');
|
var fileName = obj.parent.path.join(require('os').tmpdir(), 'Plugin_'+randId+'.zip');
|
||||||
var plugin = docs[0];
|
var plugin = docs[0];
|
||||||
if (plugin.repository.type == 'git') {
|
if (plugin.repository.type == 'git') {
|
||||||
const file = obj.fs.createWriteStream(fileName);
|
const file = obj.fs.createWriteStream(fileName);
|
||||||
var request = http.get(plugin.downloadUrl, function(response) {
|
var dl_url = plugin.downloadUrl;
|
||||||
|
if (version_only != null && version_only != false) dl_url = version_only.url;
|
||||||
|
var url = require('url');
|
||||||
|
var q = url.parse(dl_url, true);
|
||||||
|
var http = (q.protocol == "http") ? require('http') : require('https');
|
||||||
|
var opts = {
|
||||||
|
path: q.pathname,
|
||||||
|
host: q.hostname,
|
||||||
|
port: q.port,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'MeshCentral'
|
||||||
|
},
|
||||||
|
followRedirects: true,
|
||||||
|
method: 'GET'
|
||||||
|
};
|
||||||
|
var request = http.get(opts, function(response) {
|
||||||
|
// handle redirections with grace
|
||||||
|
if (response.headers.location) return obj.installPlugin(id, { name: version_only.name, url: response.headers.location }, func);
|
||||||
response.pipe(file);
|
response.pipe(file);
|
||||||
file.on('finish', function() {
|
file.on('finish', function() {
|
||||||
file.close(function(){
|
file.close(function(){
|
||||||
|
@ -341,18 +374,24 @@ module.exports.pluginHandler = function (parent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
zipfile.on("end", function () { setTimeout(function () {
|
zipfile.on("end", function () { setTimeout(function () {
|
||||||
obj.fs.unlinkSync(fileName);
|
obj.fs.unlinkSync(fileName);
|
||||||
parent.db.setPluginStatus(id, 1, func);
|
if (version_only == null || version_only === false) {
|
||||||
|
parent.db.setPluginStatus(id, 1, func);
|
||||||
|
} else {
|
||||||
|
parent.db.updatePlugin(id, { status: 1, version: version_only.name }, func);
|
||||||
|
}
|
||||||
obj.plugins[plugin.shortName] = require(obj.pluginPath + '/' + plugin.shortName + '/' + plugin.shortName + '.js')[plugin.shortName](obj);
|
obj.plugins[plugin.shortName] = require(obj.pluginPath + '/' + plugin.shortName + '/' + plugin.shortName + '.js')[plugin.shortName](obj);
|
||||||
obj.exports[plugin.shortName] = obj.plugins[plugin.shortName].exports;
|
obj.exports[plugin.shortName] = obj.plugins[plugin.shortName].exports;
|
||||||
|
if (typeof obj.plugins[plugin.shortName].server_startup == 'function') obj.plugins[plugin.shortName].server_startup();
|
||||||
|
parent.updateMeshCore();
|
||||||
}); });
|
}); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (plugin.repository.type == 'npm') {
|
} else if (plugin.repository.type == 'npm') {
|
||||||
// @TODO npm install and symlink dirs (need a test plugin)
|
// @TODO npm support? (need a test plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -361,8 +400,58 @@ module.exports.pluginHandler = function (parent) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
obj.getPluginVersions = function(id) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
parent.db.getPlugin(id, function(err, docs) {
|
||||||
|
var plugin = docs[0];
|
||||||
|
if (plugin.versionHistoryUrl == null) reject('No version history available for this plugin.');
|
||||||
|
var url = require('url');
|
||||||
|
var q = url.parse(plugin.versionHistoryUrl, true);
|
||||||
|
var http = (q.protocol == "http") ? require('http') : require('https');
|
||||||
|
var opts = {
|
||||||
|
path: q.pathname,
|
||||||
|
host: q.hostname,
|
||||||
|
port: q.port,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'MeshCentral',
|
||||||
|
'Accept': 'application/vnd.github.v3+json'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
http.get(opts, function(res) {
|
||||||
|
var versStr = '';
|
||||||
|
res.on('data', function(chunk){
|
||||||
|
versStr += chunk;
|
||||||
|
});
|
||||||
|
res.on('end', function(){
|
||||||
|
if (versStr[0] == '{' || versStr[0] == '[') { // let's be sure we're JSON
|
||||||
|
try {
|
||||||
|
var vers = JSON.parse(versStr);
|
||||||
|
var vList = [];
|
||||||
|
var s = require('semver');
|
||||||
|
vers.forEach((v) => {
|
||||||
|
if (s.lt(v.name, plugin.version)) vList.push(v);
|
||||||
|
});
|
||||||
|
if (vers.length == 0) reject('No previous versions available.');
|
||||||
|
resolve({ 'id': plugin._id, 'name': plugin.name, versionList: vList });
|
||||||
|
} catch (e) { reject('Version history problem.'); }
|
||||||
|
} else {
|
||||||
|
reject('Version history appears to be malformed.'+versStr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on('error', function(e) {
|
||||||
|
reject("Error getting plugin versions: " + e.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
obj.disablePlugin = function(id, func) {
|
obj.disablePlugin = function(id, func) {
|
||||||
parent.db.setPluginStatus(id, 0, func);
|
parent.db.getPlugin(id, function(err, docs){
|
||||||
|
var plugin = docs[0];
|
||||||
|
parent.db.setPluginStatus(id, 0, func);
|
||||||
|
delete obj.plugins[plugin.shortName];
|
||||||
|
delete obj.exports[plugin.shortName];
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.removePlugin = function(id, func) {
|
obj.removePlugin = function(id, func) {
|
||||||
|
|
|
@ -423,7 +423,7 @@
|
||||||
<table id="p7tbl">
|
<table id="p7tbl">
|
||||||
<tr><th class="chName">Name</th><th class="chDescription">Description</th><th class="chSite">Link</th><th class="chVersion">Version</th><th class="chUpgradeAvail">Latest Available</th><th class="chStatus">Status</th><th class="chAction">Action</th></tr>
|
<tr><th class="chName">Name</th><th class="chDescription">Description</th><th class="chSite">Link</th><th class="chVersion">Version</th><th class="chUpgradeAvail">Latest Available</th><th class="chStatus">Status</th><th class="chAction">Action</th></tr>
|
||||||
</table>
|
</table>
|
||||||
<div id="pluginRestartNotice" style="display:none;"><div>Notice:</div> MeshCentral restart required to complete plugin changes.</div>
|
<div id="pluginRestartNotice" style="display:none;"><div>Notice:</div> MeshCentral plugins have been altered. Agent cores require may require an update before full features are available.</div>
|
||||||
</div>
|
</div>
|
||||||
<div id=p10 style="display:none">
|
<div id=p10 style="display:none">
|
||||||
<table style="width:100%" cellpadding="0" cellspacing="0">
|
<table style="width:100%" cellpadding="0" cellspacing="0">
|
||||||
|
@ -2313,6 +2313,11 @@
|
||||||
updatePluginList();
|
updatePluginList();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'pluginStateChange': {
|
||||||
|
if (pluginHandler == null) break;
|
||||||
|
pluginHandler.refreshPluginHandler();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
//console.log('Unknown message.event.action', message.event.action);
|
//console.log('Unknown message.event.action', message.event.action);
|
||||||
break;
|
break;
|
||||||
|
@ -2376,6 +2381,15 @@
|
||||||
updatePluginList(message.list);
|
updatePluginList(message.list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'downgradePluginVersions': {
|
||||||
|
var vSelect = '<select id="lastPluginVersion">';
|
||||||
|
message.info.versionList.forEach(function(v){
|
||||||
|
vSelect += '<option value="' + v.zipball_url + '">' + v.name + '</option>';
|
||||||
|
});
|
||||||
|
vSelect += '</select>';
|
||||||
|
setDialogMode(2, 'Plugin Action', 3, pluginActionEx, 'Select the version to downgrade the plugin: ' + message.info.name + '<hr />' + vSelect + '<hr />Please be aware that downgrading is not recommended. Please only do so in the event that a recent upgrade has broken something.<input id="lastPluginAct" type="hidden" value="downgrade" /><input id="lastPluginId" type="hidden" value="' + message.info.id + '" />');
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'pluginError': {
|
case 'pluginError': {
|
||||||
setDialogMode(2, 'Oops!', 1, null, message.msg);
|
setDialogMode(2, 'Oops!', 1, null, message.msg);
|
||||||
break;
|
break;
|
||||||
|
@ -9480,7 +9494,8 @@
|
||||||
},
|
},
|
||||||
1: {
|
1: {
|
||||||
'disable': 'Disable',
|
'disable': 'Disable',
|
||||||
'upgrade': 'Upgrade'
|
'upgrade': 'Upgrade',
|
||||||
|
// 'downgrade': 'Downgrade' // disabling until plugins have prior versions available for better testing
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var vers_not_compat = ` [ <span onclick="return setDialogMode(2, 'Compatibility Issue', 1, null, 'This plugin version is not compatible with your MeshCentral installation, please upgrade MeshCentral first.');" title="Version incompatible, please upgrade your MeshCentral installation first" style="cursor: pointer; color:red;"> ! </span> ]`;
|
var vers_not_compat = ` [ <span onclick="return setDialogMode(2, 'Compatibility Issue', 1, null, 'This plugin version is not compatible with your MeshCentral installation, please upgrade MeshCentral first.');" title="Version incompatible, please upgrade your MeshCentral installation first" style="cursor: pointer; color:red;"> ! </span> ]`;
|
||||||
|
@ -9488,7 +9503,7 @@
|
||||||
var tbl = Q('p7tbl');
|
var tbl = Q('p7tbl');
|
||||||
installedPluginList.forEach(function(p){
|
installedPluginList.forEach(function(p){
|
||||||
var cant_action = [];
|
var cant_action = [];
|
||||||
if (p.hasAdminPanel == true) {
|
if (p.hasAdminPanel == true && p.status) {
|
||||||
p.nameHtml = `<a onclick="return goPlugin('${p.shortName}', '${p.name}');">${p.name}</a>`;
|
p.nameHtml = `<a onclick="return goPlugin('${p.shortName}', '${p.name}');">${p.name}</a>`;
|
||||||
} else {
|
} else {
|
||||||
p.nameHtml = p.name;
|
p.nameHtml = p.name;
|
||||||
|
@ -9496,7 +9511,9 @@
|
||||||
p.statusText = statusMap[p.status].text;
|
p.statusText = statusMap[p.status].text;
|
||||||
p.statusColor = statusMap[p.status].color;
|
p.statusColor = statusMap[p.status].color;
|
||||||
|
|
||||||
|
if (p.versionHistoryUrl == null) {
|
||||||
|
cant_action.push('downgrade');
|
||||||
|
}
|
||||||
|
|
||||||
if (!p.status) { // It isn't technically installed, so no version number
|
if (!p.status) { // It isn't technically installed, so no version number
|
||||||
p.version = ' - ';
|
p.version = ' - ';
|
||||||
|
@ -9547,11 +9564,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function pluginActionEx() {
|
function pluginActionEx() {
|
||||||
var act = Q('lastPluginAct').value, id = Q('lastPluginId').value;
|
var act = Q('lastPluginAct').value, id = Q('lastPluginId').value, pVersUrl = Q('lastPluginVersion').value;
|
||||||
|
|
||||||
switch(act) {
|
switch(act) {
|
||||||
case 'upgrade':
|
case 'upgrade':
|
||||||
case 'install':
|
case 'install':
|
||||||
meshserver.send({ "action": "installplugin", "id": id });
|
meshserver.send({ "action": "installplugin", "id": id, "version_only": false });
|
||||||
|
break;
|
||||||
|
case 'downgrade':
|
||||||
|
Q('lastPluginVersion').querySelectorAll('option').forEach(function(opt) {
|
||||||
|
if (opt.value == pVersUrl) pVers = opt.text;
|
||||||
|
});
|
||||||
|
meshserver.send({ "action": "installplugin", "id": id, "version_only": { "name": pVers, "url": pVersUrl }});
|
||||||
break;
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
meshserver.send({ "action": "removeplugin", "id": id });
|
meshserver.send({ "action": "removeplugin", "id": id });
|
||||||
|
@ -9564,7 +9588,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function pluginAction(elem, id) {
|
function pluginAction(elem, id) {
|
||||||
setDialogMode(2, 'Plugin Action', 3, pluginActionEx, 'Are you sure you want to ' + elem.value + ' the plugin: ' + elem.parentNode.parentNode.firstChild.innerText+'<input id="lastPluginAct" type="hidden" value="' + elem.value + '" /><input id="lastPluginId" type="hidden" value="' + elem.parentNode.parentNode.getAttribute('data-id') + '" />');
|
if (elem.value == 'downgrade') {
|
||||||
|
meshserver.send({ "action": "getpluginversions", "id": id });
|
||||||
|
} else {
|
||||||
|
setDialogMode(2, 'Plugin Action', 3, pluginActionEx, 'Are you sure you want to ' + elem.value + ' the plugin: ' + elem.parentNode.parentNode.firstChild.innerText+'<input id="lastPluginAct" type="hidden" value="' + elem.value + '" /><input id="lastPluginId" type="hidden" value="' + elem.parentNode.parentNode.getAttribute('data-id') + '" /><input id="lastPluginVersion" type="hidden" value="" />');
|
||||||
|
}
|
||||||
elem.value = '';
|
elem.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
webserver.js
11
webserver.js
|
@ -3208,6 +3208,16 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
parent.pluginHandler.handleAdminPostReq(req, res, user, obj);
|
parent.pluginHandler.handleAdminPostReq(req, res, user, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj.handlePluginJS = function(req, res) {
|
||||||
|
const domain = checkUserIpAddress(req, res);
|
||||||
|
if (domain == null) { res.sendStatus(404); return; }
|
||||||
|
if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
|
||||||
|
var user = obj.users[req.session.userid];
|
||||||
|
if (user == null) { res.sendStatus(401); return; }
|
||||||
|
|
||||||
|
parent.pluginHandler.refreshJS(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
// Starts the HTTPS server, this should be called after the user/mesh tables are loaded
|
// Starts the HTTPS server, this should be called after the user/mesh tables are loaded
|
||||||
function serverStart() {
|
function serverStart() {
|
||||||
|
@ -3334,6 +3344,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (parent.pluginHandler != null) {
|
if (parent.pluginHandler != null) {
|
||||||
obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq);
|
obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq);
|
||||||
obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq);
|
obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq);
|
||||||
|
obj.app.get(url + 'pluginHandler.js', obj.handlePluginJS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server redirects
|
// Server redirects
|
||||||
|
|
Loading…
Reference in New Issue