op-packages/luci-app-nodogsplash/htdocs/luci-static/resources/view/nodogsplash/mac.js
github-actions[bot] 32600acc60 🌴 Sync 2026-03-05 23:51:42
2026-03-05 23:51:42 +08:00

188 lines
6.5 KiB
JavaScript

'use strict';
'require form';
'require ui';
'require view';
'require uci';
'require fs';
// Project code format is tabs, not spaces
return view.extend({
can_block: true,
auth_list: [],
allow_list: [],
block_list: [],
trust_list: [],
allow_orig: [],
block_orig: [],
trust_orig: [],
client_list: [],
load: function () {
return Promise.all([
uci.load('nodogsplash')
]).then(function(stat) {
return fs.exec_direct("/usr/bin/ndsctl", [ 'json' ]).catch(function(err) {
ui.addNotification(null, E('p', {}, err.message ));
return '';
});
});
},
ndsctl: function(group, div, cmd) {
var mac = div.previousSibling.getElementsByClassName('mac')[0].innerHTML;
var is_active = this.client_list[mac].state != null;
var no_un = cmd.replace(/un|de/, "");
fs.exec('/usr/bin/ndsctl', [ cmd, mac ]).then(function(res) {
ui.addNotification(null, E('p', [ res.stdout ]), res.code ? 'error' : 'success')
}).catch(function(err) {
ui.addNotification(null, E('p', [ err ]), 'error')
});
if (cmd != no_un)
{
group = group.filter( check => check != mac );
div.getElementsByClassName('cbi-un' + no_un + '-button')[0].classList.add("hidden");
div.getElementsByClassName('cbi-' + no_un + '-button')[0].classList.remove("hidden");
} else {
group = group.push(mac);
div.getElementsByClassName('cbi-' + no_un + '-button')[0].classList.add("hidden");
div.getElementsByClassName('cbi-un' + no_un + '-button')[0].classList.remove("hidden");
}
uci.set_first("nodogsplash", "nodogsplash", "trustedmac", group.length > 0 ? group : null);
},
trust_mac: function(elem, cmd) {
this.ndsctl(this.trust_orig, elem.currentTarget.parentNode, 'trust');
},
untrust_mac: function(elem, cmd) {
this.ndsctl(this.trust_orig, elem.currentTarget.parentNode, 'untrust');
},
allow_mac: function(elem, cmd) {
this.ndsctl(this.allow_orig, elem.currentTarget.parentNode, 'allow');
},
unallow_mac: function(elem, cmd) {
this.ndsctl(this.allow_orig, elem.currentTarget.parentNode, 'unallow');
},
block_mac: function(elem, cmd) {
this.ndsctl(this.allow_orig, elem.currentTarget.parentNode, 'block');
},
unblock_mac: function(elem, cmd) {
this.ndsctl(this.allow_orig, elem.currentTarget.parentNode, 'unblock');
},
auth_mac: function(elem, cmd) {
this.ndsctl(this.auth_orig, elem.currentTarget.parentNode, 'auth');
},
unauth_mac: function(elem, cmd) {
this.ndsctl(this.auth_orig, elem.currentTarget.parentNode, 'deauth');
},
render_button: function(txt, is_hidden) {
var cname = txt.toLowerCase();
return E('button', {
'class': 'cbi-button cbi-button-action cbi-' + cname + '-button cbi-' + cname.replace('un', '') + '-group' + (is_hidden ? ' hidden' : ''),
'click': ui.createHandlerFn(this, cname + '_mac')
}, _(txt + ' MAC'));
},
render_client: function(client) {
return E('tr', { 'class': 'tr mac-' + client.mac.replaceAll(":", "") }, [
E('td', { 'class': 'td left', 'style': 'width: 50%;' }, [
E('span', { style: 'font-size:medium;', class: 'mac' }, client.mac),
E('span', {}, client.ip != null ? ' (' + client.ip + ')' : ''),
E('ul', { style: "margin-left: 20px" }, [
E('li', { style: "list-style-type: circle;" }, [
E('span', { style: "font-weight:bold;" }, _("Client Status") + ": "),
E('span', {}, client.state != null ? _(client.state) : _('Disconnected'))
]),
client.state != null ? E('li', { style: "list-style-type: circle;" }, [
E('span', { style: "font-weight:bold;" }, _("Active Since") + ": "),
E('span', {}, new Date(client.active * 1000)),
]) : E('span', {})
]),
]),
E('td', { 'class': 'diag-action', 'style': 'width: 50%; vertical-align: top;' }, [
this.render_button('Trust', client.trusted),
this.render_button('Untrust', !client.trusted),
this.render_button('Allow', client.allowed || this.can_block),
this.render_button('Unallow', !client.allowed || this.can_block),
this.render_button('Block', client.blocked || !this.can_block),
this.render_button('Unblock', !client.blocked || !this.can_block),
])
]);
},
render_list: function(table, list) {
for (let i in list) {
// Render the client data:
var client = list[i].mac == null ? { mac: list[i] } : list[i];
var mac = client.mac = client.mac.toLowerCase();
client.trusted = this.trust_list.includes(mac);
client.allowed = this.allow_list.includes(mac);
client.blocked = this.block_list.includes(mac);
this.client_list[ mac ] = client;
table.appendChild( this.render_client( client ) );
// Remove the client from each of the mac lists:
this.trust_list = this.trust_list.filter( check => check != mac );
this.allow_list = this.allow_list.filter( check => check != mac );
this.block_list = this.block_list.filter( check => check != mac );
}
return table;
},
lowercase_list: function(table) {
for (let i in table)
table[i] = table[i].toLowerCase();
return table;
},
render: function(data) {
var m, s, o;
var sections = uci.sections('nodogsplash');
this.allow_orig = this.allow_list = this.lowercase_list( sections[0].allowedmac != null ? sections[0].allowedmac : [] );
this.block_orig = this.block_list = this.lowercase_list( sections[0].blockedmac != null ? sections[0].blockedmac : [] );
this.trust_orig = this.trust_list = this.lowercase_list( sections[0].trustedmac != null ? sections[0].trustedmac : [] );
this.can_block = sections[0].macmechanism == 'block';
// Process the current clients first, creating table for use later:
var table = E('table', { 'class': 'table mac-table' });
data = JSON.parse( (data == '' || data == null) ? '{"clients": {}}' : data );
this.render_list( table, data.clients );
// Process the trusted, allowed and blocked MAC address lists:
this.render_list( table, this.trust_list );
this.render_list( table, this.allow_list );
this.render_list( table, this.block_list );
// Actually render the page:
m = new form.Map('nodogsplash', _('MAC Mechanism'));
s = m.section(form.TypedSection, 'nodogsplash');
s.anonymous = true;
o = s.option(form.ListValue, 'macmechanism', _("MAC Access Mechanism"), _("MAC addresses that are / are not allowed to access the splash page"));
o.value('block', _("Block MACs"));
o.value('allow', _("Allow MACs"));
o.default = 'block';
o.rmempty = false;
o.editable = false;
s = m.section(form.TypedSection, 'nodogsplash', _('Clients'));
s.anonymous = true;
var ClientTable = form.DummyValue.extend({
renderWidget: function(section_id, option_index, cfgvalue) {
return table;
}
});
o = s.option(ClientTable);
return m.render();
}
});