mirror of
https://github.com/webmin/webmin.git
synced 2026-06-05 04:40:24 +01:00
Fix index page to implement view ACL better
This commit is contained in:
@@ -13,16 +13,19 @@ our $grub2_formno = 0;
|
||||
&error_setup($text{'acl_ecannot'});
|
||||
my %access = &grub2_effective_acl();
|
||||
&error("$text{'eacl_np'} $text{'eacl_pview'}")
|
||||
if (!&grub2_can_enter_module(\%access));
|
||||
if (!&can_use_index(\%access));
|
||||
|
||||
# Show configuration/install guidance before rendering module actions.
|
||||
if (!&grub2_any_installed()) {
|
||||
&ui_print_header(&grub2_version_text() || "", $text{'index_title'},
|
||||
"", undef, 1, 1);
|
||||
print &ui_alert($text{'index_missing'}, 'warning');
|
||||
foreach my $issue (&grub2_install_issues()) {
|
||||
print &ui_div(&text('index_missing_detail',
|
||||
&ui_tag('tt', &html_escape($issue))));
|
||||
if ($access{'view'}) {
|
||||
# Install issue details include discovered paths and commands.
|
||||
foreach my $issue (&grub2_install_issues()) {
|
||||
print &ui_div(&text('index_missing_detail',
|
||||
&ui_tag('tt', &html_escape($issue))));
|
||||
}
|
||||
}
|
||||
print &ui_p(&ui_link("@{[&get_webprefix()]}/config.cgi?$module_name",
|
||||
$text{'index_config_link'}));
|
||||
@@ -41,33 +44,47 @@ if (!&grub2_any_installed()) {
|
||||
&ui_print_header(&grub2_version_text() || "", $text{'index_title'}, "",
|
||||
undef, 1, 1, undef, &grub2_action_links(\%access));
|
||||
|
||||
foreach my $warning (&grub2_status_warnings()) {
|
||||
print &ui_alert($warning, 'warning');
|
||||
if ($access{'view'}) {
|
||||
foreach my $warning (&grub2_status_warnings()) {
|
||||
print &ui_alert($warning, 'warning');
|
||||
}
|
||||
|
||||
# Only the two entry lists are tabs; global settings live in separate pages.
|
||||
my @tabs = (
|
||||
[ 'entries', $text{'index_entries_tab'} ],
|
||||
[ 'custom', $text{'index_custom_tab'} ],
|
||||
);
|
||||
my %valid = map { $_->[0] => 1 } @tabs;
|
||||
my $requested = defined($in{'mode'}) ? $in{'mode'} : '';
|
||||
my $mode = $requested && $valid{$requested} ? $requested : 'entries';
|
||||
print &ui_tabs_start(\@tabs, "mode", $mode, 1);
|
||||
|
||||
print &ui_tabs_start_tab("mode", "entries");
|
||||
&print_entries_tab(\%access);
|
||||
print &ui_tabs_end_tab("mode", "entries");
|
||||
|
||||
print &ui_tabs_start_tab("mode", "custom");
|
||||
&print_custom_tab(\%access);
|
||||
print &ui_tabs_end_tab("mode", "custom");
|
||||
|
||||
print &ui_tabs_end();
|
||||
}
|
||||
|
||||
# Only the two entry lists are tabs; global settings live in separate pages.
|
||||
my @tabs = (
|
||||
[ 'entries', $text{'index_entries_tab'} ],
|
||||
[ 'custom', $text{'index_custom_tab'} ],
|
||||
);
|
||||
my %valid = map { $_->[0] => 1 } @tabs;
|
||||
my $requested = defined($in{'mode'}) ? $in{'mode'} : '';
|
||||
my $mode = $requested && $valid{$requested} ? $requested : 'entries';
|
||||
print &ui_tabs_start(\@tabs, "mode", $mode, 1);
|
||||
|
||||
print &ui_tabs_start_tab("mode", "entries");
|
||||
&print_entries_tab(\%access);
|
||||
print &ui_tabs_end_tab("mode", "entries");
|
||||
|
||||
print &ui_tabs_start_tab("mode", "custom");
|
||||
&print_custom_tab(\%access);
|
||||
print &ui_tabs_end_tab("mode", "custom");
|
||||
|
||||
print &ui_tabs_end();
|
||||
|
||||
&print_action_buttons(\%access);
|
||||
&ui_print_footer("/", $text{'index_return'});
|
||||
|
||||
# can_use_index(&access)
|
||||
# Returns true if the index can show entry data or a global action.
|
||||
sub can_use_index
|
||||
{
|
||||
my ($access) = @_;
|
||||
return 1 if ($access->{'view'});
|
||||
return 1 if ($access->{'edit'} || $access->{'security'} ||
|
||||
$access->{'manual'} || $access->{'install'});
|
||||
return 1 if ($access->{'apply'} && &grub2_command('mkconfig_cmd'));
|
||||
return 0;
|
||||
}
|
||||
|
||||
# print_entries_tab(&access)
|
||||
# Outputs generated boot menu entries and selected-entry runtime actions.
|
||||
sub print_entries_tab
|
||||
@@ -78,8 +95,10 @@ my $parsed = &read_grub_defaults();
|
||||
my %env = &grub2_read_env();
|
||||
# Selection roles are derived from both defaults and grubenv state.
|
||||
my %selection = &grub2_entry_selection_roles(\@entries, $parsed, \%env);
|
||||
my $can_default = $access->{'runtime'} && &grub2_command('set_default_cmd');
|
||||
my $can_once = $access->{'runtime'} && &grub2_command('reboot_once_cmd');
|
||||
my $can_default = $access->{'view'} && $access->{'runtime'} &&
|
||||
&grub2_command('set_default_cmd');
|
||||
my $can_once = $access->{'view'} && $access->{'runtime'} &&
|
||||
&grub2_command('reboot_once_cmd');
|
||||
my $show_actions = $can_default || $can_once;
|
||||
print &ui_div($text{'index_entries_desc'});
|
||||
if (!@entries) {
|
||||
@@ -230,7 +249,8 @@ if ($access->{'manual'}) {
|
||||
push(@icons, "images/manual.svg");
|
||||
}
|
||||
return if (!@links && !$can_status && !$can_generate);
|
||||
print &ui_hr();
|
||||
# Without view content, the action hub should start directly with actions.
|
||||
print &ui_hr() if ($access->{'view'});
|
||||
if (@links) {
|
||||
print &ui_subheading($text{'index_global'});
|
||||
&icons_table(\@links, \@titles, \@icons, scalar(@links) > 5 ? 5 :
|
||||
|
||||
@@ -153,6 +153,7 @@ my $save_defaults_source = slurp_test_file("$bindir/../save_defaults.cgi");
|
||||
my $theme_source = slurp_test_file("$bindir/../edit_theme.cgi");
|
||||
my $save_theme_source = slurp_test_file("$bindir/../save_theme.cgi");
|
||||
my $edit_install_source = slurp_test_file("$bindir/../edit_install.cgi");
|
||||
my $acl_source = slurp_test_file("$bindir/../acl_security.pl");
|
||||
unlike($index_source, qr/\[\s*'security'\s*,/,
|
||||
'index has no separate security tab');
|
||||
unlike($index_source, qr/\[\s*'defaults'\s*,/,
|
||||
@@ -167,9 +168,29 @@ my $status_source = slurp_test_file("$bindir/../status.cgi");
|
||||
like($index_source,
|
||||
qr/ui_print_header\(&grub2_version_text\(\) \|\| "".*?\$text\{'index_title'\}/s,
|
||||
'index header displays GRUB version text when available');
|
||||
like($index_source,
|
||||
qr/sub can_use_index\b.*?\$access->\{'view'\}.*?\$access->\{'edit'\}.*?\$access->\{'security'\}.*?\$access->\{'manual'\}.*?\$access->\{'install'\}.*?\$access->\{'apply'\} && &grub2_command\('mkconfig_cmd'\)/s,
|
||||
'index allows action-only ACLs without granting entry view');
|
||||
like($index_source,
|
||||
qr/if \(\$access\{'view'\}\) \{.*?grub2_install_issues/s,
|
||||
'index hides install issue details without view ACL');
|
||||
like($index_source,
|
||||
qr/if \(\$access\{'view'\}\) \{.*?grub2_status_warnings.*?ui_tabs_start/s,
|
||||
'index hides status warnings and entry tabs without view ACL');
|
||||
like($index_source,
|
||||
qr/my \$can_default = \$access->\{'view'\} && \$access->\{'runtime'\}/,
|
||||
'index runtime default actions require view ACL');
|
||||
like($index_source,
|
||||
qr/my \$can_once = \$access->\{'view'\} && \$access->\{'runtime'\}/,
|
||||
'index one-time boot actions require view ACL');
|
||||
like($index_source,
|
||||
qr/sub print_action_buttons\b.*?ui_buttons_row\("status\.cgi".*?ui_buttons_row\("generate\.cgi"/ms,
|
||||
'index exposes status above the bottom regenerate action');
|
||||
like($acl_source,
|
||||
qr/ui_table_row\(\$text\{'acl_view'\},\s*&ui_yesno_radio\("view"/s,
|
||||
'ACL view permission is rendered as a standalone row');
|
||||
unlike($acl_source, qr/acl_section_view/,
|
||||
'ACL view permission does not use a one-row section heading');
|
||||
like($status_source, qr/grub2_assert_acl\('view'\)/,
|
||||
'status page enforces view ACL directly');
|
||||
like($status_source, qr/index_boot_mode.*boot_mode_cell/s,
|
||||
@@ -357,6 +378,9 @@ like($edit_install_source, qr/install_boot_directory.*use_boot_directory/s,
|
||||
like($index_source,
|
||||
qr/sub print_action_buttons\b.*?&icons_table\(/ms,
|
||||
'index action shortcuts use an icon table');
|
||||
like($index_source,
|
||||
qr/sub print_action_buttons\b.*?print &ui_hr\(\) if \(\$access->\{'view'\}\)/ms,
|
||||
'index omits the top action separator for action-only ACLs');
|
||||
like($index_source,
|
||||
qr/sub print_action_buttons\b.*?ui_buttons_row\("generate\.cgi"/ms,
|
||||
'index exposes a bottom regenerate action button');
|
||||
|
||||
Reference in New Issue
Block a user