os-firewall: add savepoint / revert actions including simple ui test calls

for https://github.com/opnsense/plugins/issues/1720
This commit is contained in:
Ad Schellevis
2020-03-10 15:17:52 +01:00
committed by Ad Schellevis
parent 8ab9605961
commit 9f7954b248
3 changed files with 110 additions and 0 deletions
@@ -29,6 +29,7 @@ namespace OPNsense\Firewall\Api;
use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
class FilterController extends ApiMutableModelControllerBase
{
@@ -73,4 +74,37 @@ class FilterController extends ApiMutableModelControllerBase
return array("status" => "error");
}
}
public function savepointAction()
{
if ($this->request->isPost()) {
// trigger a save, so we know revision->time matches our running config
Config::getInstance()->save();
return array(
"status" => "ok",
"retention" => (string)Config::getInstance()->backupCount(),
"revision" => (string)Config::getInstance()->object()->revision->time
);
} else {
return array("status" => "error");
}
}
public function revertAction($revision)
{
if ($this->request->isPost()) {
Config::getInstance()->lock();
$filename = Config::getInstance()->getBackupFilename($revision);
if (!$filename) {
Config::getInstance()->unlock();
return ["status" => gettext("unknown (or removed) savepoint")];
}
$this->getModel()->rollback($revision);
Config::getInstance()->unlock();
(new Backend())->configdRun('filter reload');
return ["status" => "ok"];
} else {
return array("status" => "error");
}
}
}
@@ -28,6 +28,7 @@
namespace OPNsense\Firewall;
use OPNsense\Core\Config;
use Phalcon\Validation\Message;
use OPNsense\Base\BaseModel;
use OPNsense\Firewall\Util;
@@ -82,4 +83,26 @@ class Filter extends BaseModel
}
return $messages;
}
/**
* Rollback this model to a previous version.
* Make sure to remove this object afterwards, since its contents won't be updated.
* @param $revision float|string revision number
*/
public function rollback($revision)
{
$filename = Config::getInstance()->getBackupFilename($revision);
if ($filename) {
// fiddle with the dom, copy OPNsense->Firewall->FilterRule from backup to current config
$sourcexml = simplexml_load_file($filename);
if ($sourcexml->OPNsense->Firewall->FilterRule) {
$sourcedom = dom_import_simplexml($sourcexml->OPNsense->Firewall->FilterRule);
$targetxml = Config::getInstance()->object();
$targetdom = dom_import_simplexml($targetxml->OPNsense->Firewall->FilterRule);
$node = $targetdom->ownerDocument->importNode($sourcedom, TRUE);
$targetdom->parentNode->replaceChild($node, $targetdom);
Config::getInstance()->save();
}
}
}
}
@@ -21,6 +21,47 @@
}
$("#reconfigureAct").SimpleActionButton();
$("#savepointAct").SimpleActionButton({
onAction: function(data, status){
stdDialogInform(
"{{ lang._('Savepoint created') }}",
data['revision'],
"{{ lang._('Close') }}"
);
}
});
$("#revertAction").on('click', function(){
BootstrapDialog.show({
type: BootstrapDialog.TYPE_DEFAULT,
title: "{{ lang._('Revert to savepoint') }}",
message: "<p>{{ lang._('Enter a savepoint to rollback to.') }}</p>" +
'<div class="form-group" style="display: block;">' +
'<input id="revertToTime" type="text" class="form-control"/>' +
'<span class="error text-danger" id="revertToTimeError"></span>'+
'</div>',
buttons: [{
label: "{{ lang._('Revert') }}",
cssClass: 'btn-primary',
action: function(dialogRef) {
ajaxCall("/api/firewall/filter/revert/" + $("#revertToTime").val(), {}, function (data, status) {
if (data.status !== "ok") {
$("#revertToTime").parent().addClass("has-error");
$("#revertToTimeError").html(data.status);
} else {
std_bootgrid_reload("grid-rules");
dialogRef.close();
}
});
}
}],
onshown: function(dialogRef) {
$("#revertToTime").parent().removeClass("has-error");
$("#revertToTimeError").html("");
$("#revertToTime").val("");
}
});
});
});
</script>
@@ -64,6 +105,18 @@
data-error-title="{{ lang._('Filter load error') }}"
type="button"
></button>
<div class="pull-right">
<button class="btn" id="savepointAct"
data-endpoint='/api/firewall/filter/savepoint'
data-label="{{ lang._('Savepoint') }}"
data-error-title="{{ lang._('snapshot error') }}"
type="button"
></button>
<button class="btn" id="revertAction">
{{ lang._('Revert') }}
</button>
</div>
<br/><br/>
</div>
</div>