luci-base: luci.js: introduce hasSystemFeature() api
The new function allows querying the presence of certain system features such as dnsmasq or firewall availability or the compile time features of hostapd and wpa_supplicant. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
3b335f2764
commit
a4621c9520
3 changed files with 137 additions and 2 deletions
|
@ -559,6 +559,7 @@
|
||||||
domParser = null,
|
domParser = null,
|
||||||
originalCBIInit = null,
|
originalCBIInit = null,
|
||||||
rpcBaseURL = null,
|
rpcBaseURL = null,
|
||||||
|
sysFeatures = null,
|
||||||
classes = {};
|
classes = {};
|
||||||
|
|
||||||
var LuCI = Class.extend({
|
var LuCI = Class.extend({
|
||||||
|
@ -797,6 +798,43 @@
|
||||||
return Promise.resolve(rpcBaseURL);
|
return Promise.resolve(rpcBaseURL);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
probeSystemFeatures: function() {
|
||||||
|
if (sysFeatures == null) {
|
||||||
|
try {
|
||||||
|
sysFeatures = JSON.parse(window.sessionStorage.getItem('sysFeatures'));
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isObject(sysFeatures)) {
|
||||||
|
sysFeatures = classes.rpc.declare({
|
||||||
|
object: 'luci',
|
||||||
|
method: 'getFeatures',
|
||||||
|
expect: { '': {} }
|
||||||
|
})().then(function(features) {
|
||||||
|
try {
|
||||||
|
window.sessionStorage.setItem('sysFeatures', JSON.stringify(features));
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
|
||||||
|
sysFeatures = features;
|
||||||
|
|
||||||
|
return features;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(sysFeatures);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasSystemFeature: function() {
|
||||||
|
var ft = sysFeatures[arguments[0]];
|
||||||
|
|
||||||
|
if (arguments.length == 2)
|
||||||
|
return this.isObject(ft) ? ft[arguments[1]] : null;
|
||||||
|
|
||||||
|
return (ft != null && ft != false);
|
||||||
|
},
|
||||||
|
|
||||||
setupDOM: function(res) {
|
setupDOM: function(res) {
|
||||||
var domEv = res[0],
|
var domEv = res[0],
|
||||||
uiClass = res[1],
|
uiClass = res[1],
|
||||||
|
@ -828,10 +866,12 @@
|
||||||
throw 'Session expired';
|
throw 'Session expired';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return this.probeSystemFeatures().finally(this.initDOM);
|
||||||
|
},
|
||||||
|
|
||||||
|
initDOM: function() {
|
||||||
originalCBIInit();
|
originalCBIInit();
|
||||||
|
|
||||||
Poll.start();
|
Poll.start();
|
||||||
|
|
||||||
document.dispatchEvent(new CustomEvent('luci-loaded'));
|
document.dispatchEvent(new CustomEvent('luci-loaded'));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -320,6 +320,92 @@ local methods = {
|
||||||
|
|
||||||
return { helpers = rv }
|
return { helpers = rv }
|
||||||
end
|
end
|
||||||
|
},
|
||||||
|
|
||||||
|
getFeatures = {
|
||||||
|
call = function()
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
local rv = {}
|
||||||
|
local ok, fd
|
||||||
|
|
||||||
|
rv.firewall = fs.access("/sbin/fw3")
|
||||||
|
rv.opkg = fs.access("/bin/opkg")
|
||||||
|
rv.offloading = fs.access("/sys/module/xt_FLOWOFFLOAD/refcnt")
|
||||||
|
rv.br2684ctl = fs.access("/usr/sbin/br2684ctl")
|
||||||
|
rv.swconfig = fs.access("/sbin/swconfig")
|
||||||
|
rv.odhcpd = fs.access("/usr/sbin/odhcpd")
|
||||||
|
|
||||||
|
local wifi_features = { "eap", "11n", "11ac", "11r", "11w", "acs", "sae", "owe", "suiteb192" }
|
||||||
|
|
||||||
|
if fs.access("/usr/sbin/hostapd") then
|
||||||
|
rv.hostapd = {}
|
||||||
|
|
||||||
|
local _, feature
|
||||||
|
for _, feature in ipairs(wifi_features) do
|
||||||
|
rv.hostapd[feature] =
|
||||||
|
(os.execute(string.format("/usr/sbin/hostapd -v%s >/dev/null 2>/dev/null", feature)) == 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fs.access("/usr/sbin/wpa_supplicant") then
|
||||||
|
rv.wpasupplicant = {}
|
||||||
|
|
||||||
|
local _, feature
|
||||||
|
for _, feature in ipairs(wifi_features) do
|
||||||
|
rv.wpasupplicant[feature] =
|
||||||
|
(os.execute(string.format("/usr/sbin/wpa_supplicant -v%s >/dev/null 2>/dev/null", feature)) == 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ok, fd = pcall(io.popen, "dnsmasq --version 2>/dev/null")
|
||||||
|
if ok then
|
||||||
|
rv.dnsmasq = {}
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local line = fd:read("*l")
|
||||||
|
if not line then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local opts = line:match("^Compile time options: (.+)$")
|
||||||
|
if opts then
|
||||||
|
local opt
|
||||||
|
for opt in opts:gmatch("%S+") do
|
||||||
|
local no = opt:match("^no%-(%S+)$")
|
||||||
|
rv.dnsmasq[string.lower(no or opt)] = not no
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
ok, fd = pcall(io.popen, "ipset --help 2>/dev/null")
|
||||||
|
if ok then
|
||||||
|
rv.ipset = {}
|
||||||
|
|
||||||
|
local sets = false
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local line = fd:read("*l")
|
||||||
|
if not line then
|
||||||
|
break
|
||||||
|
elseif line:match("^Supported set types:") then
|
||||||
|
sets = true
|
||||||
|
elseif sets then
|
||||||
|
local set, ver = line:match("^%s+(%S+)%s+(%d+)")
|
||||||
|
if set and not rv.ipset[set] then
|
||||||
|
rv.ipset[set] = tonumber(ver)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
return rv
|
||||||
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
{
|
{
|
||||||
|
"unauthenticated": {
|
||||||
|
"description": "Allow system feature probing",
|
||||||
|
"read": {
|
||||||
|
"ubus": {
|
||||||
|
"luci": [ "getFeatures" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"uci-access": {
|
"uci-access": {
|
||||||
"description": "Grant uci write access to all configurations",
|
"description": "Grant uci write access to all configurations",
|
||||||
"read": {
|
"read": {
|
||||||
|
|
Loading…
Reference in a new issue