source: LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/User.pm @ 657

Last change on this file since 657 was 657, checked in by nanardon, 14 years ago
  • fix ldap user creation: don't call as object in _populate_entry
File size: 5.5 KB
Line 
1package LATMOS::Accounts::Bases::Ldap::User;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Ldap::objects);
8use Net::LDAP;
9use Net::LDAPS;
10use Net::LDAP::Entry;
11use Net::LDAP::Control::Paged;
12use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); 
13use Net::LDAP::Util     qw( escape_filter_value );
14use LATMOS::Accounts::Log;
15
16our $VERSION = (q$Rev: 649 $ =~ /^Rev: (\d+) /)[0];
17
18=head1 NAME
19
20LATMOS::Ldap - Perl extension for blah blah blah
21
22=head1 SYNOPSIS
23
24  use LATMOS::Ldap;
25  blah blah blah
26
27=head1 DESCRIPTION
28
29Stub documentation for LATMOS::Ldap, created by h2xs. It looks like the
30author of the extension was negligent enough to leave the stub
31unedited.
32
33Blah blah blah.
34
35=head1 FUNCTIONS
36
37=cut
38
39sub _class_filter { '(&(ObjectClass=posixAccount))' }
40
41sub _key_attr { 'cn' } 
42
43sub _my_ldap_classes { qw(
44    top
45    inetOrgPerson
46    organizationalPerson
47    posixAccount
48    shadowAccount
49) }
50
51sub _delayed_fields {
52    my ($self)= @_;
53    return qw();
54}
55
56sub _canonical_fields {
57    my ($self, $base, $mode) = @_;
58    (
59        qw(displayName givenName homePhone homePostalAddress
60        initials mail sn
61        mobile o uid manager facsimileTelephoneNumber), # inetOrgPerson
62        qw(uidNumber gidNumber homeDirectory
63        userPassword loginShell
64        gecos description), # posixAccount
65        qw(shadowLastChange
66        shadowMin shadowMax
67        shadowWarning
68        shadowInactive
69        shadowExpire
70        shadowFlag), # shadowAccount
71        qw(street postOfficeBox postalCode postalAddress streetAddress
72        physicalDeliveryOfficeName ou st l telephoneNumber), # organizationalPerson
73        ('memberOf'),
74        ($mode
75            !~ /w/
76              ? qw(cn dn)
77              : ()
78        )
79    )
80}
81
82sub _create {
83    my ($class, $base, $id, %data) = @_;
84
85    my $entry = Net::LDAP::Entry->new();
86
87    $entry->dn(join(',',
88        sprintf('cn=%s', escape_filter_value($id)),
89        $base->object_base_dn($class->type),
90    ));
91    $entry->replace(objectClass =>
92        [ $class->_my_ldap_classes ],);
93    $data{sn} ||= $id; # sn is mandatory
94    $data{homeDirectory} ||= '/dev/null'; # homeDirectory is mandatory
95    foreach (keys %data) {
96        $class->_populate_entry($entry,
97            $_, $data{$_}, $base);
98    }
99
100    my $msg = $base->ldap->add($entry);
101    if ($msg->code) {
102        $base->log(LA_ERR, "Cannot create user: %s", $msg->error);
103        return 0;
104    }
105    return 1;
106}
107
108sub get_field {
109    my ($self, $field) = @_;
110
111    $field eq 'streetAddress' and $field = 'street';
112    $field eq 'memberOf' and do {
113        my @res;
114        $self->base->_unlimited_search(
115            base => $self->base->object_base_dn('group'),
116            filter => sprintf(
117                '(&(objectClass=posixGroup)(memberUID=%s))',
118                escape_filter_value($self->id),
119            ),
120            callback => sub {
121                my ($mesg, $entry) = @_;
122                ref $entry eq 'Net::LDAP::Entry' or return;
123                push(@res, $entry->get_value('cn'));
124                1;
125            },
126        );
127        return [ sort(@res) ];
128    };
129    $field eq 'manager' and do {
130        my $dn = $self->SUPER::get_field($field) or return;
131        return $self->base->_get_object_from_dn($dn)->get_value('cn');
132    };
133    $self->SUPER::get_field($field);
134}
135
136sub _populate_entry {
137    my ($self, $entry, $f, $val, $base) = @_;
138    $base ||= $self->base;
139    for ($f) {
140        /^sn$/ and $val ||= $entry->get_value('cn');
141        /^memberOf$/ and do {
142            my %users;
143            $users{$_}{e} = 1 foreach (ref $self
144                ? $self->get_attributes('memberOf')
145                : ());
146            $users{$_}{n} = 1 foreach (@{ $val || []});
147            foreach (keys %users) {
148                $users{$_}{e} && $users{$_}{n} and next;
149                my $group = $base->get_object('group', $_) or next;
150                if ($users{$_}{e}) {
151                    $group->{entry}->delete(memberUID => $entry->get_value('cn'));
152                } elsif ($users{$_}{n}) {
153                    $group->{entry}->add(memberUID => $entry->get_value('cn'));
154                } # else {} # can't happen
155                my $mesg = $group->{entry}->update($base->ldap);
156                if ($mesg->code) {
157                    $base->log(LA_ERR, "Cannot set attributes: %s", $mesg->error);
158                    return;
159                }
160            }
161            return 1;
162        };
163        /^userPassword$/ and do {
164            # openldap use prefix to identify encryption passwd
165            # {CRYPT} is system dependant, eg use crypt from system
166            # As we run openldap on UNIX, this should not be a problem
167            # as we use perl crypt() which does the same
168            # This code will have to be changed if we use openldap on other UNIX
169            $val = '{CRYPT}' . ($val || 'xxx');
170            next;
171        };
172        /^manager$/ && $val and do {
173            my $user = $base->get_object('user', $val) or
174            next;
175            $val = $user->get_field('dn');
176            next;
177        };
178        /^homeDirectory$/ and $val ||= '/dev/null';
179    }
180    $self->SUPER::_populate_entry($entry, $f, $val, $base);
181}
182
1831;
184
185__END__
186
187=head1 SEE ALSO
188
189=head1 AUTHOR
190
191Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
192
193=head1 COPYRIGHT AND LICENSE
194
195Copyright (C) 2008 CNRS SA/CETP/LATMOS
196
197This library is free software; you can redistribute it and/or modify
198it under the same terms as Perl itself, either Perl version 5.10.0 or,
199at your option, any later version of Perl 5 you may have available.
200
201
202=cut
Note: See TracBrowser for help on using the repository browser.