Users using the Tequila login are invited to migrate to gitlab.epfl.ch. This instance will close for Tequila users by May 2020.

Commit 2258a0cd authored by Florian Vessaz's avatar Florian Vessaz

Fix member creation

parent 665e80c6
......@@ -50,7 +50,7 @@ sub new {
base => GnuGeneration::LDAP->groups_base,
filter => "(&(objectclass=posixGroup)"
. "(cn=" . escape_filter_value($group_name) . "))",
attrs => ['memberUid']
attrs => ['cn', 'memberUid']
);
if ($mesg->code) {
......@@ -67,6 +67,7 @@ sub new {
}
return unless @usernames;
$self->{usernames} = \@usernames;
$self->{dn} = decode('UTF-8', $entry->dn);
} else {
# No group with the given name exists.
return;
......@@ -115,4 +116,78 @@ sub contains {
return grep {$_ eq $user} @{$self->{usernames}};
}
=head2 Add/remove members
C<< $group->add($user) >>
C<< $group->add(\@users) >>
Add the given username, GnuGeneration::Member to the group.
It also accepts a reference to a list to add multiple users at the same time.
C<< $group->remove($user) >>
C<< $group->remove(\@users) >>
Remove the given username or GnuGeneration::Member from the group.
It also acceptis a reference to a list to remove multiple users at the same
time.
=cut
sub _get_username {
my $arg = shift;
my $what = ref($arg);
if ($what eq 'GnuGeneration::Member') {
return $arg->username;
} elsif ($what) {
warn "Argument cannot be converted to a username: ",
($arg // "undenifed");
return;
} else {
return $arg;
}
}
sub _get_usernames {
my $arg = shift;
if (ref($arg) eq 'ARRAY') {
my @list;
foreach my $x (@{$arg}) {
my $username = _get_username($_);
return unless (defined $username);
push @list, $username;
}
return \@list;
} else {
my $username = _get_username($arg);
return unless (defined $username);
return [$username];
}
}
sub add {
my ($self, $new_members) = @_;
die "Missing argument" unless defined $new_members;
use Data::Dumper;
my $usernames = _get_usernames($new_members);
return unless (defined $usernames);
my $ldap = GnuGeneration::LDAP->ldap;
my $mesg = $ldap->modify($self->{dn},
add => {'memberUid' => $usernames},
);
if ($mesg->is_error) {
warn "Couldn't add members to group: ", $mesg->error;
return;
}
return 1;
}
sub remove {
my ($self, $members) = @_;
die "Missing argument" unless defined $members;
my $usernames = _get_usernames($members);
return unless (defined $usernames);
my $ldap = GnuGeneration::LDAP->ldap;
my $mesg = $ldap->modify($self->{dn},
delete => {'memberUid' => $usernames},
);
}
1;
......@@ -7,7 +7,7 @@ use Digest::SHA;
use Encode qw(decode);
use MIME::Base64;
use Net::LDAP qw(LDAP_SUCCESS);
use Net::LDAP::Util qw(escape_filter_value);
use Net::LDAP::Util qw(escape_filter_value escape_dn_value);
use POSIX;
use GnuGeneration::LDAP;
......@@ -145,7 +145,7 @@ sub all_members {
my $res = $ldap->search(
base => $GnuGeneration::LDAP::USERS_BASE,
filter => "(objectclass=gnugenMember)",
filter => "(objectClass=gnugenMember)",
attrs => ['', '*']);
my %members;
......@@ -172,7 +172,6 @@ New members can be created with the following code:
mail => 'foo@bar.net',
mobile => '+41791234567',
username => 'fbar',
password => 'password',
shell => '/bin/bash',
};
......@@ -180,7 +179,7 @@ New members can be created with the following code:
sub create {
my ($class, %args) = @_;
for my $arg (qw(cn firstName lastName mail mobile username password shell)) {
for my $arg (qw(cn firstName lastName mail mobile username shell)) {
unless (defined $args{$arg}) {
warn "missing $arg argument";
return;
......@@ -193,9 +192,9 @@ sub create {
my $userdn = 'cn=' . escape_dn_value($args{cn}) . ','
. $GnuGeneration::LDAP::USERS_BASE;
my @userattrs = [
my @userattrs = (
cn => $args{cn},
objectclass => [
objectClass => [
'inetOrgPerson',
'posixAccount',
'shadowAccount',
......@@ -207,16 +206,16 @@ sub create {
mobile => $args{mobile},
uidNumber => $id,
gidNumber => $id,
shell => '/bin/bash',
homeDirectory => '/home/' . $args{username},
loginShell => '/bin/bash',
shadowExpire => $SHADOW_EXPIRE_DISABLED,
userPassword => $args{password_hash},
gnugenMemberSubscriptionPayedDate => 0,
gnugenMemberTermsOfUseAcceptedDate => 0,
];
);
my $groupdn = 'cn=' . escape_dn_value($args{username}) . ','
. $GnuGeneration::LDAP::GROUPS_BASE;
my @groupattrs = (
'objectclass' => [ "posixGroup" ],
'objectClass' => [ "posixGroup" ],
'cn' => $args{username},
'description' => "Private group for $args{username}",
'memberUid' => $args{username},
......@@ -226,12 +225,16 @@ sub create {
# Create the user entry
my $mesg = $ldap->add($userdn, attrs => \@userattrs);
if ($mesg->code) {
warn "Failed to user entry: ", $mesg->error;
warn "Failed to add user entry: ", $mesg->error;
return;
}
# Synchronize concurrent user creation
$id = _fixup_new_user_id($ldap, $userdn);
unless (defined $id) {
$ldap->delete($userdn);
warn "User entry was deleted due to previous errors.";
}
# Create the group entry
$mesg = $ldap->add($groupdn, attrs => \@groupattrs);
......@@ -267,9 +270,12 @@ sub create {
return;
}
$member->add_to_group("members");
$member->add_to_group("gnunas-sftp");
$member->add_to_group("rainbowdash-login");
GnuGeneration::Group->new("members")->add($args{username})
or warn "Couldn't add member to members group";
GnuGeneration::Group->new("gnunas-sftp")->add($args{username})
or warn "Couldn't add member to gnunas-sftp gorup";
GnuGeneration::Group->new("rainbowdash-login")->add($args{username})
or warn "Couldn't add member to rainbowdash-login group";
return $member;
}
......@@ -281,13 +287,23 @@ sub create {
sub _fixup_new_user_id {
my ($ldap, $dn) = @_;
my $mesg = $ldap->search(base => $GnuGeneration::LDAP::USERS_BASE,
my $mesg = $ldap->search(
base => $dn,
scope => "base",
filter => "(objectclass=*)",
attrs => "uidNumber",
filter => "(objectClass=*)",
attrs => ["*"],
);
if ($mesg->is_error) {
warn "Couldn't perform search: ", $mesg->error;
return;
}
if ($mesg->count == 0) {
warn "Couldn't find newly created entry";
return;
}
my $entry = $mesg->pop_entry;
my $id = decode('UTF-8', $entry->get_value("uidNumber", asref => 1)->[0]);
......@@ -411,7 +427,7 @@ sub _entry_for_username {
my $safe_username = escape_filter_value($username);
my $mesg = $ldap->search(
base => $GnuGeneration::LDAP::USERS_BASE,
filter => "(&(objectclass=gnugenMember)(uid=$safe_username))");
filter => "(&(objectClass=gnugenMember)(uid=$safe_username))");
$mesg->code && warn "Can't find $username: " . $mesg->error;
return $mesg->shift_entry;
}
......@@ -428,7 +444,7 @@ sub _from_usernames {
my ($class, $ldap, @usernames) = @_;
return unless scalar(@usernames) > 0;
my $filter = '(&(objectclass=gnugenMember)(|'
my $filter = '(&(objectClass=gnugenMember)(|'
. join("", map {'(uid=' . escape_filter_value($_) . ')'}
@usernames)
. '))';
......@@ -690,7 +706,7 @@ sub _next_uid {
my $lst = $ldap->search(base => $GnuGeneration::LDAP::USERS_BASE,
scope => 'subtree',
filter => "(objectclass=posixAccount)",
filter => "(objectClass=posixAccount)",
attrs => ['uidNumber']);
$lst->code && die $lst->error;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment