From 1824eb9c3b6eb79088ed282ba6017fb6493fbc95 Mon Sep 17 00:00:00 2001
From: Johannes Meyer <johannes.meyer@netways.de>
Date: Mon, 4 May 2015 11:43:53 +0200
Subject: [PATCH] Make class UserBackend being just a factory for user backends

refs #8826
---
 .../Authentication/User/UserBackend.php       | 88 +++++--------------
 1 file changed, 24 insertions(+), 64 deletions(-)

diff --git a/library/Icinga/Authentication/User/UserBackend.php b/library/Icinga/Authentication/User/UserBackend.php
index 89bd1f56e..8bda07323 100644
--- a/library/Icinga/Authentication/User/UserBackend.php
+++ b/library/Icinga/Authentication/User/UserBackend.php
@@ -3,25 +3,23 @@
 
 namespace Icinga\Authentication\User;
 
-use Countable;
 use Icinga\Application\Logger;
 use Icinga\Application\Icinga;
 use Icinga\Data\ConfigObject;
 use Icinga\Data\ResourceFactory;
 use Icinga\Exception\ConfigurationError;
-use Icinga\User;
 
 /**
- * Base class for concrete user backends
+ * Factory for user backends
  */
-abstract class UserBackend implements Countable
+class UserBackend
 {
     /**
      * The default user backend types provided by Icinga Web 2
      *
      * @var array
      */
-    private static $defaultBackends = array( // I would have liked it if I were able to declare this as constant :'(
+    protected static $defaultBackends = array(
         'external',
         'db',
         'ldap',
@@ -36,39 +34,9 @@ abstract class UserBackend implements Countable
     protected static $customBackends;
 
     /**
-     * The name of this backend
-     *
-     * @var string
+     * Register all custom user backends from all loaded modules
      */
-    protected $name;
-
-    /**
-     * Set this backend's name
-     *
-     * @param   string  $name
-     *
-     * @return  $this
-     */
-    public function setName($name)
-    {
-        $this->name = $name;
-        return $this;
-    }
-
-    /**
-     * Return this backend's name
-     *
-     * @return  string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * Fetch all custom user backends from all loaded modules
-     */
-    public static function loadCustomUserBackends()
+    protected static function registerCustomUserBackends()
     {
         if (static::$customBackends !== null) {
             return;
@@ -80,7 +48,7 @@ abstract class UserBackend implements Countable
             foreach ($module->getUserBackends() as $identifier => $className) {
                 if (array_key_exists($identifier, $providedBy)) {
                     Logger::warning(
-                        'Cannot register UserBackend of type "%s" provided by module "%s".'
+                        'Cannot register user backend of type "%s" provided by module "%s".'
                         . ' The type is already provided by module "%s"',
                         $identifier,
                         $module->getName(),
@@ -88,7 +56,7 @@ abstract class UserBackend implements Countable
                     );
                 } elseif (in_array($identifier, static::$defaultBackends)) {
                     Logger::warning(
-                        'Cannot register UserBackend of type "%s" provided by module "%s".'
+                        'Cannot register user backend of type "%s" provided by module "%s".'
                         . ' The type is a default type provided by Icinga Web 2',
                         $identifier,
                         $module->getName()
@@ -102,29 +70,23 @@ abstract class UserBackend implements Countable
     }
 
     /**
-     * Validate and return the class for the given custom user backend
+     * Return the class for the given custom user backend
      *
      * @param   string  $identifier     The identifier of the custom user backend
      *
      * @return  string|null             The name of the class or null in case there was no
      *                                   backend found with the given identifier
      *
-     * @throws  ConfigurationError      In case the class could not be successfully validated
+     * @throws  ConfigurationError      In case the class associated to the given identifier does not exist
      */
     protected static function getCustomUserBackend($identifier)
     {
-        static::loadCustomUserBackends();
+        static::registerCustomUserBackends();
         if (array_key_exists($identifier, static::$customBackends)) {
             $className = static::$customBackends[$identifier];
             if (! class_exists($className)) {
                 throw new ConfigurationError(
-                    'Cannot utilize UserBackend of type "%s". Class "%s" does not exist',
-                    $identifier,
-                    $className
-                );
-            } elseif (! is_subclass_of($className, __CLASS__)) {
-                throw new ConfigurationError(
-                    'Cannot utilize UserBackend of type "%s". Class "%s" is not a sub-type of UserBackend',
+                    'Cannot utilize user backend of type "%s". Class "%s" does not exist',
                     $identifier,
                     $className
                 );
@@ -135,12 +97,12 @@ abstract class UserBackend implements Countable
     }
 
     /**
-     * Create and return a UserBackend with the given name and given configuration applied to it
+     * Create and return a user backend with the given name and given configuration applied to it
      *
      * @param   string          $name
      * @param   ConfigObject    $backendConfig
      *
-     * @return  UserBackend
+     * @return  UserBackendInterface
      *
      * @throws  ConfigurationError
      */
@@ -152,7 +114,7 @@ abstract class UserBackend implements Countable
 
         if (! ($backendType = strtolower($backendConfig->backend))) {
             throw new ConfigurationError(
-                'Authentication configuration for backend "%s" is missing the \'backend\' directive',
+                'Authentication configuration for user backend "%s" is missing the \'backend\' directive',
                 $name
             );
         }
@@ -166,11 +128,19 @@ abstract class UserBackend implements Countable
             // Do not attempt to load a custom user backend unless it's actually required
         } elseif (($customClass = static::getCustomUserBackend($backendType)) !== null) {
             $backend = new $customClass($backendConfig);
+            if (! is_a($backend, 'Icinga\Authentication\User\UserBackendInterface')) {
+                throw new ConfigurationError(
+                    'Cannot utilize user backend of type "%s". Class "%s" does not implement UserBackendInterface',
+                    $backendType,
+                    $customClass
+                );
+            }
+
             $backend->setName($name);
             return $backend;
         } else {
             throw new ConfigurationError(
-                'Authentication configuration for backend "%s" defines an invalid backend type.'
+                'Authentication configuration for user backend "%s" defines an invalid backend type.'
                 . ' Backend type "%s" is not supported',
                 $name,
                 $backendType
@@ -179,7 +149,7 @@ abstract class UserBackend implements Countable
 
         if ($backendConfig->resource === null) {
             throw new ConfigurationError(
-                'Authentication configuration for backend "%s" is missing the \'resource\' directive',
+                'Authentication configuration for user backend "%s" is missing the \'resource\' directive',
                 $name
             );
         }
@@ -239,14 +209,4 @@ abstract class UserBackend implements Countable
         $backend->setName($name);
         return $backend;
     }
-
-    /**
-     * Authenticate the given user
-     *
-     * @param   User    $user
-     * @param   string  $password
-     *
-     * @return  bool
-     */
-    abstract public function authenticate(User $user, $password);
 }