From bacff96620f0a8917ad10f438a69fe6c7eb91b09 Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Fri, 20 Nov 2015 14:47:21 -0500
Subject: [PATCH] Implemented privacy mode. - Disables database storage of
 personally identifying information.

---
 config/vufind/config.ini                      |  7 ++
 module/VuFind/src/VuFind/Auth/Manager.php     | 39 ++++++++--
 .../src/VuFind/Config/AccountCapabilities.php |  3 +-
 .../VuFind/src/VuFind/Db/Row/PrivateUser.php  | 77 +++++++++++++++++++
 module/VuFind/src/VuFind/Db/Table/User.php    |  6 +-
 5 files changed, 124 insertions(+), 8 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/Db/Row/PrivateUser.php

diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 3f9b3c490cb..ebf9d2603f0 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -290,6 +290,13 @@ ils_encryption_key = false
 ;minimum_password_length = 4
 ;maximum_password_length = 32
 
+; Uncomment this line to switch on "privacy mode" in which no user information
+; will be stored in the database. Note that this is incompatible with social
+; features, password resets, and many other features. It is not recommended for
+; use with "Database" authentication, since the user will be forced to create a
+; new account upon every login.
+;privacy = true
+
 ; See the comments in library/VF/Auth/MultiAuth.php for full details
 ; on using multiple authentication methods.  Note that MultiAuth assumes login
 ; with username and password, so some methods (i.e. Shibboleth) may not be
diff --git a/module/VuFind/src/VuFind/Auth/Manager.php b/module/VuFind/src/VuFind/Auth/Manager.php
index d4b0fa0eca5..8bcc6768f78 100644
--- a/module/VuFind/src/VuFind/Auth/Manager.php
+++ b/module/VuFind/src/VuFind/Auth/Manager.php
@@ -374,6 +374,7 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
         // Clear out the cached user object and session entry.
         $this->currentUser = false;
         unset($this->session->userId);
+        unset($this->session->userDetails);
         $this->cookieManager->set('loggedOut', 1);
 
         // Destroy the session for good measure, if requested.
@@ -408,11 +409,22 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
     {
         // If user object is not in cache, but user ID is in session,
         // load the object from the database:
-        if (!$this->currentUser && isset($this->session->userId)) {
-            $results = $this->userTable
-                ->select(['id' => $this->session->userId]);
-            $this->currentUser = count($results) < 1
-                ? false : $results->current();
+        if (!$this->currentUser) {
+            if (isset($this->session->userId)) {
+                // normal mode
+                $results = $this->userTable
+                    ->select(['id' => $this->session->userId]);
+                $this->currentUser = count($results) < 1
+                    ? false : $results->current();
+            } else if (isset($this->session->userDetails)) {
+                // privacy mode
+                $results = $this->userTable->createRow();
+                $results->exchangeArray($this->session->userDetails);
+                $this->currentUser = $results;
+            } else {
+                // unexpected state
+                $this->currentUser = false;
+            }
         }
         return $this->currentUser;
     }
@@ -441,6 +453,17 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
         return false;
     }
 
+    /**
+     * Are we in privacy mode?
+     *
+     * @return bool
+     */
+    public function inPrivacyMode()
+    {
+        return isset($this->config->Authentication->privacy)
+            && $this->config->Authentication->privacy;
+    }
+
     /**
      * Updates the user information in the session.
      *
@@ -451,7 +474,11 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
     public function updateSession($user)
     {
         $this->currentUser = $user;
-        $this->session->userId = $user->id;
+        if ($this->inPrivacyMode()) {
+            $this->session->userDetails = $user->toArray();
+        } else {
+            $this->session->userId = $user->id;
+        }
         $this->cookieManager->clear('loggedOut');
     }
 
diff --git a/module/VuFind/src/VuFind/Config/AccountCapabilities.php b/module/VuFind/src/VuFind/Config/AccountCapabilities.php
index 9efc100b967..09b9a4f2dc4 100644
--- a/module/VuFind/src/VuFind/Config/AccountCapabilities.php
+++ b/module/VuFind/src/VuFind/Config/AccountCapabilities.php
@@ -142,6 +142,7 @@ class AccountCapabilities
      */
     protected function isAccountAvailable()
     {
-        return $this->auth->loginEnabled();
+        // We can't use account features if login is broken or privacy is on:
+        return $this->auth->loginEnabled() && !$this->auth->inPrivacyMode();
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Row/PrivateUser.php b/module/VuFind/src/VuFind/Db/Row/PrivateUser.php
new file mode 100644
index 00000000000..46c9a081c58
--- /dev/null
+++ b/module/VuFind/src/VuFind/Db/Row/PrivateUser.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Fake database row to represent a user in privacy mode.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2015.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Db_Row
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+namespace VuFind\Db\Row;
+
+/**
+ * Fake database row to represent a user in privacy mode.
+ *
+ * @category VuFind2
+ * @package  Db_Row
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+class PrivateUser extends User
+{
+    /**
+     * __get
+     *
+     * @param string $name Field to retrieve.
+     *
+     * @throws Exception\InvalidArgumentException
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        return array_key_exists($name, $this->data) ? parent::__get($name) : null;
+    }
+
+    /**
+     * Whether library cards are enabled
+     *
+     * @return bool
+     */
+    public function libraryCardsEnabled()
+    {
+        return false; // not supported in this context
+    }
+
+    /**
+     * Save
+     *
+     * @return int
+     */
+    public function save()
+    {
+        $this->initialize();
+        $this->id = -1; // fake ID
+        $session = new \Zend\Session\Container('Account');
+        $session->userDetails = $this->toArray();
+        return 1;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Db/Table/User.php b/module/VuFind/src/VuFind/Db/Table/User.php
index 9444c836e07..c8619c20ae3 100644
--- a/module/VuFind/src/VuFind/Db/Table/User.php
+++ b/module/VuFind/src/VuFind/Db/Table/User.php
@@ -52,7 +52,11 @@ class User extends Gateway
      */
     public function __construct(\Zend\Config\Config $config)
     {
-        parent::__construct('user', 'VuFind\Db\Row\User');
+        // Use a special row class when we're in privacy mode:
+        $privacy = isset($config->Authentication->privacy)
+            && $config->Authentication->privacy;
+        $rowClass = 'VuFind\Db\Row\\' . ($privacy ? 'PrivateUser' : 'User');
+        parent::__construct('user', $rowClass);
         $this->config = $config;
     }
 
-- 
GitLab