package LATMOS::Accounts::Bases::Ad::Group; use 5.010000; use strict; use warnings; use base qw(LATMOS::Accounts::Bases::Ad::objects); use Net::LDAP; use Net::LDAP::Entry; use Net::LDAP::Control::Paged; use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); use Net::LDAP::Util qw( escape_filter_value ); use LATMOS::Accounts::Log; our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0]; =head1 NAME LATMOS::Ad - Perl extension for blah blah blah =head1 SYNOPSIS use LATMOS::Ad; blah blah blah =head1 DESCRIPTION Stub documentation for LATMOS::Ad, created by h2xs. It looks like the author of the extension was negligent enough to leave the stub unedited. Blah blah blah. =head1 FUNCTIONS =cut sub _class_filter { '(ObjectClass=group)' } sub _key_attr { 'cn' } sub _my_ldap_classes { qw(top group) } sub _get_attr_schema { my ($class, $base) = @_; my $info = { gidNumber => { uniq => 1, }, description => { }, member => { delayed => 1, can_values => sub { $base->list_objects('user') }, multiple => 1, }, memberUID => { delayed => 1, multiple => 1, }, sAMAccountName => { }, managedBy => { delayed => 1, can_values => sub { $base->list_objects('user') }, }, cn => { ro => 1, }, dn => { ro => 1, }, objectClass => { ro => 1, multiple => 1, }, msSFU30NisDomain => { }, msSFU30Name => { }, }; $info->{$class->_key_attribute($base)}{ro} = 1; $info->{$class->_dn_attribute($base)}{ro} = 1; $info } sub _create { my ($class, $base, $id, %data) = @_; $data{sAMAccountName} = 'GR-' . $id; my $entry = Net::LDAP::Entry->new(); $entry->dn(join(',', sprintf('%s=%s', $class->_dn_attribute($base), escape_filter_value($id)), $base->object_base_dn($class->type ), )); $entry->replace(objectClass => [ $class->_my_ldap_classes ],); $data{$class->_key_attribute($base)} = $id; my %delayed; foreach (keys %data) { /^(memberUID|member)$/ and do { $delayed{$_} = $data{$_}; next; }; $class->_populate_entry($entry, $_, $data{$_}, $base); } my $msg = $base->ldap->add($entry); $base->log(LA_ERR, "Cannot create group: %s", $msg->error) if ($msg->code); return if ($msg->code); if (! keys %delayed) { return 1 }; my $res = $base->get_object('group', $id)->set_fields(%delayed); return defined($res) ? 1 : 0; } sub get_field { my ($self, $field) = @_; require LATMOS::Accounts::Bases::Ad::User; $field eq 'member' and do { my @res; $self->base->_unlimited_search( base => $self->base->object_base_dn('user'), filter => sprintf( '(&(objectClass=user)(memberOf=%s))', escape_filter_value($self->{entry}->dn), ), callback => sub { my ($mesg, $entry) = @_; ref $entry eq 'Net::LDAP::Entry' or return; push(@res, $entry->get_value( LATMOS::Accounts::Bases::Ad::User->_key_attribute($self->base) ) ); }, ); return [ sort(@res) ]; }; $field eq 'memberUID' and do { my $val = $self->SUPER::get_field($field); return ref $val ? $val : [ grep { $_ } $val ]; }; $self->SUPER::get_field($field); } sub _populate_entry { my ($self, $entry, $field, $value, $base) = @_; $base ||= $self->base; for ($field) { /managedBy$/ and do { if ($value && (my $user = $base->get_object('user', $value))) { $value = $user->get_field('dn'); } else { $value = undef; } next; }; /^sAMAccountName$/ and do { # Hack... to avoid clash with user if ($value !~ /^GR-/) { $value = 'GR-' . $value; } next; }; } $self->SUPER::_populate_entry($entry, $field, $value, $base); } sub set_fields { my ($self, %data) = @_; my %ndata; while (my ($f, $val) = each(%data)) { $f eq 'memberUID' and do { $val = [ $val ] unless(ref $val); my %users; $users{$_}{e} = 1 foreach (@{ $self->get_field('memberUID') || []}); $users{$_}{n} = 1 foreach (@{ $val || []}); foreach (keys %users) { $users{$_}{e} && $users{$_}{n} and next; if ($users{$_}{e}) { $self->{entry}->delete(memberUID => $_); } elsif ($users{$_}{n} && $self->base->get_object('user', $_)) { $self->{entry}->add(memberUID => $_); } # else {} # can't happen } next; }; $f eq 'member' and do { my %users; $val = [ $val ] unless(ref $val); $users{$_}{e} = 1 foreach (@{ $self->get_field('member') || []}); $users{$_}{n} = 1 foreach (@{ $val || []}); foreach (keys %users) { $users{$_}{e} && $users{$_}{n} and next; my $user = $self->base->get_object('user', $_) or next; if ($users{$_}{e}) { $self->{entry}->delete(member => $user->get_field('dn')); } elsif ($users{$_}{n}) { $self->{entry}->add(member => $user->get_field('dn')); } # else {} # can't happen } next; }; $ndata{$f} = $val; } $self->SUPER::set_fields(%ndata); } 1; __END__ =head1 SEE ALSO =head1 AUTHOR Olivier Thauvin, Eolivier.thauvin@aerov.jussieu.frE =head1 COPYRIGHT AND LICENSE Copyright (C) 2008 CNRS SA/CETP/LATMOS This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available. =cut