source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ad/Group.pm @ 1117

Last change on this file since 1117 was 1117, checked in by nanardon, 12 years ago

add *_key_attribute and *_dn_attribute configuration parameters

By the way, SQL user object return a user friendly value as CN since cn is not
always used as object ID.

  • Property svn:keywords set to Id Rev
File size: 5.8 KB
Line 
1package LATMOS::Accounts::Bases::Ad::Group;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Ad::objects);
8use Net::LDAP;
9use Net::LDAP::Entry;
10use Net::LDAP::Control::Paged;
11use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); 
12use Net::LDAP::Util     qw( escape_filter_value );
13use LATMOS::Accounts::Log;
14
15our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
16
17=head1 NAME
18
19LATMOS::Ad - Perl extension for blah blah blah
20
21=head1 SYNOPSIS
22
23  use LATMOS::Ad;
24  blah blah blah
25
26=head1 DESCRIPTION
27
28Stub documentation for LATMOS::Ad, created by h2xs. It looks like the
29author of the extension was negligent enough to leave the stub
30unedited.
31
32Blah blah blah.
33
34=head1 FUNCTIONS
35
36=cut
37
38sub _class_filter { '(ObjectClass=group)' }
39
40sub _key_attr { 'cn' } 
41
42sub _my_ldap_classes { qw(top group) }
43
44sub _get_attr_schema {
45    my ($class, $base) = @_;
46    $info = {
47        gidNumber  => { uniq => 1, },
48        description => { },
49        member => {
50            delayed => 1,
51            can_values => sub { $base->list_objects('user') },
52        },
53        memberUID => { delayed => 1, },
54        sAMAccountName => { },
55        managedBy => {
56            delayed => 1,
57            can_values => sub { $base->list_objects('user') },
58        },
59        cn => { ro => 1, },
60        dn => { ro => 1, },
61        objectClass => { ro => 1, },
62        msSFU30NisDomain => { },
63        msSFU30Name => { },
64    }
65
66    $info->{$class->_key_attribute($base)}{ro} = 1;
67    $info->{$class->_dn_attribute($base)}{ro} = 1;
68
69    $info
70}
71
72sub _create {
73    my ($class, $base, $id, %data) = @_;
74
75    $data{sAMAccountName} = 'GR-' . $id;
76    my $entry = Net::LDAP::Entry->new();
77
78    $entry->dn(join(',',
79        sprintf('%s=%s',
80            $class->_dn_attribute($base),
81            escape_filter_value($id)),
82            $base->object_base_dn($class->type
83        ),
84    ));
85    $entry->replace(objectClass => [ $class->_my_ldap_classes ],);
86    $data{$class->_key_attribute($base)} = $id;
87    my %delayed;
88    foreach (keys %data) {
89        /^(memberUID|member)$/ and do {
90            $delayed{$_} = $data{$_};
91            next;
92        };
93        $class->_populate_entry($entry, $_, $data{$_}, $base);
94    }
95    my $msg = $base->ldap->add($entry);
96    $base->log(LA_ERR, "Cannot create group: %s", $msg->error) if ($msg->code);
97    return if ($msg->code);
98    if (! keys %delayed) { return 1 };
99    my $res = $base->get_object('group', $id)->set_fields(%delayed);
100    return defined($res) ? 1 : 0;
101}
102
103sub get_field {
104    my ($self, $field) = @_;
105    require LATMOS::Accounts::Bases::Ad::User;
106
107    $field eq 'member' and do {
108        my @res;
109        $self->base->_unlimited_search(
110            base => $self->base->object_base_dn('user'),
111            filter => sprintf(
112                '(&(objectClass=user)(memberOf=%s))',
113                escape_filter_value($self->{entry}->dn),
114            ),
115            callback => sub {
116                my ($mesg, $entry) = @_;
117                ref $entry eq 'Net::LDAP::Entry' or return;
118                push(@res, $entry->get_value(
119                        LATMOS::Accounts::Base::Ad::User->_key_attribute($self->base)
120                    )
121                );
122            },
123        );
124        return [ sort(@res) ];
125    };
126    $field eq 'memberUID' and do {
127        my $val = $self->SUPER::get_field($field);
128        return ref $val ? $val : [ grep { $_ } $val ];
129    };
130    $self->SUPER::get_field($field);
131}
132
133sub _populate_entry {
134    my ($self, $entry, $field, $value, $base) = @_;
135    $base ||= $self->base;
136    for ($field) {
137        /managedBy$/ and do {
138            if ($value && (my $user = $base->get_object('user', $value))) {
139                $value = $user->get_field('dn');
140            } else {
141                $value = undef;
142            }
143            next;
144        };
145        /^sAMAccountName$/ and do {
146            # Hack... to avoid clash with user
147            if ($value !~ /^GR-/) {
148                $value = 'GR-' . $value;
149            }
150            next;
151        };
152    }
153    $self->SUPER::_populate_entry($entry, $field, $value, $base);
154}
155
156sub set_fields {
157    my ($self, %data) = @_;
158    my %ndata;
159    while (my ($f, $val) = each(%data)) {
160        $f eq 'memberUID' and do {
161            my %users;
162            $users{$_}{e} = 1 foreach (@{ $self->get_field('memberUID') || []});
163            $users{$_}{n} = 1 foreach (@{ $val || []});
164            foreach (keys %users) {
165                $users{$_}{e} && $users{$_}{n} and next;
166                if ($users{$_}{e}) {
167                    $self->{entry}->delete(memberUID => $_);
168                } elsif ($users{$_}{n} && $self->base->get_object('user', $_)) {
169                    $self->{entry}->add(memberUID => $_);
170                } # else {} # can't happen
171            }
172            next;
173        };
174        $f eq 'member' and do {
175            my %users;
176            $users{$_}{e} = 1 foreach (@{ $self->get_field('member') || []});
177            $users{$_}{n} = 1 foreach (@{ $val || []});
178            foreach (keys %users) {
179                $users{$_}{e} && $users{$_}{n} and next;
180                my $user = $self->base->get_object('user', $_) or next;
181                if ($users{$_}{e}) {
182                    $self->{entry}->delete(member => $user->get_field('dn'));
183                } elsif ($users{$_}{n}) {
184                    $self->{entry}->add(member => $user->get_field('dn'));
185                } # else {} # can't happen
186            }
187            next;
188        };
189        $ndata{$f} = $val;
190    }
191    $self->SUPER::set_fields(%ndata);
192}
193
1941;
195
196__END__
197
198=head1 SEE ALSO
199
200=head1 AUTHOR
201
202Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
203
204=head1 COPYRIGHT AND LICENSE
205
206Copyright (C) 2008 CNRS SA/CETP/LATMOS
207
208This library is free software; you can redistribute it and/or modify
209it under the same terms as Perl itself, either Perl version 5.10.0 or,
210at your option, any later version of Perl 5 you may have available.
211
212
213=cut
Note: See TracBrowser for help on using the repository browser.