source: LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/User.pm @ 840

Last change on this file since 840 was 840, checked in by nanardon, 14 years ago
  • use sql view for managedObjects instead a specific query
  • Property svn:keywords set to Id Rev
File size: 16.4 KB
Line 
1package LATMOS::Accounts::Bases::Sql::User;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use LATMOS::Accounts::Utils;
8use LATMOS::Accounts::Log;
9use base qw(LATMOS::Accounts::Bases::Sql::objects);
10
11our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
12
13=head1 NAME
14
15LATMOS::Ad - Perl extension for blah blah blah
16
17=head1 SYNOPSIS
18
19  use LATMOS::Accounts::Bases;
20  my $base = LATMOS::Accounts::Bases->new('sql');
21  ...
22
23=head1 DESCRIPTION
24
25Account base access over standard unix file format.
26
27=head1 FUNCTIONS
28
29=cut
30
31=head2 new(%options)
32
33Create a new LATMOS::Ad object for windows AD $domain.
34
35domain / server: either the Ad domain or directly the server
36
37ldap_args is an optionnal list of arguments to pass to L<Net::LDAP>.
38
39=cut
40
41sub object_table { 'user' }
42
43sub key_field { 'name' }
44
45sub has_extended_attributes { 1 }
46
47sub _delayed_fields {
48    my ($self)= @_;
49    return qw(memberOf manager directReports department);
50}
51
52sub _office_address_fields { qw(telephoneNumber physicalDeliveryOfficeName site) }
53
54sub _inline_fields {
55    my ($class, $for, $base) = @_;
56    return (
57        uidNumber => 'uidnumber',
58        gidNumber => 'gidnumber',
59        exported  => 'exported',
60        expire    => 'expire',
61        ($for !~ /w/) ? (
62            name      => 'name',
63            cn => 'name',
64            create    => 'create',
65            date      => 'date',
66        ) : (),
67    );
68}
69
70sub _managed_fields {
71    my ($self, $for, $base) = @_;
72    return (
73        memberOf        => 'memberOf',
74        forward => 'forward',
75        aliases => 'aliases',
76        revaliases => 'revaliases',
77        (map { $_ => $_ } $self->_address_fields),
78        (map { $_ => $_ } $self->_office_address_fields),
79        (($for !~ /w/) ? (
80        uid => 'name',
81        cn => 'name',
82        gecos        => 'gecos',
83        displayName  => 'displayName',
84        sAMAccountName  => 'sAMAccountName',
85        accountExpires => 'accountExpires',
86        shadowExpire => 'shadowExpire',
87        directReports => 'directReports',
88        managedObjects => 'managedObjects',
89        otheraddress => 'otheraddress',
90        mainaddress => 'mainaddress',
91        postalAddress => 'postalAddress',
92        facsimileTelephoneNumber => 'facsimileTelephoneNumber',
93        allsite   => 'allsite',
94        managerContact => 'managerContact',
95        expireText => 'expireText',
96        cells  => 'cells',
97        departments => 'departments',
98        ) : ()),
99    )
100}
101
102sub get_field {
103    my ($self, $field) = @_;
104    if ($field eq 'gecos') {
105        my $gecos = sprintf("%s,%s,%s,%s",
106            join(' ', grep { $_ } 
107                    ($self->_get_c_field('givenName'),
108                    ($self->_get_c_field('sn'))))
109                || $self->_get_c_field('description') || '',
110            join(' - ', grep { $_ } (($self->_get_c_field('site') ||
111                        $self->_get_c_field('l')),
112                $self->_get_c_field('physicalDeliveryOfficeName'))) || '',
113            $self->_get_c_field('telephoneNumber') || '',
114            $self->_get_c_field('expireText') || '',
115        );
116        $gecos =~ s/:/ /g;
117        return to_ascii($gecos);
118    } elsif ($field eq 'displayName') {
119        return join(' ', grep { $_ } ($self->_get_c_field('givenName'), ($self->_get_c_field('sn'))))
120            || $self->_get_c_field('description') || $self->id;
121    } elsif ($field eq 'sAMAccountName') {
122        return $self->id;
123    } elsif ($field eq 'memberOf') {
124        my $sth = $self->db->prepare_cached(
125            q{
126            select name from "group" join
127            group_attributes on group_attributes.okey = "group".ikey
128            where value = ? and attr = ?
129            }
130        );
131        $sth->execute($self->id, 'memberUID');
132        my @res;
133        while (my $res = $sth->fetchrow_hashref) {
134            push(@res, $res->{name});
135        }
136        return \@res;
137    } elsif ($field eq 'directReports') {
138        my $sth = $self->db->prepare_cached(
139            q{
140            select name from "user" join
141            user_attributes on user_attributes.okey = "user".ikey
142            where value = ? and attr = ?
143            }
144        );
145        $sth->execute($self->id, 'manager');
146        my @res;
147        while (my $res = $sth->fetchrow_hashref) {
148            push(@res, $res->{name});
149        }
150        return \@res;
151    } elsif ($field eq 'accountExpires') {
152        my $sth = $self->db->prepare_cached(
153            sprintf(
154                q{select extract(epoch from expire) + 11644474161 as expire
155                from %s where %s = ?},
156                $self->db->quote_identifier($self->object_table),
157                $self->db->quote_identifier($self->key_field),
158            )
159        );
160        $sth->execute($self->id);
161        my $res = $sth->fetchrow_hashref;
162        $sth->finish;
163        return $res->{expire} ? sprintf("%.f", $res->{expire} * 1E7) : '9223372036854775807';
164    } elsif ($field eq 'shadowExpire') {
165        my $sth = $self->db->prepare_cached(
166            sprintf(
167                q{select justify_hours(expire - '1/1/1970'::timestamp) as expire
168                from %s where %s = ?},
169                $self->db->quote_identifier($self->object_table),
170                $self->db->quote_identifier($self->key_field),
171            )
172        );
173        $sth->execute($self->id);
174        my $res = $sth->fetchrow_hashref;
175        $sth->finish;
176        return -1 unless($res->{expire});
177        $res->{expire} =~ /(\d+) days\s*(\w)?/;
178        return $1 + ($2 ? 1 : 0);
179    } elsif ($field eq 'expireText') {
180        my $sth = $self->db->prepare_cached(
181            sprintf(
182                q{select to_char(expire, 'YYYY/MM/DD') as expire
183                from %s where %s = ?},
184                $self->db->quote_identifier($self->object_table),
185                $self->db->quote_identifier($self->key_field),
186            )
187        );
188        $sth->execute($self->id);
189        my $res = $sth->fetchrow_hashref;
190        $sth->finish;
191        return $res->{expire}
192    } elsif ($field eq 'otheraddress') {
193        my $sth = $self->db->prepare_cached(q{
194            select name from address where "user" = ?
195        });
196        $sth->execute($self->id);
197        my @values;
198        while (my $res = $sth->fetchrow_hashref) {
199            push(@values, $res->{name});
200        }
201        return \@values;
202    } elsif ($field eq 'mainaddress') {
203        my $sth = $self->db->prepare_cached(q{
204            select name from address join address_attributes on ikey = okey
205            where "user" = ? and attr = 'isMainAddress'
206            });
207        $sth->execute($self->id);
208        my $res = $sth->fetchrow_hashref;
209        $sth->finish;
210        return $res->{name};
211    } elsif (grep { $field eq $_ } __PACKAGE__->_address_fields(),
212        $self->_office_address_fields, 'postalAddress') {
213        if (my $fmainaddress = $self->_get_c_field('mainaddress')) {
214            my $address = $self->base->get_object('address', $fmainaddress);
215            if ($address) {
216                return $address->_get_c_field($field);
217            } else { # can't happend
218                return;
219            }
220        } else {
221            return $self->SUPER::get_field($field);
222        }
223    } elsif ($field eq 'aliases') {
224        my $sth = $self->db->prepare(q{
225            select name from aliases where array[lower($1)] =
226                string_to_array(lower(array_to_string("forward", ',')), ',')
227        } . ($self->base->{wexported} ? '' : 'and exported = true'));
228        $sth->execute($self->id);
229        my @values;
230        while (my $res = $sth->fetchrow_hashref) {
231            push(@values, $res->{name});
232        }
233        return \@values;
234    } elsif ($field eq 'forward') {
235        my $sth = $self->db->prepare(q{
236            select forward from aliases where name = ?
237        } . ($self->base->{wexported} ? '' : ' and exported = true'));
238        $sth->execute($self->id);
239        my $res = $sth->fetchrow_hashref;
240        $sth->finish;
241        return $res->{forward}
242    } elsif ($field eq 'revaliases') {
243        my $sth = $self->db->prepare(q{
244            select "as" from revaliases where name = ?
245        } . ($self->base->{wexported} ? '' : ' and exported = true'));
246        $sth->execute($self->id);
247        my $res = $sth->fetchrow_hashref;
248        $sth->finish;
249        return $res->{as}
250    } elsif ($field eq 'managerContact') {
251        if (my $manager = $self->_get_c_field('manager')) {
252            return $manager;
253        } elsif (my $department = $self->_get_c_field('department')) {
254            my $obj = $self->base->get_object('group', $department);
255            return $obj->_get_c_field('managedBy');
256        } else {
257            return;
258        }
259    } else {
260        return $self->SUPER::get_field($field);
261    }
262}
263
264sub set_fields {
265    my ($self, %data) = @_;
266    my %fdata;
267    my $res = 0;
268    foreach my $attr (keys %data) {
269        $attr =~ /^memberOf$/ and do {
270            my %member;
271            foreach (@{ $self->get_field('memberOf') }) {
272                $member{$_}{c} = 1;
273            }
274            foreach (grep { $_ } ref $data{$attr} ? @{ $data{$attr} || []} : $data{$attr}) {
275                $member{$_}{n} = 1;
276            }
277
278            foreach (keys %member) {
279                $member{$_}{c} && $member{$_}{n} and next; # no change !
280                my $group = $self->base->get_object('group', $_) or next;
281                ($group->_get_c_field('sutype') || '') =~ /^(jobtype|contrattype)$/ and next;
282                if ($member{$_}{n}) {
283                    my $sth = $self->db->prepare_cached(
284                        q{insert into group_attributes_users (value, attr, okey) values (?,?,?)}
285                    );
286                    $sth->execute($self->id, 'memberUID', $group->_get_ikey);
287                    $res++;
288                } elsif ($member{$_}{c}) {
289                    my $sth = $self->db->prepare_cached(
290                        q{delete from group_attributes_users where value = ? and attr = ? and okey = ?}
291                    );
292                    $sth->execute($self->id, 'memberUID', $group->_get_ikey);
293                    $res++;
294                } # else {} # can't happend
295            }
296            next;
297        };
298        $attr =~ /^forward$/ and do {
299            if ($data{$attr}) {
300                if (my $f = $self->base->get_object('aliases', $self->id)) {
301                    $res += $f->_set_c_fields(forward => $data{$attr});
302                } else {
303                    if ($self->base->_create_c_object('aliases', $self->id,
304                        forward => $data{$attr})) {
305                        $res++;
306                    } else {
307                        $self->base->log(LA_ERR, "Cannot add forward for %s",
308                            $self->id);
309                    }
310                }
311            } else {
312                if ($self->base->_delete_object('aliases', $self->id)) {
313                    $res++;
314                } else {
315                    $self->base->log(LA_ERR, "Cannot remove forward for %s",
316                        $self->id);
317                }
318            }
319            next;
320        };
321        $attr =~ /^aliases$/ and do {
322            my %aliases = map { $_ => 1 } grep { $_ } (ref $data{$attr} ? @{$data{$attr}} :
323                $data{$attr});
324            foreach ($self->_get_attributes('aliases')) {
325                $aliases{$_} ||= 0;
326                $aliases{$_} +=2;
327            }
328            foreach (keys %aliases) {
329                if ($aliases{$_} == 2) {
330                    if ($self->base->_delete_object('aliases', $_)) {
331                        $res++
332                    } else {
333                        $self->base->log(LA_ERR,
334                            "Cannot remove aliases %s from user %s", $_,
335                            $self->id);
336                    }
337                } elsif ($aliases{$_} == 1) {
338                    if ($self->base->_create_c_object('aliases', $_,
339                        forward => [ $self->id ])) {
340                        $res++
341                    } else {
342                        $self->base->log(LA_ERR, 'Cannot set forward %s to user %s',
343                            $_, $self->id);
344                        return
345                    }
346                } # 3 no change
347            }
348            next;
349        };
350        $attr =~ /^revaliases$/ and do {
351            if ($data{$attr}) {
352                if (my $obj = $self->base->
353                        get_object('revaliases', $self->id)) {
354                    my $ares = $obj->set_c_fields('as', $data{$attr});
355                    if (defined($ares)) {
356                        $res+=$ares;
357                    } else {
358                        $self->base->log(LA_ERR, 'Cannot set revaliases for user %s',
359                            $self->id);
360                    }
361                } else {
362                    if ($self->base->_create_c_object(
363                        'revaliases',
364                        $self->id, as => $data{$attr},
365                    )) {
366                        $res++;
367                    } else {
368                        $self->base->log(LA_ERR, 'Cannot set revaliases for user %s',
369                            $self->id);
370                    }
371                }
372            } else {
373                $self->base->_delete_object('revaliases', $self->id);
374                $res++;
375            }
376            next;
377        };
378        $attr =~ /^department$/ and do {
379            if ($data{$attr}) {
380                my $dpmt = $self->base->get_object('group', $data{$attr}) or do {
381                    $self->base->log(LA_ERR, 
382                        "Group %s does not exists",
383                        $data{$attr});
384                    return;
385                };
386                if ((($dpmt->_get_c_field('sutype') || '') ne 'dpmt')) {
387                    $self->base->log(LA_ERR, "Group %s is not a department",
388                        $data{$attr});
389                    return;
390                }
391            }
392        };         
393        $attr =~ /^jobType$/ and do {
394            if ($data{$attr}) {
395                my $dpmt = $self->base->get_object('group', $data{$attr}) or do {
396                    $self->base->log(LA_ERR, 
397                        "Group %s does not exists",
398                        $data{$attr});
399                    return;
400                };
401                if ((($dpmt->_get_c_field('sutype') || '') ne 'jobtype')) {
402                    $self->base->log(LA_ERR, "Group %s is not a jobtype",
403                        $data{$attr});
404                    return;
405                }
406            }
407        };         
408        $attr =~ /^contratType$/ and do {
409            if ($data{$attr}) {
410                my $dpmt = $self->base->get_object('group', $data{$attr}) or do {
411                    $self->base->log(LA_ERR, 
412                        "Group %s does not exists",
413                        $data{$attr});
414                    return;
415                };
416                if ((($dpmt->_get_c_field('sutype') || '') ne 'contrattype')) {
417                    $self->base->log(LA_ERR, "Group %s is not a contrattype",
418                        $data{$attr});
419                    return;
420                }
421            }
422        };         
423        grep { $attr eq $_ } (__PACKAGE__->_office_address_fields, __PACKAGE__->_address_fields()) and do {
424            my $fmainaddress = $self->_get_c_field('mainaddress');
425            # set address attribute => create address object on the fly
426            # except if attr is empty !
427            if (!$fmainaddress && $data{$attr}) {
428                $fmainaddress = $self->id . '-' . join('', map { ('a'..'z')[rand(26)] }
429                (0..4));
430                $self->base->_create_c_object(
431                    'address', $fmainaddress,
432                    user => $self->id,
433                    isMainAddress => 1, ) or do {
434                    $self->base->log(LA_ERR,
435                        "Cannot create main address for user %s", $self->id);
436                    return;
437                };
438            }
439            if ($fmainaddress && 
440                (my $address = $self->base->get_object('address', $fmainaddress))) {
441                $res += $address->set_c_fields($attr => $data{$attr}) ||0;
442            }
443            next;
444        };
445        $fdata{$attr} = $data{$attr} || undef;
446    }
447    if (keys %fdata) {
448        return $self->SUPER::set_fields(%fdata) + $res;
449    } else { return $res; }
450}
451
452
4531;
454
455__END__
456
457=head1 SEE ALSO
458
459=head1 AUTHOR
460
461Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
462
463=head1 COPYRIGHT AND LICENSE
464
465Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
466
467This library is free software; you can redistribute it and/or modify
468it under the same terms as Perl itself, either Perl version 5.10.0 or,
469at your option, any later version of Perl 5 you may have available.
470
471
472=cut
Note: See TracBrowser for help on using the repository browser.