luci-base: uci.js: prevent sending empty uci set operations

Under certain circumstances, a staged uci option value might get unset
again before saving the config, leaving an empty section change set
behind, causing the save call to send an empty uci set request via rpc,
triggering an ubus code 4 (Resource not found) error.

In particular this prevented bridge VLANs from getting saved properly.

Fixes: #5876
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2022-07-23 00:10:17 +02:00
parent 2771360108
commit 25dcd0b77c

View file

@ -2,6 +2,14 @@
'require rpc'; 'require rpc';
'require baseclass'; 'require baseclass';
function isEmpty(object, ignore) {
for (var property in object)
if (object.hasOwnProperty(property) && property != ignore)
return false;
return true;
}
/** /**
* @class uci * @class uci
* @memberof LuCI * @memberof LuCI
@ -570,16 +578,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
/* undelete option */ /* undelete option */
if (d[conf] && d[conf][sid]) { if (d[conf] && d[conf][sid]) {
var empty = true; if (isEmpty(d[conf][sid], opt))
for (var key in d[conf][sid]) {
if (key != opt && d[conf][sid].hasOwnProperty(key)) {
empty = false;
break;
}
}
if (empty)
delete d[conf][sid]; delete d[conf][sid];
else else
delete d[conf][sid][opt]; delete d[conf][sid][opt];
@ -589,8 +588,12 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
} }
else { else {
/* revert any change for to-be-deleted option */ /* revert any change for to-be-deleted option */
if (c[conf] && c[conf][sid]) if (c[conf] && c[conf][sid]) {
if (isEmpty(c[conf][sid], opt))
delete c[conf][sid];
else
delete c[conf][sid][opt]; delete c[conf][sid][opt];
}
/* only delete existing options */ /* only delete existing options */
if (v[conf] && v[conf][sid] && v[conf][sid].hasOwnProperty(opt)) { if (v[conf] && v[conf][sid] && v[conf][sid].hasOwnProperty(opt)) {