From db0d73fd5979efe58b202dd6cf056683eb35551e Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Tue, 8 Sep 2020 08:13:13 -0400
Subject: [PATCH] Add permission support to combined search (#1707)

- Resolves VUFIND-1421.
---
 config/vufind/combined.ini                          | 10 ++++++++++
 config/vufind/permissionBehavior.ini                |  5 +++++
 .../src/VuFind/Controller/CombinedController.php    |  5 ++++-
 .../src/VuFind/Controller/Plugin/Permission.php     | 13 +++++++++++++
 .../templates/combined/results-ajax.phtml           |  9 +++++++++
 .../templates/combined/results-list.phtml           |  9 +++++++++
 .../bootstrap3/templates/error/loginForAccess.phtml |  4 ++++
 7 files changed, 54 insertions(+), 1 deletion(-)
 create mode 100644 themes/bootstrap3/templates/error/loginForAccess.phtml

diff --git a/config/vufind/combined.ini b/config/vufind/combined.ini
index b255c6242d4..f4354f3e216 100644
--- a/config/vufind/combined.ini
+++ b/config/vufind/combined.ini
@@ -33,6 +33,9 @@
 ;          ([SearchTabsFilters] in config.ini). In this case, make sure the filters
 ;          are equal in both configurations to make the correct tab active when
 ;          clicking more results from the combined view.
+; permission = The name of a permission which must be granted in order to display
+;              results in this column. This permission must also have an appropriate
+;              deniedTemplateBehavior defined in permissionBehavior.ini.
 ; shard = Limit results to one or more shards (use names from searches.ini, not
 ;         URLs). Use multiple "shard[] = ..." lines if multiple shards are needed.
 ;
@@ -94,6 +97,13 @@ more_link = "More EDS results"
 ajax = true
 ; limit = 10
 
+;[EIT]
+;label = EIT
+;sublabel = "database results"
+;more_link = "More EIT results"
+;ajax = true
+;permission = access.EITModule
+
 ; This section controls recommendation modules displayed in combination with
 ; combined search results. Right now, only the top and bottom areas are
 ; supported. See searches.ini for a list of available modules. Not all modules
diff --git a/config/vufind/permissionBehavior.ini b/config/vufind/permissionBehavior.ini
index 3390fd023d8..c519d4aa7bc 100644
--- a/config/vufind/permissionBehavior.ini
+++ b/config/vufind/permissionBehavior.ini
@@ -78,6 +78,11 @@ defaultDeniedTemplateBehavior = false
 ;controllerAccess[*] = access.VuFindInterface
 ;controllerAccess[VuFind\Controller\SearchController] = access.SearchResults
 
+; Configuration for EIT (needed to make it behave correctly in combined
+; searches):
+[access.EITModule]
+deniedTemplateBehavior = showTemplate:error/loginForAccess
+
 ; Example configuration for non-standard favorites permission behavior:
 ;[feature.Favorites]
 ;deniedTemplateBehavior = "showMessage:Login for Favorites"
diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php
index 2e6b6dbfca5..01d8dfdc636 100644
--- a/module/VuFind/src/VuFind/Controller/CombinedController.php
+++ b/module/VuFind/src/VuFind/Controller/CombinedController.php
@@ -181,7 +181,10 @@ class CombinedController extends AbstractSearch
             $combinedResults[$current]['domId']
                 = 'combined_' . str_replace(':', '____', $current);
 
-            $combinedResults[$current]['view'] = ($settings['ajax'] ?? false)
+            $permissionDenied = isset($settings['permission'])
+                && !$this->permission()->isAuthorized($settings['permission']);
+            $isAjax = $settings['ajax'] ?? false;
+            $combinedResults[$current]['view'] = ($permissionDenied || $isAjax)
                 ? $this->createViewModel(['results' => $results])
                 : $this->forwardTo($controller, $action);
 
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Permission.php b/module/VuFind/src/VuFind/Controller/Plugin/Permission.php
index 746f1802b4e..3096f185086 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Permission.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Permission.php
@@ -85,6 +85,19 @@ class Permission extends AbstractPlugin implements LoggerAwareInterface,
         $this->authManager = $auth;
     }
 
+    /**
+     * Check if a permission is authorized, returning a boolean value without
+     * applying any additional behavior.
+     *
+     * @param string $permission Permission to check
+     *
+     * @return bool
+     */
+    public function isAuthorized($permission)
+    {
+        return $this->permissionManager->isAuthorized($permission);
+    }
+
     /**
      * Check if a permission is denied; if so, throw an exception or return an
      * error response as configured in permissionBehavior.ini.
diff --git a/themes/bootstrap3/templates/combined/results-ajax.phtml b/themes/bootstrap3/templates/combined/results-ajax.phtml
index b9240468524..fb04e1f67fd 100644
--- a/themes/bootstrap3/templates/combined/results-ajax.phtml
+++ b/themes/bootstrap3/templates/combined/results-ajax.phtml
@@ -24,6 +24,15 @@ JS;
 
 ?>
 <h2><?=$this->transEsc($currentSearch['label'])?></h2>
+
+<?php $permission = $currentSearch['permission'] ?? null ?>
+<?php if (isset($permission) && !$this->permission()->allowDisplay($permission)): ?>
+  <?php if ($block = $this->permission()->getAlternateContent($permission)): ?>
+    <?=$block?>
+  <?php endif; ?>
+  <?php return; // if permission is denied, don't render the rest of the template! ?>
+<?php endif; ?>
+
 <p><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> <?=$this->transEsc("Loading")?>...</p>
 <?=$this->inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
 <noscript><?=$this->transEsc('Please enable JavaScript.')?></noscript>
diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml
index 99a0a95058d..24f2b22a6ff 100644
--- a/themes/bootstrap3/templates/combined/results-list.phtml
+++ b/themes/bootstrap3/templates/combined/results-list.phtml
@@ -19,6 +19,15 @@
 <?php if (isset($currentSearch['sublabel'])): ?>
   <p><i><?=$this->transEsc($currentSearch['sublabel'])?></i></p>
 <?php endif; ?>
+
+<?php $permission = $currentSearch['permission'] ?? null ?>
+<?php if (isset($permission) && !$this->permission()->allowDisplay($permission)): ?>
+  <?php if ($block = $this->permission()->getAlternateContent($permission)): ?>
+    <?=$block?>
+  <?php endif; ?>
+  <?php return; // if permission is denied, don't render the rest of the template! ?>
+<?php endif; ?>
+
 <div class="clearfix">
   <div class="pull-left flip help-block">
     <?php if ($recordTotal > 0): ?>
diff --git a/themes/bootstrap3/templates/error/loginForAccess.phtml b/themes/bootstrap3/templates/error/loginForAccess.phtml
new file mode 100644
index 00000000000..3e90cee9614
--- /dev/null
+++ b/themes/bootstrap3/templates/error/loginForAccess.phtml
@@ -0,0 +1,4 @@
+<?php // This can be used as a permission denied behavior; see example in permissionBehavior.ini... ?>
+<a class="login" href="<?=$this->url('myresearch-home')?>" rel="nofollow">
+  <strong><?=$this->transEsc('Login for full access')?></strong>
+</a>
-- 
GitLab