Add PHP Documentation to Authentication

Documented all currently existing classes underneath the
Authentication package

refs #4350
This commit is contained in:
Jannis Moßhammer 2013-06-27 15:18:24 +02:00
parent cb2e1d8193
commit 934163dd04
7 changed files with 378 additions and 63 deletions

View File

@ -1,31 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Authentication;
class Backend
{
/**
* @var UserBackend
*/
protected $userBackend;
public function __construct($config)
{
$this->config = $config;
$userbackend = ucwords(strtolower($config->users->backend));
$class = '\\Icinga\\Authentication\\' . $userbackend . 'UserBackend';
$this->userBackend = new $class($config->users);
}
public function hasUsername($username)
{
return $this->userBackend->hasUsername($username);
}
public function authenticate($username, $password = null)
{
return $this->userBackend->authenticate($username, $password);
}
}

View File

@ -10,15 +10,35 @@ use Icinga\Authentication\Credentials;
use Icinga\Protocol\Ldap; use Icinga\Protocol\Ldap;
use Icinga\Application\Config; use Icinga\Application\Config;
/**
* User authentication backend (@see Icinga\Authentication\UserBackend) for
* authentication of users via LDAP. The attributes and location of the
* user is configurable via the application.ini
*
* See the UserBackend class (@see Icinga\Authentication\UserBackend) for
* usage information
**/
class LdapUserBackend implements UserBackend class LdapUserBackend implements UserBackend
{ {
/**
* @var Ldap\Connection
**/
protected $connection; protected $connection;
/**
* Creates a new Authentication backend using the
* connection information provided in $config
*
* @param object $config The ldap connection information
**/
public function __construct($config) public function __construct($config)
{ {
$this->connection = new Ldap\Connection($config); $this->connection = new Ldap\Connection($config);
} }
/**
* @see Icinga\Authentication\UserBackend::hasUsername
**/
public function hasUsername(Credentials $credential) public function hasUsername(Credentials $credential)
{ {
return $this->connection->fetchOne( return $this->connection->fetchOne(
@ -26,11 +46,27 @@ class LdapUserBackend implements UserBackend
) === $credential->getUsername(); ) === $credential->getUsername();
} }
/**
* Removes the '*' characted from $string
*
* @param String $string
*
* @return String
**/
protected function stripAsterisks($string) protected function stripAsterisks($string)
{ {
return str_replace('*', '', $string); return str_replace('*', '', $string);
} }
/**
* Tries to fetch the username given in $username from
* the ldap connection, using the configuration parameters
* given in the Authentication configuration
*
* @param String $username The username to select
*
* @return object $result
**/
protected function selectUsername($username) protected function selectUsername($username)
{ {
return $this->connection->select() return $this->connection->select()
@ -46,6 +82,9 @@ class LdapUserBackend implements UserBackend
); );
} }
/**
* @see Icinga\Authentication\UserBackend::authenticate
**/
public function authenticate(Credentials $credentials) public function authenticate(Credentials $credentials)
{ {
if (!$this->connection->testCredentials( if (!$this->connection->testCredentials(

View File

@ -4,13 +4,26 @@
namespace Icinga\Authentication; namespace Icinga\Authentication;
/**
* Data holder object for authentication information
*
* This object should be used instead of passing names and
* passwords as primitives in order to allow additional information
* to be provided (like the domain) when needed
**/
class Credentials class Credentials
{ {
protected $username; protected $username;
protected $password; protected $password;
protected $domain; protected $domain;
/**
* Create a new credential object
*
* @param String $username
* @param String $password
* @param String $domain
**/
public function __construct($username = "", $password = null, $domain = null) public function __construct($username = "", $password = null, $domain = null)
{ {
$this->username = $username; $this->username = $username;
@ -18,31 +31,49 @@ class Credentials
$this->domain = $domain; $this->domain = $domain;
} }
/**
* @return String
**/
public function getUsername() public function getUsername()
{ {
return $this->username; return $this->username;
} }
/**
* @param String $username
**/
public function setUsername($username) public function setUsername($username)
{ {
return $this->username = $username; return $this->username = $username;
} }
/**
* @return String
**/
public function getPassword() public function getPassword()
{ {
return $this->password; return $this->password;
} }
/**
* @param String $password
**/
public function setPassword($password) public function setPassword($password)
{ {
return $this->password = $password; return $this->password = $password;
} }
/**
* @return String
**/
public function getDomain() public function getDomain()
{ {
return $this->domain; return $this->domain;
} }
/**
* @param String $domain
**/
public function setDomain($domain) public function setDomain($domain)
{ {
return $this->domain = $domain; return $this->domain = $domain;

View File

@ -8,19 +8,69 @@ use Icinga\Application\Logger as Logger;
use Icinga\Application\Config as Config; use Icinga\Application\Config as Config;
use Icinga\Exception\ConfigurationError as ConfigError; use Icinga\Exception\ConfigurationError as ConfigError;
/**
* The authentication manager allows to identify users and
* to persist authentication information in a session.
*
* Direct instanciation is not permitted, the Authencation manager
* must be created using the getInstance method. Subsequent getInstance
* calls return the same object and ignore any additional configuration
*
* When creating the Authentication manager with standard PHP Sessions,
* you have to decide whether you want to modify the session on the first
* initialization and provide the 'writeSession' option if so, otherwise
* session changes won't be written to disk. This is done to prevent PHP
* from blockung concurrent requests
*
* @TODO: Group support is not implemented yet
**/
class Manager class Manager
{ {
const BACKEND_TYPE_USER = "User"; const BACKEND_TYPE_USER = "User";
const BACKEND_TYPE_GROUP = "Group"; const BACKEND_TYPE_GROUP = "Group";
/**
* @var Manager
**/
private static $instance = null; private static $instance = null;
/**
* @var User
**/
private $user = null; private $user = null;
private $groups = array(); private $groups = array();
/**
* @var UserBackend
**/
private $userBackend = null; private $userBackend = null;
/**
* @var GroupBackend
**/
private $groupBackend = null; private $groupBackend = null;
/**
* @var Session
**/
private $session = null; private $session = null;
/**
* Creates a new authentication manager using the provided config (or the
* configuration provided in the authentication.ini if no config is given)
* and with the given options.
*
* @param Icinga\Config $config The configuration to use for authentication
* instead of the authentication.ini
* @param Array $options Additional options that affect the managers behaviour.
* Supported values:
* * writeSession : Whether the session should be writable
* * userBackendClass : Allows to provide an own user backend class
* (used for testing)
* * groupBackendClass : Allows to provide an own group backend class
* (used for testing)
* * sessionClass : Allows to provide a different session implementation)
**/
private function __construct($config = null, array $options = array()) private function __construct($config = null, array $options = array())
{ {
if ($config === null) { if ($config === null) {
@ -50,6 +100,9 @@ class Manager
} }
} }
/**
* @see Manager:__construct()
**/
public static function getInstance($config = null, array $options = array()) public static function getInstance($config = null, array $options = array())
{ {
if (self::$instance === null) { if (self::$instance === null) {
@ -58,23 +111,51 @@ class Manager
return self::$instance; return self::$instance;
} }
/**
* Clears the instance (this is mostly needed for testing and shouldn't be called otherwise)
**/
public static function clearInstance() public static function clearInstance()
{ {
self::$instance = null; self::$instance = null;
} }
/**
* Creates a backend for the the given authenticationTarget (User or Group) and the
* Authenticaiton source.
*
* initBackend("User", "Ldap") would create a UserLdapBackend,
* initBackend("Group", "MySource") would create a GroupMySourceBackend,
*
* Supported backends can be found in the Authentication\Backend folder
*
* @param String $authenticationTarget "User" or "Group", depending on what
* authentication information the backend should
* provide
* @param String $authenticationSource The Source, see the above examples
*
* @return (null|UserBackend|GroupBackend)
**/
private function initBackend($authenticationTarget, $authenticationSource) private function initBackend($authenticationTarget, $authenticationSource)
{ {
$userBackend = ucwords(strtolower($authenticationSource->backend)); $backend = ucwords(strtolower($authenticationSource->backend));
if (!$userBackend) { if (!$backend) {
return null; return null;
} }
$class = '\\Icinga\\Authentication\\Backend\\' . $userBackend . $authenticationTarget. 'Backend'; $class = '\\Icinga\\Authentication\\Backend\\' . $backend . $authenticationTarget. 'Backend';
return new $class($authenticationSource); return new $class($authenticationSource);
} }
/**
* Tries to authenticate the current user with the Credentials (@see Credentials).
*
* @param Credentials $credentials The credentials to use for authentication
* @param Boolean $persist Whether to persist the authentication result
* in the current session
*
* @return Boolean true on success, otherwise false
**/
public function authenticate(Credentials $credentials, $persist = true) public function authenticate(Credentials $credentials, $persist = true)
{ {
if (!$this->userBackend) { if (!$this->userBackend) {
@ -103,16 +184,31 @@ class Manager
return true; return true;
} }
/**
* Writes the current user to the session (only usable when writeSession = true)
*
**/
public function persistCurrentUser() public function persistCurrentUser()
{ {
$this->session->set("user", $this->user); $this->session->set("user", $this->user);
} }
/**
* Tries to authenticate the user with the current session
**/
public function authenticateFromSession() public function authenticateFromSession()
{ {
$this->user = $this->session->get("user", null); $this->user = $this->session->get("user", null);
} }
/**
* Returns true when the user is currently authenticated
*
* @param Boolean $ignoreSession Set to true to prevent authentication by session
*
* @param Boolean
**/
public function isAuthenticated($ignoreSession = false) public function isAuthenticated($ignoreSession = false)
{ {
if ($this->user === null && !$ignoreSession) { if ($this->user === null && !$ignoreSession) {
@ -121,17 +217,29 @@ class Manager
return is_object($this->user); return is_object($this->user);
} }
/**
* Purges the current authorisation information and deletes the session
*
**/
public function removeAuthorization() public function removeAuthorization()
{ {
$this->user = null; $this->user = null;
$this->session->purge(); $this->session->purge();
} }
/**
* Returns the current user or null if no user is authenticated
*
* @return User
**/
public function getUser() public function getUser()
{ {
return $this->user; return $this->user;
} }
/**
* @see User::getGroups
**/
public function getGroups() public function getGroups()
{ {
return $this->user->getGroups(); return $this->user->getGroups();

View File

@ -17,7 +17,6 @@ use Icinga\Application\Logger as Logger;
* no parameter in order to auto-close it) to persist all values previously * no parameter in order to auto-close it) to persist all values previously
* set with the set() method * set with the set() method
* *
* @package Icinga\Authentication
*/ */
class PhpSession extends Session class PhpSession extends Session
{ {
@ -34,6 +33,12 @@ class PhpSession extends Session
'hash_bits_per_character' => 5, 'hash_bits_per_character' => 5,
); );
/**
* Creates a new PHPSession object using the provided options (if any)
*
* @param Array $options An optional array of ini options to set,
* @see http://php.net/manual/en/session.configuration.php
**/
public function __construct(array $options = null) public function __construct(array $options = null)
{ {
if ($options !== null) { if ($options !== null) {
@ -55,6 +60,11 @@ class PhpSession extends Session
} }
} }
/**
* Returns true when the session has not yet been closed
*
* @return Boolean
**/
private function sessionCanBeChanged() private function sessionCanBeChanged()
{ {
if ($this->isFlushed) { if ($this->isFlushed) {
@ -64,6 +74,11 @@ class PhpSession extends Session
return true; return true;
} }
/**
* Returns true when the session has not yet been opened
*
* @return Boolean
**/
private function sessionCanBeOpened() private function sessionCanBeOpened()
{ {
if ($this->isOpen) { if ($this->isOpen) {
@ -73,6 +88,11 @@ class PhpSession extends Session
return $this->sessionCanBeChanged(); return $this->sessionCanBeChanged();
} }
/**
* Opens a PHP session when possible
*
* @return Boolean True on success
**/
public function open() public function open()
{ {
if (!$this->sessionCanBeOpened()) { if (!$this->sessionCanBeOpened()) {
@ -86,6 +106,11 @@ class PhpSession extends Session
return true; return true;
} }
/**
* Ensures that the session is open modifyable
*
* @return Boolean True on success
**/
private function ensureOpen() private function ensureOpen()
{ {
// try to open first // try to open first
@ -97,6 +122,15 @@ class PhpSession extends Session
return true; return true;
} }
/**
* Reads all values written to the underyling session and
* makes them accessible. if keepOpen is not set, the session
* is immediately closed again
*
* @param Boolean $keepOpen Set to true when modifying the session
*
* @return Boolean True on success
**/
public function read($keepOpen = false) public function read($keepOpen = false)
{ {
if (!$this->ensureOpen()) { if (!$this->ensureOpen()) {
@ -109,6 +143,14 @@ class PhpSession extends Session
return true; return true;
} }
/**
* Writes all values of this session opbject to the underyling session implementation
* If keepOpen is not set, the session is closed
*
* @param Boolean $keepOpen Set to true when modifying the session further
*
* @return Boolean True on success
**/
public function write($keepOpen = false) public function write($keepOpen = false)
{ {
if (!$this->ensureOpen()) { if (!$this->ensureOpen()) {
@ -125,6 +167,11 @@ class PhpSession extends Session
return null; return null;
} }
/**
* Closes and writes the session. Call @see PHPSession::write in order to persist changes
* and only call this if you want the session to be closed without any changes
*
**/
public function close() public function close()
{ {
if (!$this->isFlushed) { if (!$this->isFlushed) {
@ -133,6 +180,10 @@ class PhpSession extends Session
$this->isFlushed = true; $this->isFlushed = true;
} }
/**
* Deletes the current session, causing all session information to be lost
*
**/
public function purge() public function purge()
{ {
if ($this->ensureOpen()) { if ($this->ensureOpen()) {
@ -143,6 +194,10 @@ class PhpSession extends Session
} }
} }
/**
* Removes session cookies
*
**/
private function clearCookies() private function clearCookies()
{ {
if (ini_get("session.use_cookies")) { if (ini_get("session.use_cookies")) {

View File

@ -4,32 +4,82 @@
namespace Icinga\Authentication; namespace Icinga\Authentication;
/**
* Base class for session, providing getter, setters and required
* interface methods
*
**/
abstract class Session abstract class Session
{ {
private $sessionValues = array(); private $sessionValues = array();
/**
* Opens a session or creates a new one if not exists
*
**/
abstract public function open(); abstract public function open();
/**
* Reads all values from the underyling session implementation
*
* @param Boolean $keepOpen True to keep the session open (depends on implementaiton)
**/
abstract public function read($keepOpen = false); abstract public function read($keepOpen = false);
/**
* Persists changes to the underlying session implementation
*
* @param Boolean $keepOpen True to keep the session open (depends on implementaiton)
**/
abstract public function write($keepOpen = false); abstract public function write($keepOpen = false);
abstract public function close(); abstract public function close();
abstract public function purge(); abstract public function purge();
/**
* Sets a $value under the provided key in the internal session data array
* Does not persist those changes, use @see Session::write in order to persist the changes
* made here.
*
* @param String $key
* @param mixed $value
**/
public function set($key, $value) public function set($key, $value)
{ {
$this->sessionValues[$key] = $value; $this->sessionValues[$key] = $value;
} }
/**
* Returns the session value stored under $key or $defaultValue if not found.
* call @see Session:read in order to populate this array with the underyling session implementation
*
* @param String $key
* @param mixed $defaultValue
*
* @return mixed
**/
public function get($key, $defaultValue = null) public function get($key, $defaultValue = null)
{ {
return isset($this->sessionValues[$key]) ? return isset($this->sessionValues[$key]) ?
$this->sessionValues[$key] : $defaultValue; $this->sessionValues[$key] : $defaultValue;
} }
/**
* Returns the current session value state (also dirty changes not yet written to the session)
*
* @return Array
**/
public function getAll() public function getAll()
{ {
return $this->sessionValues; return $this->sessionValues;
} }
/**
* Writes all values provided in the key=>value array to the internal session value state.
* In order to persist these chages, call @see Session:write
*
* @param Array $values
* @param Boolean $overwrite Whether to overwrite already set values
**/
public function setAll(array $values, $overwrite = false) public function setAll(array $values, $overwrite = false)
{ {
if ($overwrite) { if ($overwrite) {
@ -43,6 +93,10 @@ abstract class Session
} }
} }
/**
* Clears all values from the session cache
*
**/
public function clear() public function clear()
{ {
$this->sessionValues = array(); $this->sessionValues = array();

View File

@ -2,21 +2,13 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
/**
* Icinga Authentication User class
*
* @package Icinga\Authentication
*/
namespace Icinga\Authentication; namespace Icinga\Authentication;
/** /**
* This class represents a user object * This class represents an authorized user and can be used
* to retrieve authorization information (@TODO: Not implemented yet) or
* to retrieve user information
* *
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @package Icinga\Application
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/ */
class User class User
{ {
@ -30,6 +22,14 @@ class User
public $permissions = array(); public $permissions = array();
public $groups = array(); public $groups = array();
/**
* Creates a user object given the provided information
*
* @param String $username
* @param String $firstname
* @param String $lastname
* @param String $email
**/
public function __construct($username, $firstname = null, $lastname = null, $email = null) public function __construct($username, $firstname = null, $lastname = null, $email = null)
{ {
$this->setUsername($username); $this->setUsername($username);
@ -47,85 +47,144 @@ class User
} }
} }
/**
* Returns all groups this user belongs to
*
* @return Array
**/
public function getGroups() public function getGroups()
{ {
return $this->groups; return $this->groups;
} }
/**
* Sets the groups this user belongs to
*
* @return Array
**/
public function setGroups(array $groups) public function setGroups(array $groups)
{ {
$this->groups = $groups; $this->groups = $groups;
} }
/**
* Returns true if the user is a member of this group
*
* @return Boolean
**/
public function isMemberOf(Group $group) public function isMemberOf(Group $group)
{ {
return in_array($group, $this->groups); return in_array($group, $this->groups);
} }
/**
* Returns permission information for this user
*
* @return Array
**/
public function getPermissions() public function getPermissions()
{ {
return $this->permissions; return $this->permissions;
} }
/**
* @return String
**/
public function getUsername() public function getUsername()
{ {
return $this->username; return $this->username;
} }
/**
* @param String $name
**/
public function setUsername($name) public function setUsername($name)
{ {
$this->username = $name; $this->username = $name;
} }
/**
* @return String
**/
public function getFirstname() public function getFirstname()
{ {
return $this->firstname; return $this->firstname;
} }
/*+
* @param String $name
**/
public function setFirstname($name) public function setFirstname($name)
{ {
$this->firstname = $name; $this->firstname = $name;
} }
/**
* @return String
**/
public function getLastname() public function getLastname()
{ {
return $this->lastname; return $this->lastname;
} }
/**
* @param String $name
**/
public function setLastname($name) public function setLastname($name)
{ {
$this->lastname = $name; $this->lastname = $name;
} }
/**
* @return String
**/
public function getEmail() public function getEmail()
{ {
return $this->email; return $this->email;
} }
/**
* @param String $mail
*
* @throws \InvalidArgumentException When an invalid mail is provided
**/
public function setEmail($mail) public function setEmail($mail)
{ {
if (filter_var($mail, FILTER_VALIDATE_EMAIL)) { if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
$this->mail = $mail; $this->mail = $mail;
} else { } else {
throw new InvalidArgumentException("Invalid mail given for user $this->username: $mail"); throw new \InvalidArgumentException("Invalid mail given for user $this->username: $mail");
} }
} }
/**
* @param String $domain
**/
public function setDomain($domain) public function setDomain($domain)
{ {
$this->domain = $domain; $this->domain = $domain;
} }
/**
* @return String
**/
public function getDomain() public function getDomain()
{ {
return $this->domain; return $this->domain;
} }
/**
* @param String $key
* @param String $value
**/
public function setAdditional($key, $value) public function setAdditional($key, $value)
{ {
$this->additionalInformation[$key] = $value; $this->additionalInformation[$key] = $value;
} }
/**
* @return mixed
**/
public function getAdditional($key) public function getAdditional($key)
{ {
if (isset($this->additionalInformation[$key])) { if (isset($this->additionalInformation[$key])) {