From bb50ae68cf3988e095a1c3d4eac19c5bb6db0235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9rick?= Date: Wed, 19 Feb 2014 12:12:55 -0500 Subject: [PATCH] Bug 11808 - Add the SearchCardnumberWithLDAP system preference. When activated, cardnumber searches in the intranet will also do a search on the LDAP server if a user was not found in the local database. If the cardnumber is found on the LDAP server, the user account is imported in the local database. https://bugs.koha-community.org/show_bug.cgi?id=11808 --- C4/Auth_with_ldap.pm | 82 ++++++++++++++++++++++ circ/circulation.pl | 24 ++++++- ...bug_11808_SearchCardnumberWithLDAP_sys_pref.sql | 2 + installer/data/mysql/sysprefs.sql | 3 +- .../prog/en/modules/admin/preferences/patrons.pref | 6 ++ .../prog/en/modules/circ/circulation.tt | 1 + 6 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_11808_SearchCardnumberWithLDAP_sys_pref.sql diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm index 3a7c3e3..9abcd1d 100644 --- a/C4/Auth_with_ldap.pm +++ b/C4/Auth_with_ldap.pm @@ -369,6 +369,88 @@ sub update_local { _do_changepassword($userid, $borrowerid, $password) if $borrower->{'password'}; } +# Subroutine to update a user with LDAP using its cardnumber. +sub updateborrower_ldap { + my $local_borrower = shift; + my $cardnumber = $local_borrower->{'cardnumber'}; + + return 0 unless ($config{update}); + + my @hosts = split(',', $prefhost); + my $db = Net::LDAP->new(\@hosts, timeout => ($ldap->{timeout} || 30)) or return 0; + + my $cardnumber_field = $mapping{cardnumber}->{is} or die ldapserver_error("mapping for 'cardnumber'"); + my $filter = Net::LDAP::Filter->new("$cardnumber_field=$cardnumber") or die "Failed to create new Net::LDAP::Filter"; + my $res = ($config{anonymous}) ? $db->bind : $db->bind($ldapname, password=>$ldappassword); + if ($res->code) { # connection refused + warn "LDAP bind failed as ldapuser " . ($ldapname || '[ANONYMOUS]') . ": " . description($res); + return 0; + } + my $search = $db->search( + base => $base, + filter => $filter, + ); + + # Search error, return 0 + return (0, $search->error) if $search->code; + + my $count = $search->count; + if ($count == 1) { + # User was found, update! + my %borrower = ldap_entry_2_hash($search->shift_entry,$cardnumber); + &update_local($local_borrower->{userid},$local_borrower->{password},$local_borrower->{borrowernumber},\%borrower); + + return 1; + } + else { + return 0; + } + +} + +# Subroutine to search for a user by its cardnumber through LDAP. +# The user is added locally if found. (We suppose this user doesn't already exist if this subroutine is called) +sub findcardnumber_ldap { + my $cardnumber = shift; + + return 0 unless ($config{replicate}); + + my @hosts = split(',', $prefhost); + my $db = Net::LDAP->new(\@hosts, timeout => ($ldap->{timeout} || 30)) or return 0; + + my $cardnumber_field = $mapping{cardnumber}->{is} or die ldapserver_error("mapping for 'cardnumber'"); + my $filter = Net::LDAP::Filter->new("$cardnumber_field=$cardnumber") or die "Failed to create new Net::LDAP::Filter"; + my $res = ($config{anonymous}) ? $db->bind : $db->bind($ldapname, password=>$ldappassword); + if ($res->code) { # connection refused + warn "LDAP bind failed as ldapuser " . ($ldapname || '[ANONYMOUS]') . ": " . description($res); + return 0; + } + my $search = $db->search( + base => $base, + filter => $filter, + ); + + # Search error, return 0 + return (0, $search->error) if $search->code; + + my $count = $search->count; + if ($count == 1) { + # User was found, add it! + my %borrower = ldap_entry_2_hash($search->shift_entry,$cardnumber); + + # Generate a random password to keep the user secure if no password was mapped + my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(! @ $ % ^ & *) ); + $borrower{'password'} = join("", @chars[ map { rand @chars } ( 1 .. 30 ) ]) unless $borrower{'password'}; + + my $borrowernumber = AddMember(%borrower); + return $borrowernumber; + } + else { + return 0; + } + +} + 1; __END__ diff --git a/circ/circulation.pl b/circ/circulation.pl index 5db1001..c81219c 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -245,13 +245,31 @@ if ($findborrower) { my $borrowers = $results->{patrons}; if ( scalar @$borrowers == 1 ) { $borrowernumber = $borrowers->[0]->{borrowernumber}; + # Update the user with LDAP if we need to + if(C4::Context->config('useldapserver') and C4::Context->preference("SearchCardnumberWithLDAP")) { + my ($result, $ldap_error) = C4::Auth_with_ldap::updateborrower_ldap($borrowers->[0]); + $template->param(ldap_error => $ldap_error) if $ldap_error; + } $query->param( 'borrowernumber', $borrowernumber ); $query->param( 'barcode', '' ); + } elsif ( @$borrowers == 0 ) { + # Try to find a user using LDAP if we couldn't find it locally + my $borrowernumber_ldap; + my $ldap_error; + if (C4::Context->config('useldapserver') and C4::Context->preference("SearchCardnumberWithLDAP")) { + ($borrowernumber_ldap, $ldap_error) = C4::Auth_with_ldap::findcardnumber_ldap($findborrower); + } + + if ($borrowernumber_ldap) { + $borrowernumber = $borrowernumber_ldap; + } + else { + $template->param(ldap_error => $ldap_error) if $ldap_error; + $query->param( 'findborrower', '' ); + $message = "'$findborrower'"; + } } elsif ( @$borrowers ) { $template->param( borrowers => $borrowers ); - } else { - $query->param( 'findborrower', '' ); - $message = "'$findborrower'"; } } } diff --git a/installer/data/mysql/atomicupdate/bug_11808_SearchCardnumberWithLDAP_sys_pref.sql b/installer/data/mysql/atomicupdate/bug_11808_SearchCardnumberWithLDAP_sys_pref.sql new file mode 100644 index 0000000..5ccf071 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_11808_SearchCardnumberWithLDAP_sys_pref.sql @@ -0,0 +1,2 @@ +INSERT INTO systempreferences (variable,value,explanation,options,type) +VALUES('SearchCardnumberWithLDAP','','Search for a cardnumber with LDAP when trying to do a checkout with a cardnumber that does not exist locally. If the cardnumber is found via LDAP, the user is added locally.','','YesNo'); \ No newline at end of file diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index c9c86a2..95e4526 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -567,5 +567,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('XSLTListsDisplay','default','','Enable XSLT stylesheet control over lists pages display on intranet','Free'), ('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'), ('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'), -('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo') +('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo'), +('SearchCardnumberWithLDAP','','Search for a cardnumber with LDAP when trying to do a checkout with a cardnumber that does not exist locally. If the cardnumber is found via LDAP, the user is added locally.','','YesNo') ; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref index 4a85957..bab8011 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -139,6 +139,12 @@ Patrons: dateexpiry: current membership expiry date. combination: the latter of the current and expiry date. - + - pref: SearchCardnumberWithLDAP + choices: + yes: Do + no: "Don't" + - search for a cardnumber with LDAP when trying to do a checkout with a cardnumber that doesn't exist locally. If the cardnumber is found via LDAP, the user is added locally. Note : This feature only works if auth_by_bind is disabled in koha-conf.xml. + - - pref: TalkingTechItivaPhoneNotification choices: yes: Enable diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index d6608d7..d69c57f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -555,6 +555,7 @@ $(document).ready(function() { [% IF ( message ) %] [% INCLUDE 'patron-toolbar.inc' %] +[% IF ( ldap_error ) %]

An error occured while trying to contact the LDAP server : [% ldap_error %]

[% END %]

No patron matched [% message | html %]

-- 1.9.1