LP#1533329: Selectively disallow opt-in based on patron's home library
authorJeff Davis <jeff.davis@bc.libraries.coop>
Tue, 12 Jan 2016 19:58:13 +0000 (11:58 -0800)
committerGalen Charlton <gmc@esilibrary.com>
Thu, 3 Mar 2016 01:34:24 +0000 (20:34 -0500)
Patrons from Library A can "opt in" to sharing their personal
information with Library B.  However, hitherto there has been no way for
Library A to prevent their patrons from being opted in at other
libraries.  This would be useful if, for example, Library A is a school
library and does not want other libraries in the consortium to have
access to student accounts.

This commit adds the ability to selectively disallow opt-in by home
library.  Specifically, it makes the following changes:

1. Adds an org setting (org.restrict_opt_to_depth) that governs opt-in
restrictions.  All org units within the home OU's section of the org
tree at or below depth X are within the patron's opt-in scope; opt-in is
disallowed at any library outside of that scope.  If the setting is not
enabled, the entire org tree is effectively within scope.  (None of this
should be confused with the opt boundary, which defines the point at
which patrons need to be opted in vs. just granting access without
opt-in.)

2. Modifies open-ils.actor.user.org_unit_opt_in.check so that it checks
that setting and determines if the current work OU is within the
patron's opt-in scope.  If opt-in is not permitted at this work OU,
an appropriate response is returned.

3. Handles the response in both staff clients.  If opt-in is disallowed,
staff will see an alert which says, "This patron's record is not
viewable at your library."

Signed-off-by: Jeff Davis <jeff.davis@bc.libraries.coop>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.restrict_opt_to_depth_setting.sql [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
Open-ILS/xul/staff_client/server/patron/barcode_entry.xul

index 40bb6a6..07e5d6d 100644 (file)
@@ -3148,6 +3148,7 @@ __PACKAGE__->register_method(
         @param $auth The auth token
         @param user_id The ID of the user to test
         @return 1 if the user has opted in at the specified org,
+            2 if opt-in is disallowed for the user's home org,
             event on error, and 0 otherwise. /
 );
 sub user_opt_in_at_org {
@@ -3174,6 +3175,17 @@ sub user_opt_in_at_org {
 
     return 1 if grep $_ eq $user->home_ou, @$opt_orgs;
 
+    # check whether opt-in is restricted at the user's home library
+    my $opt_restrict_depth = $U->ou_ancestor_setting_value($user->home_ou, 'org.restrict_opt_to_depth');
+    if ($opt_restrict_depth) {
+        my $restrict_ancestor = $U->org_unit_ancestor_at_depth($user->home_ou, $opt_restrict_depth);
+        my $unrestricted_orgs = $U->get_org_descendants($restrict_ancestor);
+
+        # opt-in is disallowed unless the workstation org is within the home
+        # library's opt-in scope
+        return 2 unless grep $_ eq $e->requestor->ws_ou, @$unrestricted_orgs;
+    }
+
     my $vals = $e->search_actor_usr_org_unit_opt_in(
         {org_unit=>$opt_orgs, usr=>$user_id},{idlist=>1});
 
index 426e235..11a7c28 100644 (file)
@@ -16234,3 +16234,18 @@ INSERT INTO config.org_unit_setting_type
              'coust', 'description'),
          'bool');
 
+INSERT INTO config.org_unit_setting_type
+    (name, grp, label, description, datatype)
+    VALUES
+        ('org.restrict_opt_to_depth',
+         'sec',
+         oils_i18n_gettext('org.restrict_opt_to_depth',
+            'Restrict patron opt-in to home library and related orgs at specified depth',
+            'coust', 'label'),
+         oils_i18n_gettext('org.restrict_opt_to_depth',
+            'Patrons at this library can only be opted-in at org units which are within the '||
+            'library''s section of the org tree, at or below the depth specified by this setting. '||
+            'They cannot be opted in at any other libraries.',
+            'coust', 'description'),
+        'integer');
+
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.restrict_opt_to_depth_setting.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.restrict_opt_to_depth_setting.sql
new file mode 100644 (file)
index 0000000..6e0a3d8
--- /dev/null
@@ -0,0 +1,21 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+INSERT INTO config.org_unit_setting_type
+    (name, grp, label, description, datatype)
+    VALUES
+        ('org.restrict_opt_to_depth',
+         'sec',
+         oils_i18n_gettext('org.restrict_opt_to_depth',
+            'Restrict patron opt-in to home library and related orgs at specified depth',
+            'coust', 'label'),
+         oils_i18n_gettext('org.restrict_opt_to_depth',
+            'Patrons at this library can only be opted-in at org units which are within the '||
+            'library''s section of the org tree, at or below the depth specified by this setting. '||
+            'They cannot be opted in at any other libraries.',
+            'coust', 'description'),
+        'integer');
+
+COMMIT;
+
index 216b186..6a9e8fa 100644 (file)
@@ -18,5 +18,7 @@
 <div class="alert alert-warning" ng-show="bcNotFound">
   [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
 </div>
-
+<div class="alert alert-warning" ng-show="optInRestricted">
+  [% l("This patron's record is not viewable at your library.") %]
+</div>
 
index 6a184ae..9cf3b45 100644 (file)
@@ -701,6 +701,7 @@ function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc) {
 
     $scope.submitBarcode = function(args) {
         $scope.bcNotFound = null;
+        $scope.optInRestricted = false;
         if (!args.barcode) return;
 
         // blur so next time it's set to true it will re-apply select()
@@ -741,6 +742,13 @@ function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc) {
                 alert(evt); // FIXME
                 return;
             }
+
+            if (optInResp == 2) {
+                // opt-in disallowed at this location by patron's home library
+                $scope.optInRestricted = true;
+                $scope.selectMe = true;
+                return;
+            }
            
             if (optInResp == 1) {
                 // opt-in handled or not needed
index 2aedce3..29f8c38 100644 (file)
@@ -3,6 +3,7 @@ staff.patron.barcode_entry.check_out=Check Out
 staff.patron.barcode_entry.no_barcode=No barcode entered.
 staff.patron.barcode_entry.barcode_retrieval_problem=Problem retrieving %1$s.  Please report this message: \n%2$s
 staff.patron.barcode_entry.barcode_not_found=Barcode %1$s not found.
+staff.patron.barcode_entry.opt_in_restricted=This patron's record is not viewable at your library.
 staff.patron.barcode_entry.consent_from_patron=Does patron %1$s, %2$s from %3$s (%4$s) consent to having their personal information shared with your library?
 staff.patron.barcode_entry.patron_consent_title=Patron/Library Opt-In Confirmation
 staff.patron.barcode_entry.patron_consent_accept=Accept
index fa613b2..9c57135 100644 (file)
                         throw(r);
                     } else {
 
-                        if (r == 0) {
+                        if (r == 2) {
+                            // opt-in is disallowed at this location by patron's home library
+                            sound.bad();
+                            add_msg($("patronStrings").getFormattedString('staff.patron.barcode_entry.opt_in_restricted'));
+                            return;
+                        }
+
+                        else if (r == 0) {
 
                             JSAN.use('patron.util');
                             var parts;