From b55edb82cbea617962950a057f3cd3862c0cdb42 Mon Sep 17 00:00:00 2001
From: Alex Buckley <alexbuckley@catalyst.net.nz>
Date: Mon, 4 Apr 2022 19:22:16 +1200
Subject: [PATCH] Bug 30444: Add shibboleth login to self checkout

This patch adds a 'Shibboleth' option to the SelfCheckoutByLogin system
preference. When 'Shibboleth' is selected the user should be logged
straight into the self check module - assuming the AutoSelfCheckAllowed,
AutoSelfCheckID and AutoSelfCheckPass system preferences are set.

Test plan:

1. Have your Koha setup to do Shibboleth login
2. Set the following system preferences:
- AutoSelfCheckAllowed => 'Allow'
- AutoSelfCheckId and AutoSelfCheckPass => Set these to a patron with
'circulate' permissions
- WebBasedSelfCheck -> 'Enable'
- OpacShibOnly -> "Don't allow"
3. Visit the self checkout page /cgi-bin/koha/sco/sco-main.pl and notice
a local login page loads
4. Apply patchset, update database and restart services
5. Set the new syspref:
- SelfCheckoutByLogin -> 'Shibboleth'
6. Visit the self checkout page and notice you're logged into the sco
interface straight away, without the local login page loading

Sponsored-by: Catalyst IT
---
 C4/Auth.pm                                    |  3 ++-
 ..._30444-edit_SelfCheckoutByLogin_syspref.pl | 18 ++++++++++++++
 installer/data/mysql/mandatory/sysprefs.sql   |  2 +-
 .../admin/preferences/circulation.pref        |  5 ++--
 opac/sco/sco-main.pl                          | 24 ++++++++++++++++---
 5 files changed, 45 insertions(+), 7 deletions(-)
 create mode 100755 installer/data/mysql/atomicupdate/bug_30444-edit_SelfCheckoutByLogin_syspref.pl

diff --git a/C4/Auth.pm b/C4/Auth.pm
index c1c27e0eb95..6d33f08aed0 100644
--- a/C4/Auth.pm
+++ b/C4/Auth.pm
@@ -1038,7 +1038,7 @@ sub checkauth {
             my ( $return, $cardnumber );
 
             # If shib is enabled and we have a shib login, does the login match a valid koha user
-            if ( $shib && $shib_login ) {
+            if ( $shib && $shib_login && !$query->param('userid')) {
                 my $retuserid;
 
                 # Do not pass password here, else shib will not be checked in checkpw.
@@ -1137,6 +1137,7 @@ sub checkauth {
                     (
                         ( $type eq 'opac' )
                         && C4::Context->preference('OPACShibOnly')
+			&& C4::Context->preference('SelfCheckoutByLogin') ne 'shibboleth'
                     )
                     || ( ( $type ne 'opac' )
                         && C4::Context->preference('staffShibOnly') )
diff --git a/installer/data/mysql/atomicupdate/bug_30444-edit_SelfCheckoutByLogin_syspref.pl b/installer/data/mysql/atomicupdate/bug_30444-edit_SelfCheckoutByLogin_syspref.pl
new file mode 100755
index 00000000000..018eaf0de0f
--- /dev/null
+++ b/installer/data/mysql/atomicupdate/bug_30444-edit_SelfCheckoutByLogin_syspref.pl
@@ -0,0 +1,18 @@
+use Modern::Perl;
+
+return {
+    bug_number => "30444",
+    description => "Edit existing system preference SelfCheckoutByLogin",
+    up => sub {
+        my ($args) = @_;
+        my ($dbh, $out) = @$args{qw(dbh out)};
+
+        if ( C4::Context->preference('SelfCheckoutByLogin') ) {
+            $dbh->do(q{ UPDATE systempreferences SET value="cardnumber" WHERE variable="SelfCheckoutByLogin" });
+        } else {
+            $dbh->do(q{ UPDATE systempreferences SET value="username" WHERE variable="SelfCheckoutByLogin" });
+        }
+
+        $dbh->do(q{ UPDATE systempreferences SET options="cardnumber|username|shibboleth", type="Choice", explanation="Have patrons log in to the web-based self checkout system with their username/password, their cardnumber, or using Shibboleth" WHERE variable="SelfCheckoutByLogin" });
+    },
+};
diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql
index 1b029aa5ee8..59022d6d21c 100644
--- a/installer/data/mysql/mandatory/sysprefs.sql
+++ b/installer/data/mysql/mandatory/sysprefs.sql
@@ -607,7 +607,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
 ('SelfCheckInTimeout','120','','Define the number of seconds before the self check-in module times out.','Integer'),
 ('SelfCheckInUserCSS','',NULL,'Add CSS to be included in the self check-in module in an embedded <style> tag.','free'),
 ('SelfCheckInUserJS','',NULL,'Define custom javascript for inclusion in the self check-in module.','free'),
-('SelfCheckoutByLogin','1',NULL,'Have patrons login into the web-based self checkout system with their username/password or their cardnumber','YesNo'),
+('SelfCheckoutByLogin','username','username|cardnumber|shibboleth','Have patrons log in to the web-based self checkout system with their username/password, their cardnumber, or using Shibboleth','Choice'),
 ('SelfCheckReceiptPrompt','1','NULL','If ON, print receipt dialog pops up when self checkout is finished','YesNo'),
 ('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'),
 ('SendAllEmailsTo','',NULL,'All emails will be redirected to this email if it is not empty','free'),
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
index 8f77412eb49..626b9d4a405 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -1116,8 +1116,9 @@ Circulation:
             - Have patrons log into the web-based self checkout system with their
             - pref: SelfCheckoutByLogin
               choices:
-                  1: username and password
-                  0: cardnumber
+                  username: username and password
+                  cardnumber: cardnumber
+                  shibboleth: Shibboleth login
             - ".</br>NOTE: If using 'cardnumber' and AutoSelfCheckAllowed you should set SelfCheckAllowByIPRanges to prevent brute force attacks to gain patron information outside the library."
         -
             - "Time out the current patron's web-based self checkout system login after"
diff --git a/opac/sco/sco-main.pl b/opac/sco/sco-main.pl
index a89f2538d6e..b4bede9a515 100755
--- a/opac/sco/sco-main.pl
+++ b/opac/sco/sco-main.pl
@@ -33,6 +33,7 @@ use Modern::Perl;
 use CGI qw ( -utf8 );
 
 use C4::Auth qw( in_iprange get_template_and_user checkpw );
+use C4::Auth_with_shibboleth qw( shib_ok get_login_shib );
 use C4::Circulation qw( barcodedecode AddReturn CanBookBeIssued AddIssue CanBookBeRenewed AddRenewal );
 use C4::Reserves;
 use C4::Output qw( output_html_with_http_headers );
@@ -117,7 +118,20 @@ my $issuer   = Koha::Patrons->find( $issuerid )->unblessed;
 
 my $patronid = $jwt ? Koha::Token->new->decode_jwt({ token => $jwt }) : undef;
 unless ( $patronid ) {
-    if ( C4::Context->preference('SelfCheckoutByLogin') ) {
+    if ( C4::Context->preference('SelfCheckoutByLogin') eq 'shibboleth' ) {
+        # Do Shibboleth login
+        my ($shib, $shib_login, $patron, $value, $shib_config, $match_point);
+        $shib = C4::Context->config('useshibboleth') && shib_ok();
+        $shib_login = $shib ? get_login_shib() : undef;
+        $shib_config = C4::Context->config('shibboleth');
+        $match_point = $shib_config->{matchpoint};
+        $patron = Koha::Patrons->find({ $match_point => $shib_login }) if $shib_login;
+        if ($patron) {
+           $patronid = $patron->userid;
+        } else {
+          undef $patronid;
+        }
+    } elsif ( C4::Context->preference('SelfCheckoutByLogin') eq 'username' ) {
         my $dbh = C4::Context->dbh;
         ( undef, $patronid ) = checkpw( $dbh, $patronlogin, $patronpw );
     }
@@ -130,8 +144,12 @@ unless ( $patronid ) {
 
 my $patron;
 if ( $patronid ) {
-    Koha::Plugins->call( 'patron_barcode_transform', \$patronid );
-    $patron = Koha::Patrons->find( { cardnumber => $patronid } );
+    if ( C4::Context->preference('SelfCheckoutByLogin') eq 'shibboleth' ) {
+        $patron = Koha::Patrons->find( { userid => $patronid } );
+    } else {
+        Koha::Plugins->call( 'patron_barcode_transform', \$patronid );
+        $patron = Koha::Patrons->find( { cardnumber => $patronid } );
+    }
 }
 
 undef $jwt unless $patron;
-- 
2.20.1