View | Details | Raw Unified | Return to bug 11808
Collapse All | Expand All

(-)a/C4/Auth_with_ldap.pm (+94 lines)
Lines 28-33 use Koha::Patrons; Link Here
28
use Koha::AuthUtils qw( hash_password );
28
use Koha::AuthUtils qw( hash_password );
29
use Net::LDAP;
29
use Net::LDAP;
30
use Net::LDAP::Filter;
30
use Net::LDAP::Filter;
31
use Try::Tiny;
31
32
32
our ( @ISA, @EXPORT_OK );
33
our ( @ISA, @EXPORT_OK );
33
34
Lines 443-448 sub update_local { Link Here
443
    _do_changepassword( $userid, $borrowerid, $password ) if exists( $borrower->{'password'} );
444
    _do_changepassword( $userid, $borrowerid, $password ) if exists( $borrower->{'password'} );
444
}
445
}
445
446
447
# Subroutine to update a user with LDAP using its cardnumber.
448
sub updateborrower_ldap {
449
    my $patron = shift;
450
    my $cardnumber = $patron->cardnumber;
451
452
    return unless ($config{update});
453
454
    my @hosts = split(',', $prefhost);
455
    my $db = Net::LDAP->new(\@hosts, timeout => ($ldap->{timeout} || 30)) or return;
456
457
    my $cardnumber_field = $mapping{cardnumber}->{is} or die ldapserver_error("mapping for 'cardnumber'");
458
    my $filter = Net::LDAP::Filter->new("$cardnumber_field=$cardnumber") or die "Failed to create new Net::LDAP::Filter";
459
    my $res = ($config{anonymous}) ? $db->bind : $db->bind($ldapname, password=>$ldappassword);
460
    if ($res->code) {   # connection refused
461
        warn "LDAP bind failed as ldapuser " . ($ldapname || '[ANONYMOUS]') . ": " . description($res);
462
        return;
463
    }
464
    my $search = $db->search(
465
        base => $base,
466
        filter => $filter,
467
    );
468
469
    # Search error, return undef
470
    return (undef, $search->error) if $search->code;
471
472
    my $count = $search->count;
473
    if ($count == 1) {
474
        # User was found, update!
475
        my %borrower = ldap_entry_2_hash($search->shift_entry,$cardnumber);
476
477
        &update_local($patron->userid, $patron->password, $patron->borrowernumber, \%borrower);
478
479
        my $updated_patron = Koha::Patrons->find( $patron->borrowernumber );
480
        return $updated_patron;
481
    }
482
    else {
483
        return;
484
    }
485
486
}
487
488
# Subroutine to search for a user by its cardnumber through LDAP.
489
# The user is added locally if found. (We suppose this user doesn't already exist if this subroutine is called)
490
sub findcardnumber_ldap {
491
    my $cardnumber = shift;
492
493
    return unless ($config{replicate});
494
495
    my @hosts = split(',', $prefhost);
496
    my $db = Net::LDAP->new(\@hosts, timeout => ($ldap->{timeout} || 30)) or return;
497
498
    my $cardnumber_field = $mapping{cardnumber}->{is} or die ldapserver_error("mapping for 'cardnumber'");
499
    my $filter = Net::LDAP::Filter->new("$cardnumber_field=$cardnumber") or die "Failed to create new Net::LDAP::Filter";
500
    my $res = ($config{anonymous}) ? $db->bind : $db->bind($ldapname, password=>$ldappassword);
501
    if ($res->code) {   # connection refused
502
        warn "LDAP bind failed as ldapuser " . ($ldapname || '[ANONYMOUS]') . ": " . description($res);
503
        return;
504
    }
505
    my $search = $db->search(
506
        base => $base,
507
        filter => $filter,
508
    );
509
510
    # Search error, return undef
511
    return (undef, $search->error) if $search->code;
512
513
    my $count = $search->count;
514
    if ($count == 1) {
515
        # User was found, add it!
516
        my %borrower = ldap_entry_2_hash($search->shift_entry,$cardnumber);
517
518
        # Generate a random password to keep the user secure if no password was mapped
519
        my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(! @ $ % ^ & *) );
520
        $borrower{'password'} = join("", @chars[ map { rand @chars } ( 1 .. 30 ) ]) unless $borrower{'password'};
521
522
        try {
523
            my @columns = Koha::Patrons->columns;
524
            my $patron = Koha::Patron->new(
525
                {
526
                    map { exists( $borrower{$_} ) ? ( $_ => $borrower{$_} ) : () } @columns
527
                }
528
            )->store;
529
            return $patron;
530
        } catch {
531
            return (undef, $_->{msg});
532
        };
533
    }
534
    else {
535
        return;
536
    }
537
538
}
539
446
1;
540
1;
447
__END__
541
__END__
448
542
(-)a/circ/circulation.pl (-1 / +15 lines)
Lines 244-250 if ( @$barcodes == 0 && $charges eq 'yes' ) { Link Here
244
if ($findborrower) {
244
if ($findborrower) {
245
    Koha::Plugins->call( 'patron_barcode_transform', \$findborrower );
245
    Koha::Plugins->call( 'patron_barcode_transform', \$findborrower );
246
    my $patron = Koha::Patrons->find( { cardnumber => $findborrower } );
246
    my $patron = Koha::Patrons->find( { cardnumber => $findborrower } );
247
    if ($patron) {
247
248
    # search cardnumber on LDAP server
249
    if ( C4::Context->config('useldapserver')
250
        and ( my $search_cardnumber = C4::Context->preference("SearchCardnumberWithLDAP") ) ne "never")
251
    {
252
        my $ldap_error;
253
        if ( $patron ) {
254
            ($patron, $ldap_error) = C4::Auth_with_ldap::updateborrower_ldap($patron) if $search_cardnumber eq "always";
255
        } else {
256
            ($patron, $ldap_error) = C4::Auth_with_ldap::findcardnumber_ldap($findborrower);
257
        }
258
        $template->param(ldap_error => $ldap_error) if $ldap_error;
259
    }
260
261
    if ( $patron ) {
248
        $borrowernumber = $patron->borrowernumber;
262
        $borrowernumber = $patron->borrowernumber;
249
    } else {
263
    } else {
250
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember="
264
        print $query->redirect( "/cgi-bin/koha/members/member.pl?quicksearch=1&circsearch=1&searchmember="
(-)a/circ/request-article.pl (-4 / +19 lines)
Lines 51-60 my $biblio = Koha::Biblios->find($biblionumber); Link Here
51
output_and_exit( $cgi, $cookie, $template, 'unknown_biblio' )
51
output_and_exit( $cgi, $cookie, $template, 'unknown_biblio' )
52
    unless $biblio;
52
    unless $biblio;
53
53
54
my $patron =
54
my $patron = undef;
55
      $patron_id         ? Koha::Patrons->find($patron_id)
55
if ( $patron_id ) {
56
    : $patron_cardnumber ? Koha::Patrons->find( { cardnumber => $patron_cardnumber } )
56
    $patron = Koha::Patrons->find($patron_id);
57
    :                      undef;
57
} elsif ( $patron_cardnumber ) {
58
    $patron = Koha::Patrons->find( { cardnumber => $patron_cardnumber } );
59
60
    # search cardnumber on LDAP server
61
    if ( C4::Context->config('useldapserver')
62
        and ( my $search_cardnumber = C4::Context->preference("SearchCardnumberWithLDAP") ) ne "never")
63
    {
64
        my $ldap_error;
65
        if ( $patron ) {
66
            ($patron, $ldap_error) = C4::Auth_with_ldap::updateborrower_ldap($patron) if $search_cardnumber eq "always";
67
        } else {
68
            ($patron, $ldap_error) = C4::Auth_with_ldap::findcardnumber_ldap($patron_cardnumber);
69
        }
70
        $template->param(ldap_error => $ldap_error) if $ldap_error;
71
    }
72
}
58
73
59
if ( $op eq 'cud-create' ) {
74
if ( $op eq 'cud-create' ) {
60
    my $borrowernumber = $cgi->param('borrowernumber');
75
    my $borrowernumber = $cgi->param('borrowernumber');
(-)a/installer/data/mysql/atomicupdate/bug_11808.pl (+14 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number => "11808",
5
    description => "Search cardnumber on the LDAP server if one is configured and add/update user.",
6
    up => sub {
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
9
        $dbh->do(q{
10
            INSERT INTO systempreferences (variable,value,explanation,options,type)
11
            VALUES('SearchCardnumberWithLDAP', 'never', 'Search for a cardnumber with LDAP when searching for a patron that does not exist locally. If the cardnumber is found via LDAP, the user is added or updated.', 'always|not_found|never', 'Choice');
12
        });
13
    },
14
};
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+1 lines)
Lines 721-726 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
721
('SCOLoadCheckoutsByDefault','1','','If enabled, load the list of a patrons checkouts when they log in to the Self Checkout','YesNo'),
721
('SCOLoadCheckoutsByDefault','1','','If enabled, load the list of a patrons checkouts when they log in to the Self Checkout','YesNo'),
722
('SCOUserCSS','',NULL,'Add CSS to be included in the SCO module in an embedded <style> tag.','free'),
722
('SCOUserCSS','',NULL,'Add CSS to be included in the SCO module in an embedded <style> tag.','free'),
723
('SCOUserJS','',NULL,'Define custom javascript for inclusion in the SCO module','free'),
723
('SCOUserJS','',NULL,'Define custom javascript for inclusion in the SCO module','free'),
724
('SearchCardnumberWithLDAP', 'never', 'Search for a cardnumber with LDAP when searching for a patron that does not exist locally. If the cardnumber is found via LDAP, the user is added or updated.', 'always|not_found|never', 'Choice'),
724
('SearchCancelledAndInvalidISBNandISSN','0',NULL,'Enable search for cancelled or invalid forms of ISBN/ISSN when performing ISBN/ISSN search (when using ES)','YesNo'),
725
('SearchCancelledAndInvalidISBNandISSN','0',NULL,'Enable search for cancelled or invalid forms of ISBN/ISSN when performing ISBN/ISSN search (when using ES)','YesNo'),
725
('SearchEngine','Zebra','Elasticsearch|Zebra','Search Engine','Choice'),
726
('SearchEngine','Zebra','Elasticsearch|Zebra','Search Engine','Choice'),
726
('SearchLimitLibrary', 'homebranch', 'homebranch|holdingbranch|both', "When limiting search results with a library or library group, use the item's home library, or holding library, or both.", 'Choice'),
727
('SearchLimitLibrary', 'homebranch', 'homebranch|holdingbranch|both', "When limiting search results with a library or library group, use the item's home library, or holding library, or both.", 'Choice'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+7 lines)
Lines 215-220 Patrons: Link Here
215
         - '<br><strong>NOTE:</strong> All patron fields can be used, but to work correctly they must contain a valid email address or an empty string.'
215
         - '<br><strong>NOTE:</strong> All patron fields can be used, but to work correctly they must contain a valid email address or an empty string.'
216
         - "Valid options are the <a href='https://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> of the borrowers table, separated by | (pipe)."
216
         - "Valid options are the <a href='https://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> of the borrowers table, separated by | (pipe)."
217
         - "Example: email|emailpro|B_email"
217
         - "Example: email|emailpro|B_email"
218
     -
219
         - pref: SearchCardnumberWithLDAP
220
           choices:
221
               always: Always
222
               not_found: If not found locally,
223
               never: Never
224
         - "search cardnumbers on the LDAP server. If the cardnumber is found via LDAP, the user is added or updated locally. Note : This feature only works if auth_by_bind is disabled in koha-conf.xml."
218
     -
225
     -
219
         - "When <a href='/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=EmailFieldPrimary'>EmailFieldPrimary</a> is set to '<strong>selected addresses</strong>', send email to all valid email addresses in the selected fields:"
226
         - "When <a href='/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=EmailFieldPrimary'>EmailFieldPrimary</a> is set to '<strong>selected addresses</strong>', send email to all valid email addresses in the selected fields:"
220
         - pref: EmailFieldSelection
227
         - pref: EmailFieldSelection
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt (+5 lines)
Lines 787-792 Link Here
787
        <p>Item checked out</p>
787
        <p>Item checked out</p>
788
    [% END %]
788
    [% END %]
789
789
790
    [% IF (ldap_error) %]
791
        <div class="dialog alert">
792
            An error occured while searching for cardnumber on the LDAP server : [% ldap_error | html %]
793
        </div>
794
    [% END %]
790
    <!-- BARCODE ENTRY -->
795
    <!-- BARCODE ENTRY -->
791
796
792
    [% IF patron %]
797
    [% IF patron %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/request-article.tt (+7 lines)
Lines 93-98 Link Here
93
[% END #/ WRAPPER sub-header.inc %]
93
[% END #/ WRAPPER sub-header.inc %]
94
94
95
[% WRAPPER 'main-container.inc' aside='biblio-view-menu' %]
95
[% WRAPPER 'main-container.inc' aside='biblio-view-menu' %]
96
97
    [% IF (ldap_error) %]
98
        <div class="dialog alert">
99
            An error occured while searching for cardnumber on the LDAP server : [% ldap_error | html %]
100
        </div>
101
    [% END %]
102
96
    <h1>Request article from [% INCLUDE 'biblio-title.inc' link = 1 %]</h1>
103
    <h1>Request article from [% INCLUDE 'biblio-title.inc' link = 1 %]</h1>
97
    [% IF error_message %]
104
    [% IF error_message %]
98
        <div class="alert alert-warning">
105
        <div class="alert alert-warning">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt (+6 lines)
Lines 115-120 Link Here
115
                        </div>
115
                        </div>
116
                    [% END %]
116
                    [% END %]
117
117
118
                    [% IF (ldap_error) %]
119
                        <div class="dialog alert">
120
                            An error occured while searching for cardnumber on the LDAP server : [% ldap_error | html %]
121
                        </div>
122
                    [% END %]
123
118
                    [% IF CAN_user_borrowers_edit_borrowers || CAN_user_tools_manage_patron_lists %]
124
                    [% IF CAN_user_borrowers_edit_borrowers || CAN_user_tools_manage_patron_lists %]
119
                        [% columns.unshift('checkbox') | html %]
125
                        [% columns.unshift('checkbox') | html %]
120
                    [% END %]
126
                    [% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (+17 lines)
Lines 285-290 Link Here
285
        </div>
285
        </div>
286
    [% END %]
286
    [% END %]
287
287
288
    [% IF ( messagetransfert ) %]
289
        <div class="dialog message">
290
            <h2>Hold found for ([% nextreservtitle | html %]), please transfer</h2>
291
            <p>Hold placed by : <strong> [% nextreservsurname | html %] [% nextreservfirstname | html %]</strong> at : <strong> [% branchname | html %] </strong>, Please transfer this item.
292
            </p>
293
            <form name="cancelReservewithtransfert" action="branchreserves.pl" method="post">
294
                <input type="submit" class="button" />
295
            </form>
296
        </div>
297
    [% END %]
298
299
    [% IF (ldap_error) %]
300
        <div class="dialog alert">
301
            An error occured while searching for cardnumber on the LDAP server : [% ldap_error | html %]
302
        </div>
303
    [% END %]
304
288
    [% UNLESS ( multi_hold ) %]
305
    [% UNLESS ( multi_hold ) %]
289
        <h2>Place a hold on [% INCLUDE 'biblio-title.inc' link = 1 %] [% IF biblio.author %]by [% biblio.author | html %][% END %]</h2>
306
        <h2>Place a hold on [% INCLUDE 'biblio-title.inc' link = 1 %] [% IF biblio.author %]by [% biblio.author | html %][% END %]</h2>
290
    [% ELSE %]
307
    [% ELSE %]
(-)a/members/member.pl (+14 lines)
Lines 53-58 if ( $quicksearch and $searchmember && !$circsearch ) { Link Here
53
        $branchcode = $userenv->{'branch'};
53
        $branchcode = $userenv->{'branch'};
54
    }
54
    }
55
    my $patron = Koha::Patrons->find( { cardnumber => $searchmember } );
55
    my $patron = Koha::Patrons->find( { cardnumber => $searchmember } );
56
57
    # search cardnumber on LDAP server
58
    if ( C4::Context->config('useldapserver')
59
        and ( my $search_cardnumber = C4::Context->preference("SearchCardnumberWithLDAP") ) ne "never")
60
    {
61
        my $ldap_error;
62
        if ( $patron ) {
63
            ($patron, $ldap_error) = C4::Auth_with_ldap::updateborrower_ldap($patron) if $search_cardnumber eq "always";
64
        } else {
65
            ($patron, $ldap_error) = C4::Auth_with_ldap::findcardnumber_ldap($searchmember);
66
        }
67
        $template->param(ldap_error => $ldap_error) if $ldap_error;
68
    }
69
56
    if (
70
    if (
57
        $patron
71
        $patron
58
        and (  ( $branchcode and $patron->branchcode eq $branchcode )
72
        and (  ( $branchcode and $patron->branchcode eq $branchcode )
(-)a/reserve/request.pl (-1 / +14 lines)
Lines 198-203 if ( $op eq 'cud-move' ) { Link Here
198
198
199
if ($findborrower) {
199
if ($findborrower) {
200
    my $patron = Koha::Patrons->find( { cardnumber => $findborrower } );
200
    my $patron = Koha::Patrons->find( { cardnumber => $findborrower } );
201
202
    # search cardnumber on LDAP server
203
    if ( C4::Context->config('useldapserver')
204
        and ( my $search_cardnumber = C4::Context->preference("SearchCardnumberWithLDAP") ) ne "never")
205
    {
206
        my $ldap_error;
207
        if ( $patron ) {
208
            ($patron, $ldap_error) = C4::Auth_with_ldap::updateborrower_ldap($patron) if $search_cardnumber eq "always";
209
        } else {
210
            ($patron, $ldap_error) = C4::Auth_with_ldap::findcardnumber_ldap($findborrower);
211
        }
212
        $template->param(ldap_error => $ldap_error) if $ldap_error;
213
    }
214
201
    $borrowernumber_hold = $patron->borrowernumber if $patron;
215
    $borrowernumber_hold = $patron->borrowernumber if $patron;
202
}
216
}
203
217
204
- 

Return to bug 11808