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

Last change on this file since 1495 was 1495, checked in by nanardon, 9 years ago

Fix attribute description

File size: 7.7 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;
15use LATMOS::Accounts::Bases::Ldap::Group;
16use LATMOS::Accounts::Utils;
17
18our $VERSION = (q$Rev: 649 $ =~ /^Rev: (\d+) /)[0];
19
20=head1 NAME
21
22LATMOS::Ldap - Perl extension for blah blah blah
23
24=head1 SYNOPSIS
25
26  use LATMOS::Ldap;
27  blah blah blah
28
29=head1 DESCRIPTION
30
31Stub documentation for LATMOS::Ldap, created by h2xs. It looks like the
32author of the extension was negligent enough to leave the stub
33unedited.
34
35Blah blah blah.
36
37=head1 FUNCTIONS
38
39=cut
40
41sub _class_filter { '(&(ObjectClass=posixAccount))' }
42
43sub _key_attr { 'cn' } 
44
45sub _my_ldap_classes { qw(
46    top
47    inetOrgPerson
48    organizationalPerson
49    posixAccount
50    shadowAccount
51) }
52
53sub _get_attr_schema {
54    my ($class, $base) = @_;
55    $class->SUPER::_get_attr_schema($base,
56    {
57        displayName => { },
58        givenName => { },
59        homePhone => { },
60        homePostalAddress => { },
61        initials => { },
62        mail => { },
63        sn => { },
64        mobile => { },
65        o => { },
66        uid => { mandatory => 1 },
67        manager => {
68            delayed => 1,
69            can_values => sub { $base->list_objects('user') },
70        },
71        facsimileTelephoneNumber => { },
72        uidNumber => { uniq => 1, },
73        gidNumber => {
74            reference => 'group',
75            mandatory => 1,
76            can_values => sub {
77                map { $base->get_object('group',
78                        $_)->get_attributes('gidNumber') }
79                $base->list_objects('group')
80            },
81            display => sub {
82                my ($self, $val) = @_;
83                my ($gr) = $self->base->search_objects('group', "gidNumber=$val")
84                    or return;
85                return $gr;
86            },
87
88        },
89        homeDirectory => { },
90        userPassword => { },
91        loginShell => { },
92        gecos => { },
93        description => { },
94        shadowLastChange => { },
95        shadowMin => { },
96        shadowMax => { },
97        shadowWarning => { },
98        shadowInactive => { },
99        shadowExpire => { },
100        shadowFlag => { },
101        street => { },
102        postOfficeBox => { },
103        postalCode => { },
104        postalAddress => { },
105        streetAddress => { },
106        physicalDeliveryOfficeName => { },
107        ou => { },
108        st => { },
109        l => { },
110        telephoneNumber => { },
111        memberOf => {
112            delayed => 1,
113            multiple => 1,
114            reference => 'group',
115        },
116        cn => { ro => 1, },
117        dn => { ro => 1, },
118        objectClass => { ro => 1, },
119        pwdAccountLockedTime => {},
120        pwdPolicySubentry => {},
121        pwdChangedTime => { ro => 1 },
122        labeledURI => {},
123        userPassword => { readable => 0, },
124    }
125    );
126}
127
128sub _create {
129    my ($class, $base, $id, %data) = @_;
130
131    my $entry = Net::LDAP::Entry->new();
132
133    $entry->dn(join(',',
134        sprintf('%s=%s',
135            $class->_dn_attribute($base),
136            escape_filter_value($id)),
137            $base->object_base_dn($class->type),
138        )
139    );
140    $entry->replace(objectClass =>
141        [ $class->_my_ldap_classes ],);
142    $data{cn} ||= $data{sn} || $id; # cn is mandatory
143    $data{sn} ||= $id; # sn is mandatory
144    $data{uid} ||= $id; # uid is mandatory
145    $data{homeDirectory} ||= '/dev/null'; # homeDirectory is mandatory
146    $data{$class->_key_attribute($base)} = $id;
147    foreach (keys %data) {
148        $class->_populate_entry($entry,
149            $_, $data{$_}, $base);
150    }
151
152    my $msg = $base->ldap->add($entry);
153    if ($msg->code) {
154        $base->log(LA_ERR, "Cannot create user: %s", $msg->error);
155        return 0;
156    }
157    return 1;
158}
159
160sub _rename {
161    my ($class, $base, $uid, $newuid) = @_;
162
163    $class->SUPER::_rename($base, $uid, $newuid) or return;
164}
165
166sub get_field {
167    my ($self, $field) = @_;
168
169    $field eq 'streetAddress' and $field = 'street';
170    $field eq 'memberOf' and do {
171        my @res;
172        $self->base->_unlimited_search(
173            base => $self->base->object_base_dn('group'),
174            filter => sprintf(
175                '(&(objectClass=posixGroup)(memberUID=%s))',
176                escape_filter_value($self->id),
177            ),
178            callback => sub {
179                my ($mesg, $entry) = @_;
180                ref $entry eq 'Net::LDAP::Entry' or return;
181                push(@res, $entry->get_value(
182                    LATMOS::Accounts::Bases::Ldap::Group->_key_attribute($self->base),
183                ));
184                1;
185            },
186        );
187        return [ sort(@res) ];
188    };
189    $field eq 'manager' and do {
190        my $dn = $self->SUPER::get_field($field) or return;
191        my $manager = $self->base->_get_object_from_dn($dn) or return;
192        return $manager->get_value(__PACKAGE__->_key_attribute($self->base));
193    };
194    $self->SUPER::get_field($field);
195}
196
197sub _populate_entry {
198    my ($self, $entry, $f, $val, $base) = @_;
199    $base ||= $self->base;
200    for ($f) {
201        /^sn$/ and $val ||= $entry->get_value($self->_key_attribute);
202        /^memberOf$/ and do {
203            my %users;
204            $users{$_}{e} = 1 foreach (ref $self
205                ? $self->get_attributes('memberOf')
206                : ());
207            $users{$_}{n} = 1 foreach (@{ $val || []});
208            foreach (keys %users) {
209                $users{$_}{e} && $users{$_}{n} and next;
210                my $group = $base->get_object('group', $_) or next;
211                if ($users{$_}{e}) {
212                    $group->{entry}->delete(memberUID =>
213                        $entry->get_value(
214                            LATMOS::Accounts::Bases::Ldap::User->_key_attribute($base),
215                        )
216                    );
217                } elsif ($users{$_}{n}) {
218                    $group->{entry}->add(memberUID =>
219                        $entry->get_value(
220                            LATMOS::Accounts::Bases::Ldap::User->_key_attribute($base),
221                        )
222                    );
223                } # else {} # can't happen
224                my $mesg = $group->{entry}->update($base->ldap);
225                if ($mesg->code) {
226                    $base->log(LA_ERR, "Cannot set attributes: %s", $mesg->error);
227                    return;
228                }
229            }
230            return 1;
231        };
232        /^userPassword$/ and do {
233            # openldap use prefix to identify encryption passwd
234            # {CRYPT} is system dependant, eg use crypt from system
235            # As we run openldap on UNIX, this should not be a problem
236            # as we use perl crypt() which does the same
237            # This code will have to be changed if we use openldap on other UNIX
238            $val = '{CRYPT}' . ($val || 'xxx');
239            next;
240        };
241        /^manager$/ && $val and do {
242            my $user = $base->get_object('user', $val) or do {
243                $val = undef;
244                next;
245            };
246            $val = $user->get_field('dn');
247            next;
248        };
249        /^gecos$/ and do {
250            $val = to_ascii($val);
251        };
252        /^homeDirectory$/ and $val ||= '/dev/null';
253    }
254    $self->SUPER::_populate_entry($entry, $f, $val, $base);
255}
256
2571;
258
259__END__
260
261=head1 SEE ALSO
262
263=head1 AUTHOR
264
265Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
266
267=head1 COPYRIGHT AND LICENSE
268
269Copyright (C) 2008 CNRS SA/CETP/LATMOS
270
271This library is free software; you can redistribute it and/or modify
272it under the same terms as Perl itself, either Perl version 5.10.0 or,
273at your option, any later version of Perl 5 you may have available.
274
275
276=cut
Note: See TracBrowser for help on using the repository browser.