=cut
-# XXX use get_user / get_group
# XXX make read_acl faster when we only care about one user
BEGIN { push(@INC, ".."); };
if ($proto eq "mysql" || $proto eq "postgresql") {
# Fetch users with SQL
my %userid;
- my $cmd = $dbh->prepare("select id,name,pass from webmin_user".
+ my $cmd = $dbh->prepare(
+ "select id,name,pass from webmin_user".
($only ? " where name in (".
join(",", map { "'$_'" } @$only).")" : ""));
$cmd && $cmd->execute() ||
return $user;
}
-=head2 list_groups
+=head2 list_groups([&only-groups])
Returns a list of hashes, one per Webmin group. Group membership is stored in
/etc/webmin/webmin.groups, and other attributes in the config file. Useful
=item modules - Modules to grant to members
+If the only-groups parameter is given, limit the list to just groups with
+those group names.
+
=cut
sub list_groups
{
+my ($only) = @_;
my @rv;
my %miniserv;
&get_miniserv_config(\%miniserv);
while(<GROUPS>) {
s/\r|\n//g;
local @g = split(/:/, $_);
- local $group = { 'name' => $g[0],
- 'members' => [ split(/\s+/, $g[1]) ],
- 'modules' => [ split(/\s+/, $g[2]) ],
- 'desc' => $g[3],
- 'ownmods' => [ split(/\s+/, $g[4]) ] };
- push(@rv, $group);
+ if (@g) {
+ next if ($only && &indexof($g[0], @$only) < 0);
+ local $group = { 'name' => $g[0],
+ 'members' => [ split(/\s+/, $g[1]) ],
+ 'modules' => [ split(/\s+/, $g[2]) ],
+ 'desc' => $g[3],
+ 'ownmods' => [ split(/\s+/, $g[4]) ] };
+ push(@rv, $group);
+ }
}
close(GROUPS);
# Fetch groups with SQL
my %groupid;
my $cmd = $dbh->prepare(
- "select id,name,description from webmin_group");
+ "select id,name,description from webmin_group ".
+ ($only ? " where name in (".
+ join(",", map { "'$_'" } @$only).")" : ""));
$cmd && $cmd->execute() ||
&error("Failed to query groups : ".$dbh->errstr);
while(my ($id, $name, $desc) = $cmd->fetchrow()) {
# Add group attributes
my $cmd = $dbh->prepare(
- "select id,attr,value from webmin_group_attr");
+ "select id,attr,value from webmin_group_attr ".
+ ($only && %userid ?
+ " where id in (".join(",", keys %userid).")" : ""));
$cmd && $cmd->execute() ||
&error("Failed to query group attrs : ".$dbh->errstr);
while(my ($id, $attr, $value) = $cmd->fetchrow()) {
}
elsif ($proto eq "ldap") {
# Find groups with LDAP query
+ my $filter = '(objectClass='.$args->{'groupclass'}.')';
+ if ($only) {
+ my $gfilter =
+ "(|".join("", map { "(cn=$_)" } @$only).")";
+ $filter = "(&".$filter.$gfilter.")";
+ }
my $rv = $dbh->search(
base => $prefix,
- filter => '(objectClass='.$args->{'groupclass'}.')',
+ filter => $filter,
scope => 'sub');
if (!$rv || $rv->code) {
&error("Failed to search groups : ".
if ($in{'group'}) {
# Editing an existing group
&ui_print_header(undef, $text{'gedit_title'}, "");
- foreach $g (&list_groups()) {
- if ($g->{'name'} eq $in{'group'}) {
- %group = %$g;
- }
- }
+ $g = &get_group($in{'group'});
+ $g || &error($text{'gedit_egone'});
+ %group = %$g;
}
else {
# Creating a new group
&ui_print_header(undef, $text{'gedit_title2'}, "");
- foreach $g (&list_groups()) {
- if ($g->{'name'} eq $in{'clone'}) {
+ %group = ( );
+ if ($in{'clone'}) {
+ # Copy modules from clone
+ $g = &get_group($in{'clone'});
+ if ($g) {
$group{'modules'} = $g->{'modules'};
}
}
# Show the group name
print &ui_table_row($text{'gedit_group'},
- &ui_textbox("name", $group{'name'}, 30));
+ &ui_textbox("name", $group{'name'}, 30, 0, undef, "autocomplete=off"));
# Show group description
print &ui_table_row($text{'gedit_desc'},
%user = %$u;
delete($user{'name'});
}
+ else {
+ %user = ( );
+ }
$user{'skill'} = $user{'risk'} = 'high' if ($in{'risk'});
}
$me = &get_user($base_remote_user);
# Username
print &ui_table_row($text{'edit_user'},
$access{'rename'} || !$in{'user'} ?
- &ui_textbox("name", $user{'name'}, 30) : $user{'name'});
+ &ui_textbox("name", $user{'name'}, 30,
+ 0, undef, "autocomplete=off") : $user{'name'});
# Source user for clone
if ($in{'clone'}) {
}
print &ui_table_row($text{'edit_pass'},
&ui_select("pass_def", $passmode, \@opts)." ".
- &ui_password("pass", undef, 25).
+ &ui_password("pass", undef, 25, 0, undef, "autocomplete=off").
($lockbox || $tempbox ? "<br>" : "").$lockbox.$tempbox.$expmsg);
# Real name
gedit_modules=Members' modules
gedit_members=Member users and groups
gedit_desc=Group description
+gedit_egone=Selected group no longer exists!
gdelete_err=Failed to delete group
gdelete_ecannot=You are not allowed to delete groups
exit;
}
-@glist = &list_groups();
-@ulist = &list_users();
if ($in{'old'}) {
+ # Get the original group
%group = ( );
- foreach $g (@glist) {
- $old = $g if ($g->{'name'} eq $in{'old'});
- }
+ $old = &get_group($in{'old'});
+ $old || &error($text{'gedit_egone'});
$group{'members'} = $old->{'members'};
$group{'proto'} = $old->{'proto'};
$group{'id'} = $old->{'id'};
&error(&text('gsave_ename', $in{'name'}));
$in{'name'} eq 'webmin' && &error($text{'gsave_enamewebmin'});
if (!$in{'old'} || $in{'old'} ne $in{'name'}) {
- foreach $g (@glist) {
- if ($g->{'name'} eq $in{'name'}) {
- &error(&text('gsave_edup', $in{'name'}));
- }
- }
+ $clash = &get_group($in{'name'});
+ $clash && &error(&text('gsave_edup', $in{'name'}));
}
$in{'desc'} !~ /:/ || &error($text{'gsave_edesc'});
-# Find the current group
+# Find the current parent group
if ($in{'old'}) {
foreach $g (&list_groups()) {
if (&indexof('@'.$in{'old'}, @{$g->{'members'}}) >= 0) {
}
# Store parent group membership
- @glist = &list_groups();
- ($group) = grep { $_->{'name'} eq $in{'group'} } @glist;
+ $newgroup = &get_group($in{'group'});
if ($in{'group'} ne ($oldgroup ? $oldgroup->{'name'} : '')) {
# Group has changed - update the member lists
if ($oldgroup) {
@{$oldgroup->{'members'}} ];
&modify_group($oldgroup->{'name'}, $oldgroup);
}
- if ($group) {
- push(@{$group->{'members'}}, '@'.$in{'name'});
- &modify_group($in{'group'}, $group);
+ if ($newgroup) {
+ push(@{$newgroup->{'members'}}, '@'.$in{'name'});
+ &modify_group($in{'group'}, $newgroup);
}
}
}
@mods = grep { &indexof($_, @{$oldgroup->{'modules'}}) < 0 } @mods;
}
-if ($group) {
+if ($newgroup) {
# Add modules from parent group to list
local @ownmods;
foreach $m (@mods) {
push(@ownmods, $m)
- if (&indexof($m, @{$group->{'modules'}}) < 0);
+ if (&indexof($m, @{$newgroup->{'modules'}}) < 0);
}
- @mods = &unique(@mods, @{$group->{'modules'}});
+ @mods = &unique(@mods, @{$newgroup->{'modules'}});
$group{'ownmods'} = \@ownmods;
# Copy ACL files for parent group
local $name = $in{'old'} ? $in{'old'} : $in{'name'};
©_group_acl_files($in{'group'}, $name,
- [ @{$group->{'modules'}}, "" ]);
+ [ @{$newgroup->{'modules'}}, "" ]);
}
# Store group options
&modify_group($in{'old'}, \%group);
# recursively update all member users and groups
+ @glist = &list_groups();
+ @ulist = &list_users();
&update_members(\@ulist, \@glist, $group{'modules'},
$old->{'members'});
}
}
# Store group membership
- @glist = &list_groups();
- ($group) = grep { $_->{'name'} eq $in{'group'} } @glist;
+ $newgroup = &get_group($in{'group'});
if ($in{'group'} ne ($oldgroup ? $oldgroup->{'name'} : '')) {
# Group has changed - update the member lists
if ($oldgroup) {
@{$oldgroup->{'members'}} ];
&modify_group($oldgroup->{'name'}, $oldgroup);
}
- if ($group) {
+ if ($newgroup) {
# Put into new
- push(@{$group->{'members'}}, $in{'name'});
- &modify_group($in{'group'}, $group);
+ push(@{$newgroup->{'members'}}, $in{'name'});
+ &modify_group($in{'group'}, $newgroup);
}
}
- elsif ($in{'old'} ne $in{'name'} && $oldgroup && $group) {
+ elsif ($in{'old'} ne $in{'name'} && $oldgroup && $newgroup) {
# Name has changed - rename in group
local $idx = &indexof(
$in{'old'}, @{$oldgroup->{'members'}});
}
if ($base_remote_user eq $in{'old'} &&
&indexof("acl", @mods) == -1 &&
- (!$group || &indexof("acl", @{$group->{'modules'}}) == -1)) {
+ (!$newgroup || &indexof("acl", @{$newgroup->{'modules'}}) == -1)) {
&error($text{'save_edeny'});
}
©_acl_files($me->{'name'}, $in{'name'}, $me->{'modules'});
}
- if ($group) {
+ if ($newgroup) {
# Add modules from group to list
local @ownmods;
foreach $m (@mods) {
push(@ownmods, $m)
- if (&indexof($m, @{$group->{'modules'}}) < 0);
+ if (&indexof($m, @{$newgroup->{'modules'}}) < 0);
}
- @mods = &unique(@mods, @{$group->{'modules'}});
+ @mods = &unique(@mods, @{$newgroup->{'modules'}});
$user{'ownmods'} = \@ownmods;
# Copy ACL files for group
local $name = $in{'old'} ? $in{'old'} : $in{'name'};
©_group_user_acl_files($in{'group'}, $name,
- [ @{$group->{'modules'}}, "" ]);
+ [ @{$newgroup->{'modules'}}, "" ]);
}
$user{'modules'} = \@mods;
delete($user{'skill'});
}
}
-if ($in{'old'} && $in{'acl_security_form'} && !$group) {
+if ($in{'old'} && $in{'acl_security_form'} && !$newgroup) {
# Update user's global ACL
&foreign_require("", "acl_security.pl");
&foreign_call("", "acl_security_save", \%uaccess, \%in);