User preferences: Session store and glue to build instance

refs #4069
This commit is contained in:
Marius Hein 2013-07-30 16:02:05 +02:00
parent 6d1f349616
commit f3ed73175b
9 changed files with 275 additions and 37 deletions

3
.gitignore vendored
View File

@ -26,3 +26,6 @@ doc/api
# Enabled modules
config/enabledModules/
# User preferences
config/preferences/*.ini

View File

@ -17,3 +17,6 @@ target = /tmp/icinga2.log
debug.enable = 1
debug.type = stream
debug.target = /tmp/icinga2.debug.log
[preferences]
type=ini

View File

@ -0,0 +1 @@
# Keep this directory

View File

@ -140,7 +140,7 @@ abstract class ApplicationBootstrap
Benchmark::measure('Bootstrap, autoloader registered');
Icinga::setApp($this);
$this->configDir = $configDir;
$this->configDir = realpath($configDir);
require_once dirname(__FILE__) . '/functions.php';
}
@ -212,10 +212,32 @@ abstract class ApplicationBootstrap
*/
public function getApplicationDir($subdir = null)
{
$dir = $this->appDir;
return $this->getDirWithSubDir($this->appDir, $subdir);
}
/**
* Getter for config dir
* @param string|null $subdir
* @return string
*/
public function getConfigDir($subdir = null)
{
return $this->getDirWithSubDir($this->configDir, $subdir);
}
/**
* Helper to glue directories together
*
* @param string $dir
* @param string|null $subdir
* @return string
*/
private function getDirWithSubDir($dir, $subdir=null)
{
if ($subdir !== null) {
$dir .= '/' . ltrim($subdir, '/');
}
return $dir;
}

View File

@ -30,6 +30,7 @@ namespace Icinga\Application;
use Icinga\Authentication\Manager as AuthenticationManager;
use Icinga\User\Preferences;
use Icinga\User;
use Icinga\Web\Request;
use Zend_Controller_Front;
use Zend_Layout;
@ -39,6 +40,8 @@ use Zend_Controller_Action_HelperBroker;
use Zend_Controller_Router_Route;
use Zend_Controller_Action_Helper_ViewRenderer;
use Icinga\Web\View;
use Icinga\User\Preferences\StorageFactory;
use Icinga\User\Preferences\SessionStore;
/**
* Use this if you want to make use of Icinga funtionality in other web projects
@ -198,15 +201,8 @@ class Web extends ApplicationBootstrap
return $this;
}
/**
* Inject dependencies into request
*
* @return self
*/
private function setupRequest()
private function setupUser()
{
$this->request = new Request();
$authenticationManager = AuthenticationManager::getInstance(
null,
array(
@ -217,9 +213,44 @@ class Web extends ApplicationBootstrap
if ($authenticationManager->isAuthenticated() === true) {
$user = $authenticationManager->getUser();
$preferences = new Preferences(array());
$this->getConfig()->preferences->configPath = $this->getConfigDir('preferences');
$preferenceStore = StorageFactory::create(
$this->getConfig()->preferences,
$user
);
$sessionStore = new SessionStore($authenticationManager->getSession());
$initialPreferences = (count($sessionStore->load()))
? $sessionStore->load() : $preferenceStore->load();
$preferences = new Preferences($initialPreferences);
$preferences->attach($sessionStore);
$preferences->attach($preferenceStore);
$user->setPreferences($preferences);
$requestCounter = $user->getPreferences()->get('test.request.counter', 0);
$requestCounter++;
$user->getPreferences()->set('test.request.counter', $requestCounter);
return $user;
}
}
/**
* Inject dependencies into request
*
* @return self
*/
private function setupRequest()
{
$this->request = new Request();
$user = $this->setupUser();
if ($user instanceof User) {
$this->request->setUser($user);
}

View File

@ -31,6 +31,7 @@ namespace Icinga\Authentication;
use Icinga\Application\Logger;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Exception\ConfigurationError as ConfigError;
use Icinga\User;
/**
* The authentication manager allows to identify users and

View File

@ -44,17 +44,12 @@ use \Zend_Config_Writer_Ini;
*/
class IniStore implements LoadInterface, FlushObserverInterface
{
/**
* Name of preferences section in ini file
*/
const DEFAULT_SECTION = 'preferences';
/**
* Path to ini configuration
*
* @var string
*/
private $configDir;
private $configPath;
/**
* Specific user file for preferences
@ -87,26 +82,28 @@ class IniStore implements LoadInterface, FlushObserverInterface
/**
* Create a new object
*
* @param string $configDir
* @param string|null $configPath
*/
public function __construct($configDir)
public function __construct($configPath=null)
{
$this->setConfigDir($configDir);
if ($configPath !== null) {
$this->setConfigPath($configPath);
}
}
/**
* Setter for config directory
*
* @param string $configDir
* @param string $configPath
* @throws \Icinga\Exception\ConfigurationError
*/
public function setConfigDir($configDir)
public function setConfigPath($configPath)
{
if (!is_dir($configDir)) {
throw new ConfigurationError('Config dir dos not exist: '. $configDir);
if (!is_dir($configPath)) {
throw new ConfigurationError('Config dir dos not exist: '. $configPath);
}
$this->configDir = $configDir;
$this->configPath = $configPath;
}
/**
@ -120,7 +117,7 @@ class IniStore implements LoadInterface, FlushObserverInterface
$this->preferencesFile = sprintf(
'%s/%s.ini',
$this->configDir,
$this->configPath,
$this->user->getUsername()
);
@ -146,17 +143,7 @@ class IniStore implements LoadInterface, FlushObserverInterface
*/
private function createDefaultIniFile()
{
$writer = new Zend_Config_Writer_Ini(
array(
'config' => new Zend_Config(
array(
self::DEFAULT_SECTION => array()
)
),
'filename' => $this->preferencesFile
)
);
$writer->write();
touch($this->preferencesFile);
}
/**

View File

@ -0,0 +1,107 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\User\Preferences;
use Icinga\Authentication\Session;
use \SplObserver;
use \SplSubject;
use Icinga\User\Preferences;
use Icinga\Exception\ProgrammingError;
/**
* Modify preferences into session
*/
class SessionStore implements SplObserver, LoadInterface
{
/**
* Name of session var for preferences
*/
const DEFAULT_SESSION_NAMESPACE = 'preferences';
/**
* Session data
*
* @var Session
*/
private $session;
/**
* Create a new object
*
* @param Session $session
*/
public function __construct(Session $session)
{
$this->session = $session;
}
/**
* Receive update from subject
*
* @link http://php.net/manual/en/splobserver.update.php
* @param SplSubject $subject
* @throws ProgrammingError
*/
public function update(SplSubject $subject)
{
if (!$subject instanceof Preferences) {
throw new ProgrammingError('Not compatible with '. get_class($subject));
}
$changeSet = $subject->getChangeSet();
$data = $this->session->get(self::DEFAULT_SESSION_NAMESPACE, array());
foreach ($changeSet->getCreate() as $key => $value) {
$data[$key] = $value;
}
foreach ($changeSet->getUpdate() as $key => $value) {
$data[$key] = $value;
}
foreach ($changeSet->getDelete() as $key) {
unset($data[$key]);
}
$this->session->set(self::DEFAULT_SESSION_NAMESPACE, $data);
$this->session->write();
}
/**
* Load preferences from source
*
* @return array
*/
public function load()
{
return $this->session->get(self::DEFAULT_SESSION_NAMESPACE, array());
}
}

View File

@ -0,0 +1,83 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\User\Preferences;
use Icinga\User;
use Icinga\Exception\ProgrammingError;
use \Zend_Config;
final class StorageFactory
{
/**
* Prefix for classes containing namespace
*/
const CLASS_PREFIX = 'Icinga\\User\\Preferences\\';
/**
* Suffix for class
*/
const CLASS_SUFFIX = 'Store';
/**
* Create storage adapter from zend configuration
*
* @param Zend_Config $config
* @param User $user
* @return FlushObserverInterface
* @throws ProgrammingError
*/
public static function create(Zend_Config $config, User $user)
{
$class = self::CLASS_PREFIX. ucfirst($config->get('type')). self::CLASS_SUFFIX;
if (class_exists($class)) {
$store = new $class();
if (!$store instanceof FlushObserverInterface) {
throw new ProgrammingError('Not instance of FlushObserverInterface: '. $class);
}
$items = $config->toArray();
unset($items['type']);
foreach ($items as $key => $value) {
$setter = 'set'. ucfirst($key);
if (is_callable(array($store, $setter))) {
$store->$setter($value);
}
}
$store->setUser($user);
return $store;
}
throw new ProgrammingError('Could not instantiate class: '. $class);
}
}