diff --git a/config/vufind/config.ini b/config/vufind/config.ini index 728a9ff30beee58d4317f345b3c953288d60e6c1..518994e61873b5bf99b3f05b1a7e890ddb55cfa3 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -381,6 +381,10 @@ force_first_scheduled_email = false ; also supported as the primary authentication mechanism for some ILS drivers (e.g. ; Alma). In these cases, ChoiceAuth is not needed, and ILS should be configured as ; the Authentication method; see the ILS driver's configuration for possible options. +; +; Also note that the Email method stores hashes in your database's auth_hash table. +; You should run the "php $VUFIND_HOME/public/index.php util expire_auth_hashes" +; utility periodically to clean out old data in this table. [Authentication] ;method = LDAP ;method = ILS diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index fc4f62739148ce618f688d5ab9e098b089a681e2..b0e499d1418fb9ab1934fb13054fcbd98190417b 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -430,6 +430,7 @@ $config = [ 'VuFindHttp\HttpService' => 'VuFind\Service\HttpServiceFactory', 'VuFindSearch\Service' => 'VuFind\Service\SearchServiceFactory', 'Zend\Db\Adapter\Adapter' => 'VuFind\Db\AdapterFactory', + 'Zend\Http\PhpEnvironment\RemoteAddress' => 'VuFind\Http\PhpEnvironment\RemoteAddressFactory', 'Zend\Mvc\I18n\Translator' => 'VuFind\I18n\Translator\TranslatorFactory', 'Zend\Session\SessionManager' => 'VuFind\Session\ManagerFactory', ], @@ -526,6 +527,7 @@ $config = [ 'config_reader' => [ /* see VuFind\Config\PluginManager for defaults */ ], // PostgreSQL sequence mapping 'pgsql_seq_mapping' => [ + 'auth_hash' => ['id', 'auth_hash_id_seq'], 'comments' => ['id', 'comments_id_seq'], 'external_session' => ['id', 'external_session_id_seq'], 'oai_resumption' => ['id', 'oai_resumption_id_seq'], diff --git a/module/VuFind/sql/migrations/pgsql/6.1/004-add-auth-hash-table.sql b/module/VuFind/sql/migrations/pgsql/6.1/004-add-auth-hash-table.sql new file mode 100644 index 0000000000000000000000000000000000000000..5898a0ebc3eab531d5aa76e1915812090b60de51 --- /dev/null +++ b/module/VuFind/sql/migrations/pgsql/6.1/004-add-auth-hash-table.sql @@ -0,0 +1,15 @@ +-- +-- Table structure for table auth_hash +-- + +CREATE TABLE auth_hash ( +id BIGSERIAL, +session_id varchar(128), +hash varchar(255), +type varchar(50), +data text, +created timestamp NOT NULL default '1970-01-01 00:00:00', +PRIMARY KEY (id), +UNIQUE (hash, type) +); +CREATE INDEX auth_hash_created_idx on auth_hash(created); diff --git a/module/VuFind/sql/mysql.sql b/module/VuFind/sql/mysql.sql index e92f516a87efd8a8fe2e66e505b3d27197fe700b..d4e1340ae7be69e65246a1f6b1cc25e4ab99b1c3 100644 --- a/module/VuFind/sql/mysql.sql +++ b/module/VuFind/sql/mysql.sql @@ -322,3 +322,24 @@ CREATE TABLE `record` ( UNIQUE KEY `record_id_source` (`record_id`, `source`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `auth_hash` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_hash` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `session_id` varchar(128) DEFAULT NULL, + `hash` varchar(255) NOT NULL DEFAULT '', + `type` varchar(50) DEFAULT NULL, + `data` mediumtext, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `session_id` (`session_id`), + UNIQUE KEY `hash_type` (`hash`, `type`), + KEY `created` (`created`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + diff --git a/module/VuFind/sql/pgsql.sql b/module/VuFind/sql/pgsql.sql index 744cc0f6bb5277cd7c424c7bb6ea9fa0cdd4f1c5..39abd1cbc298764d4e2d35c13e6a6ecd528f37b7 100644 --- a/module/VuFind/sql/pgsql.sql +++ b/module/VuFind/sql/pgsql.sql @@ -306,6 +306,24 @@ CONSTRAINT user_card_ibfk_1 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELE CREATE INDEX user_card_cat_username_idx ON user_card (cat_username); CREATE INDEX user_card_user_id_idx ON user_card (user_id); +-- +-- Table structure for table auth_hash +-- + +DROP TABLE IF EXISTS "auth_hash"; + +CREATE TABLE auth_hash ( +id BIGSERIAL, +session_id varchar(128), +hash varchar(255), +type varchar(50), +data text, +created timestamp NOT NULL default '1970-01-01 00:00:00', +PRIMARY KEY (id), +UNIQUE (hash, type) +); +CREATE INDEX auth_hash_created_idx on auth_hash(created); + -- -------------------------------------------------------- -- diff --git a/module/VuFind/src/VuFind/Auth/ChoiceAuth.php b/module/VuFind/src/VuFind/Auth/ChoiceAuth.php index 43b5ed0174576e2456b7413f1666d486ee5eb943..adbbeb42d4a04460937777b24ca20daaff796f83 100644 --- a/module/VuFind/src/VuFind/Auth/ChoiceAuth.php +++ b/module/VuFind/src/VuFind/Auth/ChoiceAuth.php @@ -337,6 +337,20 @@ class ChoiceAuth extends AbstractBase return $this->proxyAuthMethod('getDelegateAuthMethod', func_get_args()); } + /** + * Is the configured strategy on the list of legal options? + * + * @return bool + */ + protected function hasLegalStrategy() + { + // Do a case-insensitive search of the strategy list: + return in_array( + strtolower($this->strategy), + array_map('strtolower', $this->strategies) + ); + } + /** * Proxy auth method; a helper function to be called like: * return $this->proxyAuthMethod(METHOD, func_get_args()); @@ -354,7 +368,7 @@ class ChoiceAuth extends AbstractBase return false; } - if (!in_array($this->strategy, $this->strategies)) { + if (!$this->hasLegalStrategy()) { throw new InvalidArgumentException("Illegal setting: {$this->strategy}"); } $authenticator = $this->getPluginManager()->get($this->strategy); @@ -434,4 +448,21 @@ class ChoiceAuth extends AbstractBase } return isset($user) && $user instanceof User; } + + /** + * Whether this authentication method needs CSRF checking for the request. + * + * @param \Zend\Http\PhpEnvironment\Request $request Request object. + * + * @return bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function needsCsrfCheck($request) + { + if (!$this->strategy) { + return true; + } + return $this->proxyAuthMethod('needsCsrfCheck', func_get_args()); + } } diff --git a/module/VuFind/src/VuFind/Auth/Email.php b/module/VuFind/src/VuFind/Auth/Email.php index 3d5725feb6ec10a7f92f54a6cf0440ab6b79313d..9c9e9a0ee7d04f8af008182e2402be458688a722 100644 --- a/module/VuFind/src/VuFind/Auth/Email.php +++ b/module/VuFind/src/VuFind/Auth/Email.php @@ -86,8 +86,11 @@ class Email extends AbstractBase $loginData = [ 'vufind_id' => $user['id'] ]; - $this->emailAuthenticator - ->sendAuthenticationLink($user['email'], $loginData); + $this->emailAuthenticator->sendAuthenticationLink( + $user['email'], + $loginData, + ['auth_method' => 'email'] + ); } // Don't reveal the result throw new \VuFind\Exception\AuthInProgress('email_login_link_sent'); diff --git a/module/VuFind/src/VuFind/Auth/EmailAuthenticator.php b/module/VuFind/src/VuFind/Auth/EmailAuthenticator.php index 2fe718eb32e918e7de4fdacb28aea06abd8c5896..19f1faa775e9c54f9cb1c593488ab8054c52965f 100644 --- a/module/VuFind/src/VuFind/Auth/EmailAuthenticator.php +++ b/module/VuFind/src/VuFind/Auth/EmailAuthenticator.php @@ -27,7 +27,9 @@ */ namespace VuFind\Auth; +use VuFind\DB\Table\AuthHash as AuthHashTable; use VuFind\Exception\Auth as AuthException; +use Zend\Http\PhpEnvironment\RemoteAddress; /** * Class for managing email-based authentication. @@ -74,11 +76,11 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter protected $viewRenderer = null; /** - * Request + * Remote address * - * @var \Zend\Stdlib\RequestInterface + * @var RemoteAddress */ - protected $request; + protected $remoteAddress; /** * Configuration @@ -94,6 +96,13 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter */ protected $loginRequestValidTime = 600; + /** + * Database table for authentication hashes + * + * @var AuthHashTable + */ + protected $authHashTable; + /** * Constructor * @@ -101,21 +110,23 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter * @param \VuFind\Validator\Csrf $csrf CSRF Validator * @param \VuFind\Mailer\Mailer $mailer Mailer * @param \Zend\View\Renderer\RendererInterface $viewRenderer View Renderer - * @param \Zend\Stdlib\RequestInterface $request Request + * @param RemoteAddress $remoteAddr Remote address * @param \Zend\Config\Config $config Configuration + * @param AuthHashTable $authHash AuthHash Table */ public function __construct(\Zend\Session\SessionManager $session, \VuFind\Validator\Csrf $csrf, \VuFind\Mailer\Mailer $mailer, \Zend\View\Renderer\RendererInterface $viewRenderer, - \Zend\Stdlib\RequestInterface $request, - \Zend\Config\Config $config + RemoteAddress $remoteAddr, + \Zend\Config\Config $config, AuthHashTable $authHash ) { $this->sessionManager = $session; $this->csrf = $csrf; $this->mailer = $mailer; $this->viewRenderer = $viewRenderer; - $this->request = $request; + $this->remoteAddress = $remoteAddr; $this->config = $config; + $this->authHashTable = $authHash; } /** @@ -138,14 +149,14 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter $subject = 'email_login_subject', $template = 'Email/login-link.phtml' ) { - $sessionContainer = $this->getSessionContainer(); - // Make sure we've waited long enough $recoveryInterval = isset($this->config->Authentication->recover_interval) ? $this->config->Authentication->recover_interval : 60; - if (null !== $sessionContainer->timestamp - && time() - $sessionContainer->timestamp < $recoveryInterval + $sessionId = $this->sessionManager->getId(); + + if (($row = $this->authHashTable->getLatestBySessionId($sessionId)) + && time() - strtotime($row['created']) < $recoveryInterval ) { throw new AuthException('authentication_error_in_progress'); } @@ -154,14 +165,17 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter $linkData = [ 'timestamp' => time(), 'data' => $data, - 'email' => $email + 'email' => $email, + 'ip' => $this->remoteAddress->getIpAddress() ]; $hash = $this->csrf->getHash(true); - if (!isset($sessionContainer->requests)) { - $sessionContainer->requests = []; - } - $sessionContainer->requests[$hash] = $linkData; + $row = $this->authHashTable + ->getByHashAndType($hash, AuthHashTable::TYPE_EMAIL); + + $row['session_id'] = $sessionId; + $row['data'] = json_encode($linkData); + $row->save(); $serverHelper = $this->viewRenderer->plugin('serverurl'); $urlHelper = $this->viewRenderer->plugin('url'); @@ -192,14 +206,23 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter */ public function authenticate($hash) { - $sessionContainer = $this->getSessionContainer(); + $row = $this->authHashTable + ->getByHashAndType($hash, AuthHashTable::TYPE_EMAIL, false); + if (!$row) { + throw new AuthException('authentication_error_denied'); + } + $linkData = json_decode($row['data'], true); + $row->delete(); - if (!isset($sessionContainer->requests[$hash])) { + if (time() - strtotime($row['created']) > $this->loginRequestValidTime) { throw new AuthException('authentication_error_denied'); } - $linkData = $sessionContainer->requests[$hash]; - unset($sessionContainer->requests[$hash]); - if (time() - $linkData['timestamp'] > $this->loginRequestValidTime) { + + // Require same session id or IP address: + $sessionId = $this->sessionManager->getId(); + if ($row['session_id'] !== $sessionId + && $linkData['ip'] !== $this->remoteAddress->getIpAddress() + ) { throw new AuthException('authentication_error_denied'); } @@ -220,19 +243,10 @@ class EmailAuthenticator implements \VuFind\I18n\Translator\TranslatorAwareInter $request->getQuery()->get('hash', '') ); if ($hash) { - $sessionContainer = $this->getSessionContainer(); - return isset($sessionContainer->requests[$hash]); + $row = $this->authHashTable + ->getByHashAndType($hash, AuthHashTable::TYPE_EMAIL, false); + return !empty($row); } return false; } - - /** - * Get the session container - * - * @return \Zend\Session\Container - */ - protected function getSessionContainer() - { - return new \Zend\Session\Container('EmailAuth', $this->sessionManager); - } } diff --git a/module/VuFind/src/VuFind/Auth/EmailAuthenticatorFactory.php b/module/VuFind/src/VuFind/Auth/EmailAuthenticatorFactory.php index 150b8c7d701430e6999dcfbf5183a92ad034b847..2cfa4abb87974cf576e2e7d3716b194bdd96a2b9 100644 --- a/module/VuFind/src/VuFind/Auth/EmailAuthenticatorFactory.php +++ b/module/VuFind/src/VuFind/Auth/EmailAuthenticatorFactory.php @@ -66,8 +66,10 @@ class EmailAuthenticatorFactory $container->get(\VuFind\Validator\Csrf::class), $container->get(\VuFind\Mailer\Mailer::class), $container->get('ViewRenderer'), - $container->get('Request'), - $container->get(\VuFind\Config\PluginManager::class)->get('config') + $container->get(\Zend\Http\PhpEnvironment\RemoteAddress::class), + $container->get(\VuFind\Config\PluginManager::class)->get('config'), + $container->get(\VuFind\Db\Table\PluginManager::class) + ->get(\VuFind\Db\Table\AuthHash::class) ); } } diff --git a/module/VuFind/src/VuFind/Db/Row/AuthHash.php b/module/VuFind/src/VuFind/Db/Row/AuthHash.php new file mode 100644 index 0000000000000000000000000000000000000000..265338271e773236abee5013156362ac7dd3a213 --- /dev/null +++ b/module/VuFind/src/VuFind/Db/Row/AuthHash.php @@ -0,0 +1,53 @@ +<?php +/** + * Row Definition for auth_hash + * + * PHP version 7 + * + * Copyright (C) Villanova University 2010. + * Copyright (C) The National Library of Finland 2019. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Db_Row + * @author Demian Katz <demian.katz@villanova.edu> + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace VuFind\Db\Row; + +/** + * Row Definition for auth_hash + * + * @category VuFind + * @package Db_Row + * @author Demian Katz <demian.katz@villanova.edu> + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class AuthHash extends RowGateway +{ + /** + * Constructor + * + * @param \Zend\Db\Adapter\Adapter $adapter Database adapter + */ + public function __construct($adapter) + { + parent::__construct('id', 'auth_hash', $adapter); + } +} diff --git a/module/VuFind/src/VuFind/Db/Row/PluginManager.php b/module/VuFind/src/VuFind/Db/Row/PluginManager.php index 5b402dec18fd5b2a14cc207acfd62c2a5f5930df..02d8d0fb4dbc899d3b49cf15216a159edfe4f593 100644 --- a/module/VuFind/src/VuFind/Db/Row/PluginManager.php +++ b/module/VuFind/src/VuFind/Db/Row/PluginManager.php @@ -67,6 +67,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager * @var array */ protected $factories = [ + AuthHash::class => RowGatewayFactory::class, ChangeTracker::class => RowGatewayFactory::class, Comments::class => RowGatewayFactory::class, ExternalSession::class => RowGatewayFactory::class, diff --git a/module/VuFind/src/VuFind/Db/Table/AuthHash.php b/module/VuFind/src/VuFind/Db/Table/AuthHash.php new file mode 100644 index 0000000000000000000000000000000000000000..0918b0aa60ad04190a658dd556ea1fc136da4c05 --- /dev/null +++ b/module/VuFind/src/VuFind/Db/Table/AuthHash.php @@ -0,0 +1,145 @@ +<?php +/** + * Table Definition for auth_hash + * + * PHP version 7 + * + * Copyright (C) Villanova University 2010. + * Copyright (C) The National Library of Finland 2019. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Db_Table + * @author Demian Katz <demian.katz@villanova.edu> + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Page + */ +namespace VuFind\Db\Table; + +use VuFind\Db\Row\RowGateway; +use Zend\Db\Adapter\Adapter; + +/** + * Table Definition for auth_hash + * + * @category VuFind + * @package Db_Table + * @author Demian Katz <demian.katz@villanova.edu> + * @author Ere Maijala <ere.maijala@helsinki.fi> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +class AuthHash extends Gateway +{ + use ExpirationTrait; + + const TYPE_EMAIL = 'email'; // EmailAuthenticator + + /** + * Constructor + * + * @param Adapter $adapter Database adapter + * @param PluginManager $tm Table manager + * @param array $cfg Zend Framework configuration + * @param RowGateway $rowObj Row prototype object (null for default) + * @param string $table Name of database table to interface with + */ + public function __construct(Adapter $adapter, PluginManager $tm, $cfg, + RowGateway $rowObj = null, $table = 'auth_hash' + ) { + parent::__construct($adapter, $tm, $cfg, $rowObj, $table); + } + + /** + * Retrieve an object from the database based on hash and type; create a new + * row if no existing match is found. + * + * @param string $hash Hash + * @param string $type Hash type + * @param bool $create Should we create rows that don't already exist? + * + * @return \VuFind\Db\Row\AuthHash + */ + public function getByHashAndType($hash, $type, $create = true) + { + $row = $this->select(['hash' => $hash, 'type' => $type])->current(); + if ($create && empty($row)) { + $row = $this->createRow(); + $row->hash = $hash; + $row->type = $type; + $row->created = date('Y-m-d H:i:s'); + } + return $row; + } + + /** + * Retrieve last object from the database based on session id. + * + * @param string $sessionId Session ID + * + * @return \VuFind\Db\Row\AuthHash + */ + public function getLatestBySessionId($sessionId) + { + $callback = function ($select) use ($sessionId) { + $select->where->equalTo('session_id', $sessionId); + $select->order('created DESC'); + }; + return $this->select($callback)->current(); + } + + /** + * Get a query representing expired sessions (this can be passed + * to select() or delete() for further processing). + * + * @param int $daysOld Age in days of an "expired" session. + * + * @return function + */ + public function getExpiredQuery($daysOld = 2) + { + // Determine the expiration date: + $expireDate = time() - $daysOld * 24 * 60 * 60; + $callback = function ($select) use ($expireDate) { + $select->where->lessThan('created', date('Y-m-d H:i:s', $expireDate)); + }; + return $callback; + } + + /** + * Update the select statement to find records to delete. + * + * @param Select $select Select clause + * @param int $daysOld Age in days of an "expired" record. + * @param int $idFrom Lowest id of rows to delete. + * @param int $idTo Highest id of rows to delete. + * + * @return void + */ + protected function expirationCallback($select, $daysOld, $idFrom = null, + $idTo = null + ) { + $expireDate = time() - $daysOld * 24 * 60 * 60; + $where = $select->where + ->lessThan('created', date('Y-m-d H:i:s', $expireDate)); + if (null !== $idFrom) { + $where->and->greaterThanOrEqualTo('id', $idFrom); + } + if (null !== $idTo) { + $where->and->lessThanOrEqualTo('id', $idTo); + } + } +} diff --git a/module/VuFind/src/VuFind/Db/Table/PluginManager.php b/module/VuFind/src/VuFind/Db/Table/PluginManager.php index e08e1e41276ab3cbd179ba235b16a137f213346b..761b62288d880f10df715bdf7ec9dfb4ad0f1b19 100644 --- a/module/VuFind/src/VuFind/Db/Table/PluginManager.php +++ b/module/VuFind/src/VuFind/Db/Table/PluginManager.php @@ -67,6 +67,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager * @var array */ protected $factories = [ + AuthHash::class => GatewayFactory::class, ChangeTracker::class => GatewayFactory::class, Comments::class => GatewayFactory::class, ExternalSession::class => GatewayFactory::class, diff --git a/module/VuFind/src/VuFind/Http/PhpEnvironment/RemoteAddressFactory.php b/module/VuFind/src/VuFind/Http/PhpEnvironment/RemoteAddressFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..8e113bf5a94c8e46e3c775e78e43f3c5bde9f307 --- /dev/null +++ b/module/VuFind/src/VuFind/Http/PhpEnvironment/RemoteAddressFactory.php @@ -0,0 +1,72 @@ +<?php +/** + * RemoteAddress utility factory. This uses the core Zend RemoteAddress but + * configures it according to VuFind settings. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFind\Http\PhpEnvironment; + +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; + +/** + * RemoteAddress utility factory. + * + * @category VuFind + * @package View_Helpers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class RemoteAddressFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + $cfg = $container->get(\VuFind\Config\PluginManager::class)->get('config'); + $object = new $requestedName(); + if ($cfg->Site->reverse_proxy ?? false) { + $object->setUseProxy(true); + } + return $object; + } +} diff --git a/module/VuFindConsole/Module.php b/module/VuFindConsole/Module.php index ae048d2d0d3d172806dfa2fe34180d0676f99a10..8a509e31dea80326a825dc5f3dc88da1bece8315 100644 --- a/module/VuFindConsole/Module.php +++ b/module/VuFindConsole/Module.php @@ -123,6 +123,7 @@ class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterfac 'util createHierarchyTrees' => 'Cache populator for hierarchies', 'util cssBuilder' => 'LESS compiler', 'util deletes' => 'Tool for deleting Solr records', + 'util expire_auth_hashes' => 'Database auth_hash table cleanup', 'util expire_external_sessions' => 'Database external_session table cleanup', 'util expire_searches' => 'Database search table cleanup', diff --git a/module/VuFindConsole/config/module.config.php b/module/VuFindConsole/config/module.config.php index 210192d576296ea2f3d4938220110705e1859108..b153af319f3e1d45c27f64e8ee18d372f26cff6d 100644 --- a/module/VuFindConsole/config/module.config.php +++ b/module/VuFindConsole/config/module.config.php @@ -76,6 +76,7 @@ $routes = [ 'util/createHierarchyTrees' => 'util createHierarchyTrees [--skip-xml|-sx] [--skip-json|-sj] [<backend>] [--help|-h]', 'util/cssBuilder' => 'util cssBuilder [...themes]', 'util/deletes' => 'util deletes [--verbose] [<filename>] [<format>] [<index>]', + 'util/expire_auth_hashes' => 'util expire_auth_hashes [--help|-h] [--batch=] [--sleep=] [<daysOld>]', 'util/expire_external_sessions' => 'util expire_external_sessions [--help|-h] [--batch=] [--sleep=] [<daysOld>]', 'util/expire_searches' => 'util expire_searches [--help|-h] [--batch=] [--sleep=] [<daysOld>]', 'util/expire_sessions' => 'util expire_sessions [--help|-h] [--batch=] [--sleep=] [<daysOld>]', diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php index 2514ec0d605d175f3551d8fd0eae7ba390fd856a..644aa0fee48fdc2dcc8938266cec8a62284d6ffa 100644 --- a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php +++ b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php @@ -556,6 +556,26 @@ class UtilController extends AbstractBase ); } + /** + * Command-line tool to clear unwanted entries + * from auth_hash database table. + * + * @return \Zend\Console\Response + */ + public function expireauthhashesAction() + { + $request = $this->getRequest(); + if ($request->getParam('help') || $request->getParam('h')) { + return $this->expirationHelp('authentication hashes'); + } + + return $this->expire( + \VuFind\Db\Table\AuthHash::class, + '%%count%% expired authentication hashes deleted.', + 'No expired authentication hashes to delete.' + ); + } + /** * Command-line tool to delete suppressed records from the index. *