Merge pull request #5540 from jow-/wireguard-peer-gridsection

Implement nested grid section support and use it for wireguard peer config
This commit is contained in:
Jo-Philipp Wich 2021-12-02 10:54:36 +01:00 committed by GitHub
commit ff4f52983e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 27 deletions

View file

@ -2972,15 +2972,44 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
/** @private */
handleModalCancel: function(modalMap, ev) {
return Promise.resolve(ui.hideModal());
var prevNode = this.getPreviousModalMap();
if (prevNode) {
var heading = prevNode.parentNode.querySelector('h4');
prevNode.classList.add('flash');
prevNode.classList.remove('hidden');
prevNode.parentNode.removeChild(prevNode.nextElementSibling);
heading.removeChild(heading.lastElementChild);
if (!this.getPreviousModalMap())
prevNode.parentNode
.querySelector('div.right > button')
.firstChild.data = _('Dismiss');
}
else {
ui.hideModal();
}
return Promise.resolve();
},
/** @private */
handleModalSave: function(modalMap, ev) {
return modalMap.save(null, true)
.then(L.bind(this.map.load, this.map))
.then(L.bind(this.map.reset, this.map))
.then(ui.hideModal)
var mapNode = this.getActiveModalMap(),
activeMap = dom.findClassInstance(mapNode),
saveTasks = activeMap.save(null, true);
while (activeMap.parent) {
activeMap = activeMap.parent;
saveTasks = saveTasks
.then(L.bind(activeMap.load, activeMap))
.then(L.bind(activeMap.reset, activeMap));
}
return saveTasks
.then(L.bind(this.handleModalCancel, this, modalMap, ev))
.catch(function() {});
},
@ -3013,6 +3042,19 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
},
/** @private */
getActiveModalMap: function() {
return document.querySelector('body.modal-overlay-active > #modal_overlay > .modal.cbi-modal > .cbi-map:not(.hidden)');
},
/** @private */
getPreviousModalMap: function() {
var mapNode = this.getActiveModalMap(),
prevNode = mapNode ? mapNode.previousElementSibling : null;
return (prevNode && prevNode.matches('.cbi-map.hidden')) ? prevNode : null;
},
/** @private */
renderMoreOptionsModal: function(section_id, ev) {
var parent = this.map,
@ -3061,20 +3103,37 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
}
return Promise.resolve(this.addModalOptions(s, section_id, ev)).then(L.bind(m.render, m)).then(L.bind(function(nodes) {
ui.showModal(title, [
nodes,
E('div', { 'class': 'right' }, [
E('button', {
'class': 'cbi-button',
'click': ui.createHandlerFn(this, 'handleModalCancel', m)
}, [ _('Dismiss') ]), ' ',
E('button', {
'class': 'cbi-button cbi-button-positive important',
'click': ui.createHandlerFn(this, 'handleModalSave', m),
'disabled': m.readonly || null
}, [ _('Save') ])
])
], 'cbi-modal');
var modalMap = this.getActiveModalMap();
if (modalMap) {
modalMap.parentNode
.querySelector('h4')
.appendChild(E('span', title ? ' » ' + title : ''));
modalMap.parentNode
.querySelector('div.right > button')
.firstChild.data = _('Back');
modalMap.classList.add('hidden');
modalMap.parentNode.insertBefore(nodes, modalMap.nextElementSibling);
nodes.classList.add('flash');
}
else {
ui.showModal(title, [
nodes,
E('div', { 'class': 'right' }, [
E('button', {
'class': 'cbi-button',
'click': ui.createHandlerFn(this, 'handleModalCancel', m)
}, [ _('Dismiss') ]), ' ',
E('button', {
'class': 'cbi-button cbi-button-positive important',
'click': ui.createHandlerFn(this, 'handleModalSave', m),
'disabled': m.readonly || null
}, [ _('Save') ])
])
], 'cbi-modal');
}
}, this)).catch(L.error);
}
});
@ -3155,25 +3214,33 @@ var CBIGridSection = CBITableSection.extend(/** @lends LuCI.form.GridSection.pro
/** @private */
handleAdd: function(ev, name) {
var config_name = this.uciconfig || this.map.config,
section_id = this.map.data.add(config_name, this.sectiontype, name);
section_id = this.map.data.add(config_name, this.sectiontype, name),
mapNode = this.getPreviousModalMap(),
prevMap = mapNode ? dom.findClassInstance(mapNode) : this.map;
prevMap.addedSection = section_id;
this.addedSection = section_id;
return this.renderMoreOptionsModal(section_id);
},
/** @private */
handleModalSave: function(/* ... */) {
var mapNode = this.getPreviousModalMap(),
prevMap = mapNode ? dom.findClassInstance(mapNode) : this.map;
return this.super('handleModalSave', arguments)
.then(L.bind(function() { this.addedSection = null }, this));
.then(function() { delete prevMap.addedSection });
},
/** @private */
handleModalCancel: function(/* ... */) {
var config_name = this.uciconfig || this.map.config;
var config_name = this.uciconfig || this.map.config,
mapNode = this.getPreviousModalMap(),
prevMap = mapNode ? dom.findClassInstance(mapNode) : this.map;
if (this.addedSection != null) {
this.map.data.remove(config_name, this.addedSection);
this.addedSection = null;
if (prevMap.addedSection != null) {
this.map.data.remove(config_name, prevMap.addedSection);
delete prevMap.addedSection;
}
return this.super('handleModalCancel', arguments);

View file

@ -163,13 +163,15 @@ return network.registerProtocol('wireguard', {
}
catch(e) {}
o = s.taboption('peers', form.SectionValue, '_peers', form.TypedSection, 'wireguard_%s'.format(s.section));
o = s.taboption('peers', form.SectionValue, '_peers', form.GridSection, 'wireguard_%s'.format(s.section));
o.depends('proto', 'wireguard');
ss = o.subsection;
ss.anonymous = true;
ss.addremove = true;
ss.addbtntitle = _('Add peer');
ss.nodescriptions = true;
ss.modaltitle = _('Edit peer');
ss.renderSectionPlaceholder = function() {
return E([], [
@ -180,6 +182,7 @@ return network.registerProtocol('wireguard', {
o = ss.option(form.Flag, 'disabled', _('Peer disabled'), _('Enable / Disable peer. Restart wireguard interface to apply changes.'));
o.optional = true;
o.editable = true;
o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
o.placeholder = 'My Peer';
@ -187,6 +190,7 @@ return network.registerProtocol('wireguard', {
o.optional = true;
o = ss.option(form.Value, 'description', _('QR-Code'));
o.modalonly = true;
o.render = L.bind(function (view, section_id) {
var sections = uci.sections('network');
var client = findSection(sections, section_id);
@ -259,10 +263,12 @@ return network.registerProtocol('wireguard', {
}, this);
o = ss.option(form.Value, 'public_key', _('Public Key'), _('Required. Base64-encoded public key of peer.'));
o.modalonly = true;
o.validate = validateBase64;
o.rmempty = false;
o = ss.option(form.Value, 'preshared_key', _('Preshared Key'), _('Optional. Base64-encoded preshared key. Adds in an additional layer of symmetric-key cryptography for post-quantum resistance.'));
o.modalonly = true;
o.password = true;
o.validate = validateBase64;
o.optional = true;
@ -272,6 +278,7 @@ return network.registerProtocol('wireguard', {
o.optional = true;
o = ss.option(form.Flag, 'route_allowed_ips', _('Route Allowed IPs'), _('Optional. Create routes for Allowed IPs for this peer.'));
o.modalonly = true;
o = ss.option(form.Value, 'endpoint_host', _('Endpoint Host'), _('Optional. Host of peer. Names are resolved prior to bringing up the interface.'));
o.placeholder = 'vpn.example.com';
@ -282,6 +289,7 @@ return network.registerProtocol('wireguard', {
o.datatype = 'port';
o = ss.option(form.Value, 'persistent_keepalive', _('Persistent Keep Alive'), _('Optional. Seconds between keep alive messages. Default is 0 (disabled). Recommended value if this device is behind a NAT is 25.'));
o.modalonly = true;
o.datatype = 'range(0,65535)';
o.placeholder = '0';
},