From 17175a9bb1ac94333d6bbdb112274b5babc70b17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Lahmann?= <lahmann@ub.uni-leipzig.de>
Date: Mon, 7 Nov 2022 16:12:05 +0100
Subject: [PATCH] refs #22117 [finc]

* introduce PermissionProvider for X-Real-IP and RemoteAddr rules
* minor refactoring to fix cs issues
* refactored private getRemoteAddr to protected
---
 module/finc/config/module.config.php          |  8 ++
 .../Role/PermissionProvider/IpRangeFoFor.php  |  4 +-
 .../Role/PermissionProvider/IpRangeReal.php   | 56 ++++++++++++++
 .../PermissionProvider/IpRangeRealFactory.php | 74 +++++++++++++++++++
 .../Role/PermissionProvider/IpRegExFoFor.php  |  4 +-
 .../Role/PermissionProvider/IpRegExReal.php   | 56 ++++++++++++++
 .../PermissionProvider/IpRegExRealFactory.php | 73 ++++++++++++++++++
 7 files changed, 271 insertions(+), 4 deletions(-)
 create mode 100644 module/finc/src/finc/Role/PermissionProvider/IpRangeReal.php
 create mode 100644 module/finc/src/finc/Role/PermissionProvider/IpRangeRealFactory.php
 create mode 100644 module/finc/src/finc/Role/PermissionProvider/IpRegExReal.php
 create mode 100644 module/finc/src/finc/Role/PermissionProvider/IpRegExRealFactory.php

diff --git a/module/finc/config/module.config.php b/module/finc/config/module.config.php
index 3f206c21d65..5969f502e6f 100644
--- a/module/finc/config/module.config.php
+++ b/module/finc/config/module.config.php
@@ -250,17 +250,25 @@ $config = [
                 'catUserType' => \finc\Role\PermissionProvider\CatUserTypeFactory::class,
                 'ipRangeFoFor' => \finc\Role\PermissionProvider\IpRangeFoForFactory::class,
                 'ipRegExFoFor' => \finc\Role\PermissionProvider\IpRegExFoForFactory::class,
+                'ipRangeReal' => \finc\Role\PermissionProvider\IpRangeRealFactory::class,
+                'ipRegExReal' => \finc\Role\PermissionProvider\IpRegExRealFactory::class,
                 'finc\Role\PermissionProvider\CatUserType' =>
                     \finc\Role\PermissionProvider\CatUserTypeFactory::class,
                 'finc\Role\PermissionProvider\IpRangeFoFor' =>
                     \finc\Role\PermissionProvider\IpRangeFoForFactory::class,
                 'finc\Role\PermissionProvider\IpRegExFoFor' =>
                     \finc\Role\PermissionProvider\IpRegExFoForFactory::class,
+                'finc\Role\PermissionProvider\IpRangeReal' =>
+                    \finc\Role\PermissionProvider\IpRangeRealFactory::class,
+                'finc\Role\PermissionProvider\IpRegExReal' =>
+                    \finc\Role\PermissionProvider\IpRegExRealFactory::class,
             ],
             'aliases' => [
                 'CatUserType' => 'finc\Role\PermissionProvider\CatUserType',
                 'IpRangeFoFor' => 'finc\Role\PermissionProvider\IpRangeFoFor',
                 'IpRegExFoFor' => 'finc\Role\PermissionProvider\IpRegExFoFor',
+                'IpRangeReal' => 'finc\Role\PermissionProvider\IpRangeReal',
+                'IpRegExReal' => 'finc\Role\PermissionProvider\IpRegExReal',
                 'IpRange' => 'VuFind\Role\PermissionProvider\IpRange',
             ]
         ]
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRangeFoFor.php b/module/finc/src/finc/Role/PermissionProvider/IpRangeFoFor.php
index 14d47f1af9a..03036b7f9de 100644
--- a/module/finc/src/finc/Role/PermissionProvider/IpRangeFoFor.php
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRangeFoFor.php
@@ -46,11 +46,11 @@ namespace finc\Role\PermissionProvider;
 class IpRangeFoFor extends \VuFind\Role\PermissionProvider\IpRange
 {
     /**
-     * returns remote address based on eventual proxy headers
+     * Returns remote address based on eventual proxy headers
      *
      * @return string
      */
-    private function getRemoteAddr()
+    protected function getRemoteAddr()
     {
         // a list of ips the request is forwarded for - first is latest
         $HttpXForwardedForList = explode(',', $this->request->getServer()->get('HTTP_X_FORWARDED_FOR'));
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRangeReal.php b/module/finc/src/finc/Role/PermissionProvider/IpRangeReal.php
new file mode 100644
index 00000000000..189b37cae64
--- /dev/null
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRangeReal.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * IpRangeReal permission provider for VuFind.
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2007.
+ * Copyright (C) Leipzig University Library 2022.
+ *
+ * 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  Authorization
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace finc\Role\PermissionProvider;
+
+/**
+ * IpRangeReal permission provider for VuFind.
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class IpRangeReal extends \finc\Role\PermissionProvider\IpRangeFoFor
+{
+    /**
+     * Returns remote address based on eventual proxy headers
+     *
+     * @return string
+     */
+    protected function getRemoteAddr()
+    {
+        // often provided by nginx-reverse-proxies, should be used since its the nature of the value
+        if ($ip = $this->request->getServer()->get('HTTP_X_REAL_IP')) {
+            return $ip;
+        }
+
+        return $this->request->getServer()->get('REMOTE_ADDR');
+    }
+}
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRangeRealFactory.php b/module/finc/src/finc/Role/PermissionProvider/IpRangeRealFactory.php
new file mode 100644
index 00000000000..f5c90a936de
--- /dev/null
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRangeRealFactory.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * IpRangeReal Factory Class
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * 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  Authorization
+ * @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:plugins:hierarchy_components Wiki
+ */
+namespace finc\Role\PermissionProvider;
+
+use Interop\Container\ContainerInterface;
+use Zend\ServiceManager\Factory\FactoryInterface;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * IpRangeReal Factory Class
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @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:plugins:hierarchy_components Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class IpRangeRealFactory implements FactoryInterface
+{
+    /**
+     * Create an IpRangeReal
+     *
+     * @param ContainerInterface $container     Service manager
+     * @param string             $requestedName Service being created
+     * @param null|array         $options       Extra options (optional)
+     *
+     * @return IpRangeReal
+     *
+     * @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.');
+        }
+        return new IpRangeReal(
+            $container->get('Request'),
+            $container->get('VuFind\IpAddressUtils')
+        );
+    }
+}
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRegExFoFor.php b/module/finc/src/finc/Role/PermissionProvider/IpRegExFoFor.php
index 1e171c3f76d..1473ed55a37 100644
--- a/module/finc/src/finc/Role/PermissionProvider/IpRegExFoFor.php
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRegExFoFor.php
@@ -41,11 +41,11 @@ namespace finc\Role\PermissionProvider;
 class IpRegExFoFor extends \VuFind\Role\PermissionProvider\IpRegEx
 {
     /**
-     * returns remote address based on eventual proxy headers
+     * Returns remote address based on eventual proxy headers
      *
      * @return string
      */
-    private function getRemoteAddr()
+    protected function getRemoteAddr()
     {
         // a list of ips the request is forwarded for - first is latest
         $HttpXForwardedForList = explode(',', $this->request->getServer()->get('HTTP_X_FORWARDED_FOR'));
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRegExReal.php b/module/finc/src/finc/Role/PermissionProvider/IpRegExReal.php
new file mode 100644
index 00000000000..432385cb439
--- /dev/null
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRegExReal.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * IpRegExReal permission provider for VuFind.
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2007.
+ * Copyright (C) Leipzig University Library 2022.
+ *
+ * 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  Authorization
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace finc\Role\PermissionProvider;
+
+/**
+ * IpRegExReal permission provider for VuFind.
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class IpRegExReal extends \finc\Role\PermissionProvider\IpRegExFoFor
+{
+    /**
+     * Returns remote address based on eventual proxy headers
+     *
+     * @return string
+     */
+    protected function getRemoteAddr()
+    {
+        // often provided by nginx-reverse-proxies, should be used since its the nature of the value
+        if ($ip = $this->request->getServer()->get('HTTP_X_REAL_IP')) {
+            return $ip;
+        }
+
+        return $this->request->getServer()->get('REMOTE_ADDR');
+    }
+}
diff --git a/module/finc/src/finc/Role/PermissionProvider/IpRegExRealFactory.php b/module/finc/src/finc/Role/PermissionProvider/IpRegExRealFactory.php
new file mode 100644
index 00000000000..883971b944e
--- /dev/null
+++ b/module/finc/src/finc/Role/PermissionProvider/IpRegExRealFactory.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * IpRegExReal Factory Class
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * 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  Authorization
+ * @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:plugins:hierarchy_components Wiki
+ */
+namespace finc\Role\PermissionProvider;
+
+use Interop\Container\ContainerInterface;
+use Zend\ServiceManager\Factory\FactoryInterface;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * IpRegExReal Factory Class
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @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:plugins:hierarchy_components Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class IpRegExRealFactory implements FactoryInterface
+{
+    /**
+     * Create an IpRegExReal
+     *
+     * @param ContainerInterface $container     Service manager
+     * @param string             $requestedName Service being created
+     * @param null|array         $options       Extra options (optional)
+     *
+     * @return IpRegExReal
+     *
+     * @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.');
+        }
+        return new IpRegExReal(
+            $container->get('Request')
+        );
+    }
+}
-- 
GitLab