6 |
use Net::LDAP; |
use Net::LDAP; |
7 |
use Data::Dump qw/dump/; |
use Data::Dump qw/dump/; |
8 |
use base qw(Jifty::Object Class::Accessor::Fast); |
use base qw(Jifty::Object Class::Accessor::Fast); |
9 |
our @config_fields = qw( server dn password base ); |
our @config_fields = keys %{ Jifty->config->app('LDAP') }; |
10 |
Jifty->log->debug("using fields from configuration: ",dump( @config_fields )); |
Jifty->log->debug("using fields from configuration: ",dump( @config_fields )); |
11 |
__PACKAGE__->mk_accessors( qw(ldap current_search), @config_fields ); |
__PACKAGE__->mk_accessors( qw(ldap current_search), @config_fields ); |
12 |
|
|
42 |
} |
} |
43 |
} |
} |
44 |
|
|
45 |
|
# configuration sanity testing |
46 |
|
foreach ( qw/server dn password base objectClass link/ ) { |
47 |
|
die "missing required field $_ in LDAP from etc/config.yaml" unless $args->{$_}; |
48 |
|
} |
49 |
|
foreach ( qw/person organization/ ) { |
50 |
|
die "missing required field $_ in LDAP.objectClass.$_ from etc/config.yaml" unless $args->{objectClass}->{$_}; |
51 |
|
} |
52 |
|
foreach ( qw/person_filter display_from value_from/ ) { |
53 |
|
die "missing required field $_ in LDAP.link.$_ from etc/config.yaml" unless $args->{link}->{$_}; |
54 |
|
} |
55 |
|
|
56 |
my $ldap = Net::LDAP->new( $args->{server} ) or die "$@"; |
my $ldap = Net::LDAP->new( $args->{server} ) or die "$@"; |
57 |
|
|
58 |
# an anonymous bind |
# an anonymous bind |
113 |
$self->current_search->count; |
$self->current_search->count; |
114 |
} |
} |
115 |
|
|
116 |
=head2 as_collection_of |
=head2 collection |
117 |
|
|
118 |
my $connection = $ldap->collection( |
my $connection = $ldap->collection( |
119 |
# name of model to use |
# name of model to use |
120 |
'Organization', |
$ldap->objectClass->{organization}, |
121 |
# optional params |
# optional params |
122 |
limit => $limit, |
limit => $limit, |
123 |
filter => '(uid=foobar)', |
filter => '(uid=foobar)', |
126 |
=cut |
=cut |
127 |
|
|
128 |
my $collection2filter = { |
my $collection2filter = { |
129 |
'User' => '(objectClass=hrEduPerson)', |
'Person' => '(objectClass=hrEduPerson)', |
130 |
'Organization' => '(objectClass=hrEduOrg)', |
'Organization' => '(objectClass=hrEduOrg)', |
131 |
}; |
}; |
132 |
|
|
138 |
$args->{limit} ||= 0; # unlimited by default |
$args->{limit} ||= 0; # unlimited by default |
139 |
|
|
140 |
my $filter = $collection2filter->{$model}; |
my $filter = $collection2filter->{$model}; |
141 |
die "unknown model $model" unless $filter; |
# die "unknown model $model" unless $filter; |
142 |
|
# fallback to model named as objectClass |
143 |
|
$filter ||= "(objectClass=$model)"; |
144 |
|
|
145 |
# add user filter |
# add user filter |
146 |
$filter = '(&' . $filter . $args->{filter} . ')' if $args->{filter}; |
$filter = '(&' . $filter . $args->{filter} . ')' if $args->{filter}; |
152 |
); |
); |
153 |
|
|
154 |
Jifty->log->info( |
Jifty->log->info( |
155 |
"searching LDAP for $model with $filter ", |
"Searching LDAP for $model with $filter ", |
156 |
$args->{limit} ? 'limit ' . $args->{limit} : '', |
$args->{limit} ? 'limit ' . $args->{limit} . ' ' : '', |
157 |
'returned ', $self->count, ' results' |
'returned ', $self->count, ' results' |
158 |
); |
); |
159 |
|
|
162 |
|
|
163 |
while ( my $entry = $self->next ) { |
while ( my $entry = $self->next ) { |
164 |
my $model_obj = Jifty->app_class('Model',$model)->new; |
my $model_obj = Jifty->app_class('Model',$model)->new; |
|
#warn dump( $model_obj ); |
|
165 |
my $additional; |
my $additional; |
166 |
# if ( $model eq 'User' ) { |
$self->model_from_entry( $model_obj, $entry, %$additional ); |
|
# my $organization = A3C::Model::Organization->new; |
|
|
# $self->ldap2model( $organization, $entry ); |
|
|
# $additional->{organization} = $organization; |
|
|
# } |
|
|
$self->ldap2model( $model_obj, $entry, %$additional ); |
|
167 |
$collection->add_record( $model_obj ); |
$collection->add_record( $model_obj ); |
168 |
} |
} |
169 |
|
|
178 |
|
|
179 |
Result of last C<< $ldap->search >> request |
Result of last C<< $ldap->search >> request |
180 |
|
|
181 |
=head2 model_to_entry |
=head2 model_from_entry |
182 |
|
|
183 |
|
$ldap->model_from_entry( $model, $entry, $additional ); |
184 |
|
|
185 |
$ldap->model_to_entry( $model, $entry, $additional ); |
This method will join repeatable attributes by magic marker, |
186 |
|
see C<XXX> in code! |
187 |
|
|
188 |
=cut |
=cut |
189 |
|
|
190 |
sub ldap2model { |
sub model_from_entry { |
191 |
my ( $self, $model, $entry, $additional ) = @_; |
my ( $self, $model, $entry, $additional ) = @_; |
192 |
my $data; |
my $data; |
193 |
|
|
196 |
|
|
197 |
foreach my $attr ( $entry->attributes ) { |
foreach my $attr ( $entry->attributes ) { |
198 |
if ( grep(/^\Q$attr\E$/, @columns ) ) { |
if ( grep(/^\Q$attr\E$/, @columns ) ) { |
199 |
$data->{$attr} = $entry->get_value( $attr ); |
# $data->{$attr} = $entry->get_value( $attr ); |
200 |
} elsif ( $attr !~ m/^(objectClass)$/i ) { |
my @var = $entry->get_value( $attr ); |
201 |
|
# warn "--- $attr = ",dump( @var ); |
202 |
|
# XXX this rolls repeatable values into single field |
203 |
|
my $var = join(' <*> ', @var); |
204 |
|
$data->{$attr} = $var; |
205 |
|
# } elsif ( $attr !~ m/^(objectClass)$/i ) { |
206 |
|
} else { |
207 |
Jifty->log->warn(ref($model)," doesn't have $attr"); |
Jifty->log->warn(ref($model)," doesn't have $attr"); |
208 |
} |
} |
209 |
} |
} |