mirror of
https://github.com/webmin/webmin.git
synced 2026-05-06 15:20:29 +01:00
Add nftables apply-needed header action
* Note: Track saved nftables configuration changes with Apache-style config/apply timestamp flags, expose the standard restart.cgi header action for themes, and use it as the single apply endpoint. The button expands to “Apply Changes” when saved rules need applying, while the existing Apply Configuration action now routes through restart.cgi and clears the pending state after a successful apply.
This commit is contained in:
@@ -7,7 +7,8 @@ use strict;
|
||||
use warnings;
|
||||
our (%text);
|
||||
|
||||
ui_print_header(undef, $text{'active_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'active_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
|
||||
my ($tables, $err) = get_active_nftables_save();
|
||||
if ($err) {
|
||||
|
||||
@@ -24,7 +24,8 @@ my @saved_tables = get_nftables_save();
|
||||
my $status_key = active_table_status($table, \@saved_tables);
|
||||
my $is_saved = table_is_webmin_managed($table, \@saved_tables);
|
||||
|
||||
ui_print_header(undef, $text{'active_table_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'active_table_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
|
||||
print ui_table_start($text{'active_table_summary'}, "width=100%", 2);
|
||||
print ui_table_row($text{'active_table'}, html_escape(nft_table_spec($table)));
|
||||
|
||||
@@ -30,7 +30,8 @@ if ($in{'confirm'}) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_print_header(undef, $text{'clear_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'clear_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
print "<center>\n";
|
||||
print ui_form_start("clear_table.cgi");
|
||||
print ui_hidden("family", $table->{'family'});
|
||||
|
||||
@@ -50,7 +50,8 @@ if ($in{'create'}) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_print_header(undef, $text{'create_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'create_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
print ui_form_start("create_table.cgi");
|
||||
print ui_hidden("create", 1);
|
||||
|
||||
|
||||
@@ -29,18 +29,21 @@ else {
|
||||
$table || error($text{'delete_notable'});
|
||||
|
||||
if ($in{'confirm'}) {
|
||||
my $needs_apply = needs_config_restart();
|
||||
splice(@tables, $table_idx, 1);
|
||||
my $err = delete_table_configuration($table, @tables);
|
||||
error(text('delete_failed', $err)) if ($err);
|
||||
$err = delete_active_table($table);
|
||||
error(text('delete_failed', $err)) if ($err);
|
||||
restart_last_restart_time() if (!$needs_apply);
|
||||
webmin_log("delete", "table", $table->{'name'},
|
||||
{ 'family' => $table->{'family'} });
|
||||
redirect("index.cgi");
|
||||
return;
|
||||
}
|
||||
|
||||
ui_print_header(undef, $text{'delete_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'delete_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
print "<center>\n";
|
||||
print ui_form_start("delete_table.cgi");
|
||||
print ui_hidden("table", $table_idx);
|
||||
|
||||
@@ -17,12 +17,14 @@ my $chain_name = "";
|
||||
my $is_new = $in{'new'} ? 1 : 0;
|
||||
|
||||
if ($is_new) {
|
||||
ui_print_header(undef, $text{'chain_title_new'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'chain_title_new'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
} else {
|
||||
$chain_name = $in{'chain'};
|
||||
$chain = $table->{'chains'}->{$chain_name};
|
||||
$chain || error($text{'chain_nochain'});
|
||||
ui_print_header(undef, $text{'chain_title_edit'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'chain_title_edit'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
}
|
||||
|
||||
my @type_opts = (
|
||||
@@ -84,4 +86,3 @@ if (window.addEventListener) {
|
||||
EOF
|
||||
|
||||
ui_print_footer("index.cgi?table=$in{'table'}", $text{'index_return'});
|
||||
|
||||
|
||||
@@ -47,10 +47,12 @@ sub split_multi_value
|
||||
}
|
||||
|
||||
if ($in{'new'}) {
|
||||
ui_print_header(undef, $text{'edit_title_new'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'edit_title_new'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
$rule = { 'chain' => $in{'chain'} };
|
||||
} else {
|
||||
ui_print_header(undef, $text{'edit_title_edit'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'edit_title_edit'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
$rule = $table->{'rules'}->[$in{'idx'}];
|
||||
}
|
||||
if ($table && $rule->{'chain'}) {
|
||||
|
||||
@@ -17,13 +17,15 @@ my $set_name = "";
|
||||
my $is_new = $in{'new'} ? 1 : 0;
|
||||
|
||||
if ($is_new) {
|
||||
ui_print_header(undef, $text{'set_title_new'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'set_title_new'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
}
|
||||
else {
|
||||
$set_name = $in{'set'};
|
||||
$set = $table->{'sets'}->{$set_name};
|
||||
$set || error($text{'set_noset'});
|
||||
ui_print_header(undef, $text{'set_title_edit'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'set_title_edit'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
}
|
||||
|
||||
my $elements_text = set_elements_text($set);
|
||||
|
||||
@@ -60,7 +60,8 @@ if ($in{'import'}) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_print_header(undef, $text{'import_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'import_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
|
||||
print ui_form_start("import_table.cgi");
|
||||
print ui_hidden("family", $source->{'family'});
|
||||
|
||||
@@ -9,7 +9,8 @@ our (%in, %text, %config);
|
||||
ReadParse();
|
||||
my $partial = $in{'partial'};
|
||||
if (!$partial) {
|
||||
ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
}
|
||||
|
||||
# Check for nft command
|
||||
@@ -279,7 +280,7 @@ print $rules_html;
|
||||
if (@tables) {
|
||||
print ui_hr();
|
||||
print ui_buttons_start();
|
||||
print ui_buttons_row("apply.cgi", $text{'index_apply'}, $text{'index_applydesc'});
|
||||
print ui_buttons_row("restart.cgi", $text{'index_apply'}, $text{'index_applydesc'});
|
||||
print ui_buttons_row("active.cgi", $text{'index_active'}, $text{'index_activedesc'});
|
||||
print ui_buttons_row("setup.cgi", $text{'index_setup'}, $text{'index_setupdesc'});
|
||||
print ui_buttons_end();
|
||||
|
||||
@@ -50,6 +50,7 @@ index_cdeletesel=Delete Selected Chains
|
||||
index_cmovesel=Move Selected
|
||||
index_radd=Add Rule
|
||||
index_apply=Apply Configuration
|
||||
index_apply_changes=Apply Changes
|
||||
index_applydesc=Click this button to replace the saved Webmin-managed tables in the active nftables ruleset.
|
||||
index_active=View Active Ruleset
|
||||
index_activedesc=View active nftables tables and import copies into Webmin's saved configuration.
|
||||
|
||||
@@ -5,8 +5,63 @@ BEGIN { push(@INC, ".."); }; ## no critic
|
||||
use WebminCore;
|
||||
use strict;
|
||||
use warnings;
|
||||
our (%config, $module_config_directory);
|
||||
our (%config, $module_config_directory, $module_var_directory);
|
||||
our ($last_config_change_flag, $last_restart_time_flag);
|
||||
init_config();
|
||||
$last_config_change_flag = $module_var_directory."/config-flag";
|
||||
$last_restart_time_flag = $module_var_directory."/restart-flag";
|
||||
|
||||
# restart_button()
|
||||
# Returns HTML for the header apply button
|
||||
sub restart_button
|
||||
{
|
||||
my @tables = get_nftables_save();
|
||||
return "" if (!@tables);
|
||||
my $args = "redir=".urlize(this_url());
|
||||
my $needs = needs_config_restart();
|
||||
my $apply = text('index_apply_changes');
|
||||
my $label = $needs ? "<b>$apply</b>" : $apply;
|
||||
my $url = "restart.cgi?$args";
|
||||
$url .= "&newconfig=1" if ($needs);
|
||||
return ui_link($url, $label);
|
||||
}
|
||||
|
||||
# this_url()
|
||||
# Returns the URL in the nftables module for the current script
|
||||
sub this_url
|
||||
{
|
||||
my $url = $ENV{'SCRIPT_NAME'} || "";
|
||||
my $query = $ENV{'QUERY_STRING'} || "";
|
||||
$url .= "?$query" if ($query ne "");
|
||||
return $url;
|
||||
}
|
||||
|
||||
# update_last_config_change()
|
||||
# Updates the flag file indicating when the saved config was changed
|
||||
sub update_last_config_change
|
||||
{
|
||||
open_tempfile(my $fh, ">$last_config_change_flag", 0, 1);
|
||||
close_tempfile($fh);
|
||||
}
|
||||
|
||||
# restart_last_restart_time()
|
||||
# Updates the flag file indicating when the saved config was applied
|
||||
sub restart_last_restart_time
|
||||
{
|
||||
open_tempfile(my $fh, ">$last_restart_time_flag", 0, 1);
|
||||
close_tempfile($fh);
|
||||
}
|
||||
|
||||
# needs_config_restart()
|
||||
# Returns 1 if saved config changes still need to be applied
|
||||
sub needs_config_restart
|
||||
{
|
||||
my @cst = stat($last_config_change_flag);
|
||||
my @rst = stat($last_restart_time_flag);
|
||||
return 0 if (!@cst);
|
||||
return 1 if (!@rst);
|
||||
return $cst[9] > $rst[9] ? 1 : 0;
|
||||
}
|
||||
|
||||
# get_nft_command()
|
||||
# Returns the configured nft command path, or finds it in PATH
|
||||
@@ -1198,6 +1253,7 @@ open_tempfile(my $fh, ">$file");
|
||||
print_tempfile($fh, $out);
|
||||
close_tempfile($fh);
|
||||
sync_managed_metadata(@tables);
|
||||
update_last_config_change();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1294,6 +1350,7 @@ unlink_file($tmp);
|
||||
if ($?) {
|
||||
return "<pre>$out</pre>";
|
||||
}
|
||||
restart_last_restart_time();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ $table || error($text{'chain_notable'});
|
||||
my $chain = $table->{'chains'}->{$in{'chain'}};
|
||||
$chain || error($text{'chain_nochain'});
|
||||
|
||||
ui_print_header(undef, $text{'rename_chain_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'rename_chain_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
print ui_form_start("save_chain.cgi");
|
||||
print ui_hidden("table", $in{'table'});
|
||||
print ui_hidden("rename", 1);
|
||||
@@ -30,4 +31,3 @@ print ui_table_end();
|
||||
|
||||
print ui_form_end([ [ undef, $text{'rename_chain_ok'} ] ]);
|
||||
ui_print_footer("index.cgi?table=$in{'table'}", $text{'index_return'});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/perl
|
||||
# apply.cgi
|
||||
# Apply the current configuration
|
||||
# restart.cgi
|
||||
# Apply saved nftables configuration from the header action
|
||||
|
||||
require './nftables-lib.pl'; ## no critic
|
||||
use strict;
|
||||
@@ -12,4 +12,5 @@ error_setup($text{'apply_err'});
|
||||
my $err = apply_restore();
|
||||
error($err) if ($err);
|
||||
|
||||
redirect("index.cgi");
|
||||
webmin_log("apply");
|
||||
redirect($in{'redir'} || "index.cgi");
|
||||
@@ -47,7 +47,8 @@ if ($in{'action'} eq 'create') {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_print_header(undef, $text{'setup_title'}, "", "intro", 1, 1);
|
||||
ui_print_header(undef, $text{'setup_title'}, "", "intro", 1, 1,
|
||||
undef, restart_button());
|
||||
|
||||
print ui_form_start("setup.cgi");
|
||||
print ui_hidden("action", "create");
|
||||
|
||||
Reference in New Issue
Block a user