diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FindUser.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FindUser.pm index cb5969634..f2a42b667 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FindUser.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FindUser.pm @@ -29,28 +29,45 @@ sub provideUser { return $req->error($error); } $req->mustRedirect(1); + + return $self->sendJSONresponse( + $req, + { + user => ( $req->{findUser} ? $req->{findUser} : '' ), + result => 1 + } + ) if $req->wantJSON; return $self->p->do( $req, [ sub { PE_FIRSTACCESS } ] ); } sub retreiveFindUserParams { - my ( $self, $req ) = @_; - my ( $params, $excludedParams ) = ( [ {} ], [ {} ] ); + my ( $self, $req ) = @_; + my ( $searching, $excluding ) = ( [], [] ); $self->logger->debug("FindUser: reading parameters..."); foreach ( sort keys %{ $self->conf->{findUserSearchingAttributes} } ) { - $self->logger->debug( "Pushing searching parameter: $_ => " . $req->params($_) ); - push @$params, { key => $_, value => $req->params($_) }; + if ( $req->params($_) ) { + $self->logger->debug( + "Pushing searching parameter: $_ => " . $req->params($_) ); + push @$searching, { key => $_, value => $req->params($_) }; + } } - $self->logger->debug("FindUser: reading excluding parameters..."); - foreach ( sort keys %{ $self->conf->{findUserExcludingAttributes} } ) { - $self->logger->debug( "Pushing excluded parameter: $_ => " - . $self->conf->{findUserExcludingAttributes}->{$_} ); - push @$excludedParams, - { - key => $_, - value => $self->conf->{findUserExcludingAttributes}->{$_} - }; + + if ( scalar @$searching ) { + $self->logger->debug("FindUser: reading excluding parameters..."); + foreach ( sort keys %{ $self->conf->{findUserExcludingAttributes} } ) { + if ( $req->params($_) ) { + $self->logger->debug( "Pushing excluded parameter: $_ => " + . $self->conf->{findUserExcludingAttributes}->{$_} ); + push @$excluding, + { + key => $_, + value => $self->conf->{findUserExcludingAttributes}->{$_} + }; + } + } } - return ( $params, $excludedParams ); + + return ( $searching, $excluding ); } 1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/DBI.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/DBI.pm index 85950acae..5d3f12f77 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/DBI.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/DBI.pm @@ -50,31 +50,32 @@ sub findUser { my ( $self, $req, %args ) = @_; my $plugin = $self->p->loadedModules->{"Lemonldap::NG::Portal::Plugins::FindUser"}; - my ( $searching, $excluding ) = $plugin->retreiveFindUserParams($req); + my ( $searching, $excluding, $result ) = $plugin->retreiveFindUserParams($req); return PE_OK unless scalar @$searching; my $table = $self->table; my $pivot = $args{useMail} ? $self->mailField : $self->pivot; - my $request = 'SELECT $pivot FROM $table WHERE '; + my $request = "SELECT $pivot FROM $table WHERE "; my @args; my $sth; foreach (@$searching) { if ( $_->{value} ) { - $request .= '$' . $_->{key} . '=? AND '; + $request .= "$_->{key} = ? AND "; push @args, $_->{value}; } } foreach (@$excluding) { if ( $_->{value} ) { - $request .= '$' . $_->{key} . '!=? AND '; + $request .= "$_->{key} != ? AND "; push @args, $_->{value}; } } $request =~ s/AND\s$//; $self->logger->debug("DBI UserDB built condition: $request"); + $self->logger->debug( "DBI UserDB built args: " . join '|', @args ); eval { - $sth = $self->dbh->prepare(eval "$request"); + $sth = $self->dbh->prepare($request); $sth->execute(@args); }; eval { $self->p->_authentication->setSecurity($req) }; @@ -85,12 +86,14 @@ sub findUser { $self->logger->error("DBI error: $@") if ( $self->_dbh ); return PE_ERROR; } - if ( my $results = $sth->fetchrow_arrayref() ) { + my $results = $sth->fetchall_arrayref(); + if ( $results->[0]->[0] ) { my $rank = rand( scalar @$results ); $self->logger->debug( 'DBI UserDB number of result(s): ' . scalar @$results ); $self->logger->debug("Demo UserDB random rank: $rank"); - $req->{findUser} = $results->[$rank]; + $self->userLogger->info("FindUser: DBI UserDB returns $results->[$rank]->[0]"); + $req->{findUser} = $results->[$rank]->[0]; } PE_OK; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm index 7dd28b24b..e00d969ad 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm @@ -102,6 +102,7 @@ sub findUser { $self->logger->debug( 'Demo UserDB number of result(s): ' . scalar @results ); $self->logger->debug("Demo UserDB random rank: $rank"); + $self->userLogger->info("FindUser: Demo UserDB returns $results[$rank]"); $req->{findUser} = $results[$rank]; eval { $self->p->_authentication->setSecurity($req) }; diff --git a/lemonldap-ng-portal/t/68-FindUser-with-DBI.t b/lemonldap-ng-portal/t/68-FindUser-with-DBI.t new file mode 100644 index 000000000..471023f63 --- /dev/null +++ b/lemonldap-ng-portal/t/68-FindUser-with-DBI.t @@ -0,0 +1,205 @@ +use Test::More; +use strict; +use JSON; +use IO::String; + +require 't/test-lib.pm'; + +my $res; +my $maintests = 31; + +my $userdb = tempdb(); + +SKIP: { + eval { require DBI; require DBD::SQLite; }; + if ($@) { + skip 'DBD::SQLite not found', $maintests; + } + my $res; + my $json; + my $request; + my $dbh = DBI->connect("dbi:SQLite:dbname=$userdb"); + $dbh->do( +'CREATE TABLE users (user text,password text,name text, type text, guy text)' + ); + $dbh->do( + "INSERT INTO users VALUES ('dwho','dwho','Doctor who', 'serie', 'good')" + ); + $dbh->do( +"INSERT INTO users VALUES ('rtyler','rtyler','Rose Tyler', 'serie', 'good')" + ); + $dbh->do( + "INSERT INTO users VALUES ('davros','davros','Davros', 'serie', 'bad')" + ); + $dbh->do( +"INSERT INTO users VALUES ('msmith','msmith','Mr Smith', 'serie', 'good')" + ); + $dbh->do( + "INSERT INTO users VALUES ('spoke','spoke','Mr Spoke', 'movie', 'good')" + ); + my $client = LLNG::Manager::Test->new( { + ini => { + logLevel => 'debug', + useSafeJail => 1, + authentication => 'DBI', + userDB => 'Same', + dbiAuthChain => "dbi:SQLite:dbname=$userdb", + dbiAuthUser => '', + dbiAuthPassword => '', + dbiAuthTable => 'users', + dbiAuthLoginCol => 'user', + dbiAuthPasswordCol => 'password', + dbiAuthPasswordHash => '', + dbiDynamicHashEnabled => 0, + passwordDB => 'DBI', + requireToken => 1, + findUser => 1, + impersonationRule => 1, + findUserSearchingAttributes => + { user => 'Login', guy => 'Kind' }, + findUserExcludingAttributes => { type => 'movie' }, + } + } + ); + + ## Simple access + ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Portal', ); + my ( $host, $url, $query ) = + expectForm( $res, '#', undef, 'user', 'password', 'spoofId', 'token' ); + + $request = 'user=dwho'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'text/html', + length => length($request) + ), + 'Post FindFuser request' + ); + ( $host, $url, $query ) = + expectForm( $res, '#', undef, 'user', 'password', 'spoofId', 'token' ); + ok( $res->[2]->[0] =~ m%value="dwho"%, 'value="dwho"' ) + or explain( $res->[2]->[0], 'value="dwho"' ); + ok( $res->[2]->[0] =~ m%autocomplete="off"%, 'autocomplete="off"' ) + or explain( $res->[2]->[0], 'autocomplete="off"' ); + + $request = 'user=dwho'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{user} eq 'dwho', ' Good user' ) + or explain( $json, 'user => dwho' ); + + $request = 'user=dwo'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request no result' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{user} eq '', ' No user' ) + or explain( $json, "user => ''" ); + + $request = 'guy=bad'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request one result' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{user} eq 'davros', ' Good user' ) + or explain( $json, "user => 'davros'" ); + + $request = 'guy=good&type=serie'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request multi results' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{user} =~ /^(dwho|rtyler|msmith)$/, " Good user ($1)" ) + or explain( $json, "user => $1" ); + + $request = 'arg=good'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request with bad arg' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{result} == 1, ' Good result' ) + or explain( $json, 'result => 1' ); + ok( $json->{user} eq '', ' No user' ) + or explain( $json, 'user => ?' ); + + $request = 'guy=good&user=msmith'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request with two args' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{user} eq 'msmith', ' Good user' ) + or explain( $json, 'user => msmith' ); + + $request = 'guy=bad&user=msmith'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request with wrong args' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{result} == 1, ' Good result' ) + or explain( $json, 'result => 1' ); + ok( $json->{user} eq '', ' No user' ) + or explain( $json, 'user => ?' ); + + $request = 'user=spoke&type=good'; + ok( + $res = $client->_post( + '/finduser', IO::String->new($request), + accept => 'application/json', + length => length($request) + ), + 'Post FindFuser request with excluding result' + ); + ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' ) + or print STDERR "$@\n" . Dumper($res); + ok( $json->{result} == 1, ' Good result' ) + or explain( $json, 'result => 1' ); + ok( $json->{user} eq '', ' No user' ) + or explain( $json, 'user => ?' ); +} +count($maintests); +done_testing( count() );