From ea06aa8c41d103ff161630fd85d083b9ed6f0b41 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Mon, 28 May 2012 14:27:08 +0200 Subject: More flexible use of wildcards on usernames. --- fripost-searchalias | 2 -- fripost-searchuser | 12 +++++++---- lib/Fripost/Schema/Search.pm | 28 ++++++++++++++++++++++--- lib/Fripost/Schema/Type/User.pm | 45 +++++++++++++++++++++++++++-------------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/fripost-searchalias b/fripost-searchalias index 0a6c4d7..4c4bb9f 100755 --- a/fripost-searchalias +++ b/fripost-searchalias @@ -19,8 +19,6 @@ B [B<--man>] B list virtual aliases matching exactly I, targetting to I. -Wildcards I<*> can appear in the login part of I, to match zero -or more characters. If no I is given, list all aliases whose target matches I. If neither I nor I are given, B list all existing virtual aliases. diff --git a/fripost-searchuser b/fripost-searchuser index 83fc004..c7b2b9b 100755 --- a/fripost-searchuser +++ b/fripost-searchuser @@ -15,12 +15,16 @@ B [B<--debug>] [I] =head1 DESCRIPTION -B list virtual mailboxes whose username exactly matches +B lists virtual mailboxes whose username exactly matches I. -Wildcards I<*> can appear in the login part of I, to match zero or -more characters. +Wildcards I<*> can appear in I, to match zero or more characters. If no I is given, B list all existing mailboxes. -If I has no domain part, lists matching users for any domains. +If I has no domain part, lists matching users for any domains. +Otherwise, B first searches for matching domains, +and then for each of them, looks up the matching users. + +Because of these multiple searches, the use of wildcards on the domain +part of I may be inefficient. =head1 OPTIONS diff --git a/lib/Fripost/Schema/Search.pm b/lib/Fripost/Schema/Search.pm index a9eb2ea..1051a21 100644 --- a/lib/Fripost/Schema/Search.pm +++ b/lib/Fripost/Schema/Search.pm @@ -11,7 +11,20 @@ use base qw/Net::LDAP::Search/; our $VERSION = '0.01'; # Count the entries got out from the query. -sub count { $_[0]->{_res}->count } +sub count { + my $self = shift; + + if (ref $self->{_res} eq 'ARRAY') { + my $count; + foreach (@{$self->{_res}}) { + $count += $_->count; + } + return $count; + } + else { + return $self->{_res}->count; + } +} # Create a hash out of the LDAP entry. Keys depend on the context # of the object. @@ -31,11 +44,20 @@ sub entries { $dumpEntry = "_aliasEntry"; } else { - die "Something weird happened. Please report." + die "Something weird happened. Please report."; } + my @entries; + if (ref $self->{_res} eq 'ARRAY') { + foreach (@{$self->{_res}}) { + push @entries, $_->entries; + } + } + else { + @entries = ($self->{_res}->entries); + } no strict "refs"; - return (map {&$dumpEntry($_)} $self->{_res}->entries); + return (map {&$dumpEntry($_)} @entries); } diff --git a/lib/Fripost/Schema/Type/User.pm b/lib/Fripost/Schema/Type/User.pm index 794f5e5..a9eb293 100644 --- a/lib/Fripost/Schema/Type/User.pm +++ b/lib/Fripost/Schema/Type/User.pm @@ -6,6 +6,7 @@ use strict; use base qw/Net::LDAP/; use Fripost::Schema::Utils; +use Fripost::Schema::Type::Domain; our $VERSION = '0.01'; @@ -15,7 +16,9 @@ our $VERSION = '0.01'; # Search a user, and return the corresponding entries if found. If no # user is given, returns all users. # If the user has no domain part, returns matching users for any -# domains. +# domains. Otherwise, we first search for matching domains (we may +# have multiple matches as wildcards are allowed), and then for each of +# them, search for the matching users. sub search { my $self = shift; my $user = shift; @@ -25,26 +28,38 @@ sub search { if defined $user->{username}; my $base = $self->{_options}->{base_dn}; - $base = join ',', ( 'dc='.$domain, $base ) - if defined $domain; + my @bases; + if (defined $domain) { + my $dres = Fripost::Schema::Type::Domain::search ( $self, {domain => $domain} ); + foreach ($dres->entries) { + push @bases, join ',', ( 'dc='.$_->get_value('dc'), $base ); + } + } + else { + push @bases, $base; + } my $filter = "(ObjectClass=virtualMailbox)"; $filter = "(&" .$filter. "(uid=" .$username. ")" .")" if defined $username; - if ($self->{_options}->{debug}) { - say STDERR "DEBUG: Search base: " .$base; - say STDERR "DEBUG: Search filter: " .$filter; + my @res; + foreach my $b (@bases) { + if ($self->{_options}->{debug}) { + say STDERR "DEBUG: Search base: " .$b; + say STDERR "DEBUG: Search filter: " .$filter; + } + + my $res = $self->{_ldap}->search( + base => $b, + scope => 'sub', + attrs => [ 'uid', 'gn' , 'sn', 'isActive' ], + filter => $filter + ); + die "Error: " .$res->error. "\n" if $res->code; + push @res, $res; } - - my $res = $self->{_ldap}->search( - base => $base, - scope => 'sub', - attrs => [ 'uid', 'gn' , 'sn', 'isActive' ], - filter => $filter - ); - die "Error: " .$res->error. "\n" if $res->code; - return $res; + return \@res; } -- cgit v1.2.3