%PDF- %PDF-
| Direktori : /backups/router/usr/local/opnsense/mvc/app/views/OPNsense/Core/ |
| Current File : //backups/router/usr/local/opnsense/mvc/app/views/OPNsense/Core/backup_history.volt |
{#
# Copyright (c) 2023 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#}
<style>
.diff_record {
white-space: pre-wrap;
font-family: monospace;
border: none !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
word-break: break-all;
}
</style>
<script>
'use strict';
function get_backups(){
let provider = $("#providers").val();
$("#host_processing").show();
ajaxGet('/api/core/backup/backups/' + provider, {}, function(data, status){
let target1 = $("#backups1").empty();
let target2 = $("#backups2").empty();
if (data.items && Object.keys(data.items).length > 1) {
Object.keys(data.items).forEach(function(key) {
let record = data.items[key];
let payload = $("<div>");
payload.append(record.time_iso, " ", record.username, "<br/>");
payload.append($("<small/>").text(record.description));
target1.append($("<option/>").attr('value', record.id).attr('data-content', payload.html()));
target2.append($("<option/>").attr('value', record.id).attr('data-content', payload.html()));
});
}
$(".backups").selectpicker('refresh');
$("#backups1").change();
$("#host_processing").hide();
if ($("#backups1 option").length === 0) {
$("#diff_tfoot").show();
} else {
$("#diff_tfoot").hide();
}
});
if (provider === 'this' ) {
$(".only_local").show();
} else {
$(".only_local").hide();
}
}
$( document ).ready(function () {
ajaxGet('/api/core/backup/providers', {}, function(data, status){
let selected_host = "{{selected_host}}";
if (data.items && Object.keys(data.items).length > 1) {
let target = $("#providers").empty();
Object.keys(data.items).forEach(function(key) {
let opt = $("<option/>").attr('value', key).text(data.items[key].description);
if (selected_host == key) {
opt.attr('selected', 'selected');
}
target.append(opt);
});
target.selectpicker('refresh');
}
$("#providers").change(get_backups);
$("#providers").change();
if ($("#providers > option").length > 1) {
$("#providers_pane").show();
}
});
$("#backups1").change(function(){
let target = $("#backups2");
target.val($("#backups1").val());
if ($('#backups2 option').length > target[0].selectedIndex) {
target[0].selectedIndex = target[0].selectedIndex + 1;
}
target.selectpicker('refresh');
target.change();
});
$("#backups2").change(function(){
let provider = $("#providers").val();
let url = '/api/core/backup/diff/'+provider+'/'+$("#backups1").val()+'/'+$("#backups2").val();
ajaxGet(url, {}, function(data, status){
let target = $("#diff_records").empty();
if (data.items && data.items.length > 1) {
for (let i=0 ; i < data.items.length ; ++i) {
let $tr = $("<tr/>");
let $td = $("<td class='diff_record'/>").append($("<div>").html(data.items[i]).text());
let color = '#000000';
switch (data.items[i][0]) {
case '+':
color = '#3bbb33';
$td.addClass('diff_record_plus');
break;
case '-':
color = '#c13928';
$td.addClass('diff_record_minus');
break;
case '@':
color = '#3bb9c3';
$td.addClass('diff_record_at');
break;
default:
$td.addClass('diff_record_default');
break;
}
$td.css('color', color);
target.append($tr.append($td));
}
}
});
});
$("#act_revert").click(function(event){
event.preventDefault();
if (!$("#backups1").val()) {
return;
}
BootstrapDialog.show({
type: BootstrapDialog.TYPE_WARNING,
title: "{{ lang._('Confirmation required') }}",
message: "{{ lang._('Restore from Configuration Backup') }} <br/>" + $("#backups1 option:selected").data('content'),
buttons: [{
label: "{{ lang._('No') }}",
action: function(dialogRef) {
dialogRef.close();
}}, {
label: "{{ lang._('Yes') }}",
cssClass: 'btn-warning',
action: function(dialogRef) {
ajaxCall("/api/core/backup/revert_backup/" + $("#backups1").val(),{}, function(){
dialogRef.close();
get_backups();
});
}
}]
});
});
$("#act_remove").click(function(event){
event.preventDefault();
if (!$("#backups1").val()) {
return;
}
BootstrapDialog.show({
type: BootstrapDialog.TYPE_WARNING,
title: "{{ lang._('Confirmation required') }}",
message: "{{ lang._('Remove Configuration Backup') }} <br/>" + $("#backups1 option:selected").data('content'),
buttons: [{
label: "{{ lang._('No') }}",
action: function(dialogRef) {
dialogRef.close();
}}, {
label: "{{ lang._('Yes') }}",
cssClass: 'btn-warning',
action: function(dialogRef) {
ajaxCall("/api/core/backup/delete_backup/" + $("#backups1").val(),{}, function(){
$(".backups").find('[value="'+$("#backups1").val()+'"]').remove();
$("#backups1").selectpicker('refresh');
$("#backups1").change();
dialogRef.close();
});
}
}]
});
});
$("#act_download").click(function(event){
event.preventDefault();
if (!$("#backups1").val()) {
return;
}
let url = '/api/core/backup/download/' + $("#providers").val() + '/' + $("#backups1").val();
let link = document.createElement("a");
$(link).click(function(e) {
e.preventDefault();
window.location.href = url;
});
$(link).click();
});
});
</script>
<div class="tab-content content-box __mb" id="providers_pane" style="display: none;">
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>{{ lang._('Host')}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select id="providers" class="selectpicker">
<option value="this" selected>{{ lang._('This Firewall')}}</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-content content-box __mb">
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>
{{ lang._('Backups (compare)')}}
<i id="host_processing" class="fa fa-fw fa-spinner fa-pulse" style="display: none;"></i>
</th>
</tr>
</thead>
<tbody>
<tr style="height: 70px;">
<td>
<select class="selectpicker backups" id="backups1"></select>
<select class="selectpicker backups" id="backups2"></select>
<div>
<a id="act_revert" class="only_local btn btn-default btn-xs" data-toggle="tooltip" title="{{ lang._('Revert to this configuration')}}">
<i class="fa fa-sign-in fa-fw"></i>
</a>
<a id="act_remove" class="only_local btn btn-default btn-xs" data-toggle="tooltip" title="{{ lang._('Remove this backup')}}">
<i class="fa fa-trash fa-fw"></i>
</a>
<a id="act_download" class="btn btn-default btn-xs" data-toggle="tooltip" title="{{ lang._('Download this backup')}}">
<i class="fa fa-download fa-fw"></i>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-content content-box">
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed">
<thead>
<tr>
<th >{{ lang._('Changes between selected versions')}}</th>
</tr>
</thead>
<tbody id="diff_records">
</tbody>
<tfoot id="diff_tfoot" style="display: none;">
<tr>
<td>{{ lang._('No backups available')}}</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>