mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-28 16:24:04 +02:00
Merge branch 'master' of ssh://git.icinga.org/icinga2-web into feature/history-api-4303
Conflicts: public/js/icinga/components/actionTable.js public/js/icinga/components/mainDetail.js public/js/icinga/container.js public/js/icinga/util/async.js
This commit is contained in:
commit
d71d15c822
3
.gitignore
vendored
3
.gitignore
vendored
@ -12,3 +12,6 @@ config.log
|
|||||||
|
|
||||||
# cmd tester
|
# cmd tester
|
||||||
test/php/bin/extcmd_test
|
test/php/bin/extcmd_test
|
||||||
|
|
||||||
|
# misc test output
|
||||||
|
test/frontend/static/public
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
# namespace Icinga\Application\Controllers;
|
# namespace Icinga\Application\Controllers;
|
||||||
|
|
||||||
use Icinga\Web\ActionController;
|
use Icinga\Web\ActionController;
|
||||||
use Icinga\Authentication\Auth;
|
use Icinga\Authentication\Credentials as Credentials;
|
||||||
use Icinga\Web\Notification;
|
use Icinga\Authentication\Manager as AuthManager;
|
||||||
|
use Icinga\Form\Builder as FormBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AuthenticationController
|
* Class AuthenticationController
|
||||||
@ -25,13 +26,67 @@ class AuthenticationController extends ActionController
|
|||||||
*/
|
*/
|
||||||
protected $modifiesSession = true;
|
protected $modifiesSession = true;
|
||||||
|
|
||||||
|
private function getAuthForm()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'username' => array(
|
||||||
|
'text',
|
||||||
|
array(
|
||||||
|
'label' => t('Username'),
|
||||||
|
'required' => true,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
'password',
|
||||||
|
array(
|
||||||
|
'label' => t('Password'),
|
||||||
|
'required' => true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'submit' => array(
|
||||||
|
'submit',
|
||||||
|
array(
|
||||||
|
'label' => t('Login'),
|
||||||
|
'class' => 'pull-right'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function loginAction()
|
public function loginAction()
|
||||||
{
|
{
|
||||||
$this->replaceLayout = true;
|
$this->replaceLayout = true;
|
||||||
$this->view->form = $this->widget('form', array('name' => 'login'));
|
$credentials = new Credentials();
|
||||||
|
$this->view->form = FormBuilder::fromArray(
|
||||||
|
$this->getAuthForm(),
|
||||||
|
array(
|
||||||
|
"CSRFProtection" => false, // makes no sense here
|
||||||
|
"model" => &$credentials
|
||||||
|
)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
$auth = AuthManager::getInstance(null, array(
|
||||||
|
"writeSession" => true
|
||||||
|
));
|
||||||
|
if ($auth->isAuthenticated()) {
|
||||||
|
$this->redirectNow('index?_render=body');
|
||||||
|
}
|
||||||
|
if ($this->getRequest()->isPost() && $this->view->form->isSubmitted()) {
|
||||||
|
$this->view->form->repopulate();
|
||||||
|
if ($this->view->form->isValid()) {
|
||||||
|
if (!$auth->authenticate($credentials)) {
|
||||||
|
$this->view->form->getElement('password')->addError(t('Please provide a valid username and password'));
|
||||||
|
} else {
|
||||||
|
$this->redirectNow('index?_render=body');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Icinga\Exception\ConfigurationError $configError) {
|
||||||
|
$this->view->errorInfo = $configError->getMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,9 +94,11 @@ class AuthenticationController extends ActionController
|
|||||||
*/
|
*/
|
||||||
public function logoutAction()
|
public function logoutAction()
|
||||||
{
|
{
|
||||||
|
$auth = AuthManager::getInstance(null, array(
|
||||||
|
"writeSession" => true
|
||||||
|
));
|
||||||
$this->replaceLayout = true;
|
$this->replaceLayout = true;
|
||||||
Auth::getInstance()->forgetAuthentication();
|
$auth->removeAuthorization();
|
||||||
Notification::success('You have been logged out');
|
|
||||||
$this->_forward('login');
|
$this->_forward('login');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ class ErrorController extends ActionController
|
|||||||
$this->view->message = 'Application error';
|
$this->view->message = 'Application error';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// conditionally display exceptions
|
// conditionally display exceptions
|
||||||
if ($this->getInvokeArg('displayExceptions') == true) {
|
if ($this->getInvokeArg('displayExceptions') == true) {
|
||||||
$this->view->exception = $errors->exception;
|
$this->view->exception = $errors->exception;
|
||||||
|
51
application/controllers/ModulesController.php
Executable file
51
application/controllers/ModulesController.php
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
# namespace Icinga\Application\Controllers;
|
||||||
|
|
||||||
|
|
||||||
|
use Icinga\Web\ActionController;
|
||||||
|
use Icinga\Application\Icinga;
|
||||||
|
|
||||||
|
class ModulesController extends ActionController
|
||||||
|
{
|
||||||
|
protected $manager;
|
||||||
|
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->manager = Icinga::app()->moduleManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function indexAction()
|
||||||
|
{
|
||||||
|
$this->view->modules = $this->manager->select()
|
||||||
|
->from('modules')
|
||||||
|
->order('name');
|
||||||
|
$this->render('overview');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function overviewAction()
|
||||||
|
{
|
||||||
|
$this->indexAction();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enableAction()
|
||||||
|
{
|
||||||
|
$this->manager->enableModule($this->_getParam('name'));
|
||||||
|
$this->manager->loadModule($this->_getParam('name'));
|
||||||
|
$this->getResponse()->setHeader('X-Icinga-Enable-Module', $this->_getParam('name'));
|
||||||
|
$this->replaceLayout = true;
|
||||||
|
$this->indexAction();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disableAction()
|
||||||
|
{
|
||||||
|
$this->manager->disableModule($this->_getParam('name'));
|
||||||
|
$this->redirectNow('modules/overview?_render=body');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@ use Icinga\Web\ActionController;
|
|||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Zend_Controller_Action_Exception as ActionException;
|
use Zend_Controller_Action_Exception as ActionException;
|
||||||
|
|
||||||
|
use Icinga\Application\Benchmark;
|
||||||
/**
|
/**
|
||||||
* Class StaticController
|
* Class StaticController
|
||||||
* @package Icinga\Web\Form
|
* @package Icinga\Web\Form
|
||||||
@ -69,7 +70,7 @@ class StaticController extends ActionController
|
|||||||
*/
|
*/
|
||||||
public function javascriptAction()
|
public function javascriptAction()
|
||||||
{
|
{
|
||||||
$module = $this->_getParam('moduleName');
|
$module = $this->_getParam('module_name');
|
||||||
$file = $this->_getParam('file');
|
$file = $this->_getParam('file');
|
||||||
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
||||||
|
|
||||||
@ -96,14 +97,15 @@ class StaticController extends ActionController
|
|||||||
) . ' GMT'
|
) . ' GMT'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$hash = md5_file($filePath);
|
||||||
|
|
||||||
if ($hash === $this->getRequest()->getHeader('If-None-Match')) {
|
if ($hash === $this->getRequest()->getHeader('If-None-Match')) {
|
||||||
$response->setHttpResponseCode(304);
|
$response->setHttpResponseCode(304);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
readfile($filePath);
|
readfile($filePath);
|
||||||
}
|
}
|
||||||
// TODO: get rid of exit:
|
return;
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,14 +12,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="icinga-detail" class="icinga-container " container-id="icinga-detail">
|
<div id="icinga-detail" class="icinga-container " container-id="icinga-detail">
|
||||||
<div class="container-controls">
|
|
||||||
<a class="container-expand-link" title="expand" target="_self" href="/develop/monitoring/list/services">
|
|
||||||
<i class="icon-fullscreen"></i>
|
|
||||||
</a>
|
|
||||||
<a class="container-detach-link" title="detach" target="popup" href="/develop/develop/monitoring/list/services">
|
|
||||||
<i class="icon-share"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
ICINGA_DEBUG = true;
|
ICINGA_DEBUG = true;
|
||||||
</script>
|
</script>
|
||||||
<script src="<?php echo $this->baseUrl('js/vendor/modernizr-2.6.2.min.js') ?>"></script>
|
<script src="<?php echo $this->baseUrl('js/vendor/modernizr-2.6.2.min.js') ?>"></script>
|
||||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/icinga.css') ?>">
|
<link rel="stylesheet" href="<?php echo $this->baseUrl('css.php') ?>">
|
||||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/vendor/bootstrap-responsive.min.css') ?>">
|
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/vendor/bootstrap-responsive.min.css') ?>">
|
||||||
<script data-main="<?php echo $this->baseUrl('js/main.js')?>" src="<?php echo $this->baseUrl('js/vendor/require.js') ?>"></script>
|
<script data-main="<?php echo $this->baseUrl('js/main.js')?>" src="<?php echo $this->baseUrl('js/vendor/require.js') ?>"></script>
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
$item = $this->navigation->listAll("menu");
|
$item = $this->navigation->listAll("menu");
|
||||||
?>
|
?>
|
||||||
<?php if ($this->auth()->isAuthenticated()): ?>
|
<?php if (true || $this->auth()->isAuthenticated()): ?>
|
||||||
|
|
||||||
<ul class="nav nav-tabs icinga-navigation" >
|
<ul class="nav nav-tabs icinga-navigation" >
|
||||||
<?php
|
<?php
|
||||||
$activeSet = false;
|
$activeSet = false;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><?php echo
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><?php echo
|
||||||
$this->escape($this->auth()->getUsername())
|
$this->escape($this->auth()->getUser()->getUsername())
|
||||||
?> <i class="icon-user icon-white" style="margin-top:0.2em"></i>
|
?> <i class="icon-user icon-white" style="margin-top:0.2em"></i>
|
||||||
<b class="caret"></b>
|
<b class="caret"></b>
|
||||||
</a>
|
</a>
|
||||||
|
@ -36,6 +36,9 @@ class Zend_View_Helper_Qlink extends Zend_View_Helper_Abstract
|
|||||||
$quote = $val;
|
$quote = $val;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ($key === 'target') {
|
||||||
|
$attibutes[] = 'target="'.$val.'"';
|
||||||
|
}
|
||||||
if ($key === 'style' && is_array($val)) {
|
if ($key === 'style' && is_array($val)) {
|
||||||
if (empty($val)) {
|
if (empty($val)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1 +1,10 @@
|
|||||||
<?php echo $this->form ?>
|
<div class="well" style="margin:auto;width: 40%;max-width:25em;margin-top:10%;">
|
||||||
|
<h1> Login </h1>
|
||||||
|
<?php echo $this->form->render() ?>
|
||||||
|
<?php if (isset($this->errorInfo)): ?>
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<?= $this->errorInfo ?>
|
||||||
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@ -11,6 +11,13 @@
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>Message:</b> <?php echo $this->exception->getMessage() ?>
|
<b>Message:</b> <?php echo $this->exception->getMessage() ?>
|
||||||
|
<?php if (isset($this->exception->action)): ?>
|
||||||
|
<br/><b>Action</b>: <?= $this->exception->action; ?>
|
||||||
|
<?php endif ?>
|
||||||
|
<?php if (isset($this->exception->action)): ?>
|
||||||
|
<br/><b>Target</b>: <?= $this->exception->target; ?>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Stack trace:</h3>
|
<h3>Stack trace:</h3>
|
||||||
|
3
application/views/scripts/inline.phtml
Normal file
3
application/views/scripts/inline.phtml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?= $this->layout()->moduleStart ?>
|
||||||
|
<?= $this->layout()->content ?>
|
||||||
|
<?= $this->layout()->moduleEnd ?>
|
61
application/views/scripts/mixedPagination.phtml
Executable file
61
application/views/scripts/mixedPagination.phtml
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
<? if ($this->pageCount > 1): ?>
|
||||||
|
<?php
|
||||||
|
if (is_array($this->preserve)) {
|
||||||
|
$preserve = $this->preserve;
|
||||||
|
} else {
|
||||||
|
$preserve = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$fromto = t('%d to %d of %d');
|
||||||
|
$total = $this->totalItemCount;
|
||||||
|
?>
|
||||||
|
<div class="pagination pagination-mini" style="margin:0px">
|
||||||
|
<ul>
|
||||||
|
<!-- Previous page link -->
|
||||||
|
<? if (isset($this->previous)): ?>
|
||||||
|
<li><a href="<?= $this->url($preserve + array('page' => $this->previous)); ?>" title="<?=
|
||||||
|
sprintf($fromto,
|
||||||
|
($this->current - 2) * $this->itemCountPerPage + 1,
|
||||||
|
($this->current - 1) * $this->itemCountPerPage,
|
||||||
|
$this->totalItemCount)
|
||||||
|
?>">« <?= t('Back') ?></a></li>
|
||||||
|
<? else: ?>
|
||||||
|
<li class="disabled"><span>« <?= t('Back') ?></span></li>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
<!-- Numbered page links -->
|
||||||
|
<? foreach ($this->pagesInRange as $page): ?>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$start = ($page - 1) * $this->itemCountPerPage + 1;
|
||||||
|
$end = $page * $this->itemCountPerPage;
|
||||||
|
if ($end > $total) {
|
||||||
|
$end = $total;
|
||||||
|
}
|
||||||
|
$title = sprintf($fromto, $start, $end, $total);
|
||||||
|
$active_class = $page === $this->current ? ' class="active"' : '';
|
||||||
|
|
||||||
|
?>
|
||||||
|
<?php if ($page === '...'): ?>
|
||||||
|
<li class="disabled"><span>...</span></li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li<?= $active_class ?>><a href="<?= $this->url(
|
||||||
|
$preserve + array('page' => $page)
|
||||||
|
); ?>" title="<?= $title ?>"><?= $page; ?></a></li>
|
||||||
|
<? endif ?>
|
||||||
|
<? endforeach ?>
|
||||||
|
<!-- Next page link -->
|
||||||
|
<? if (isset($this->next)): ?>
|
||||||
|
<li><a href="<?= $this->url($preserve + array('page' => $this->next)); ?>" title="<?=
|
||||||
|
sprintf($fromto,
|
||||||
|
($this->current) * $this->itemCountPerPage + 1,
|
||||||
|
($this->current + 1) * $this->itemCountPerPage,
|
||||||
|
$total)
|
||||||
|
?>"><?= t('Next') ?> »</a></li>
|
||||||
|
<? else: ?>
|
||||||
|
<li class="disabled"><span><?= t('Next') ?> »</span></li>
|
||||||
|
<? endif ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<? endif ?>
|
38
application/views/scripts/modules/overview.phtml
Normal file
38
application/views/scripts/modules/overview.phtml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
$this->modules->limit(10);
|
||||||
|
$modules = $this->modules->paginate();
|
||||||
|
|
||||||
|
?>
|
||||||
|
<h3>Installed Modules</h3>
|
||||||
|
<?= $this->paginationControl($modules, null, null, array(
|
||||||
|
'preserve' => $this->preserve
|
||||||
|
)); ?>
|
||||||
|
<table >
|
||||||
|
<tbody>
|
||||||
|
<? foreach ($modules as $module): ?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<? if ($module->enabled): ?>
|
||||||
|
<i class="icon-ok-sign"></i> <?= $this->qlink(
|
||||||
|
$module->name,
|
||||||
|
'modules/disable',
|
||||||
|
array('name' => $module->name),
|
||||||
|
array('target'=>'body')
|
||||||
|
) ?>
|
||||||
|
<? else: ?>
|
||||||
|
<i class="icon-remove-sign"></i> <?= $this->qlink(
|
||||||
|
$module->name,
|
||||||
|
'modules/enable',
|
||||||
|
array('name' => $module->name),
|
||||||
|
array('target'=>'body')
|
||||||
|
) ?>
|
||||||
|
<? endif ?>
|
||||||
|
(<?=
|
||||||
|
$module->enabled
|
||||||
|
? ($module->loaded ? 'enabled' : 'failed')
|
||||||
|
: 'disabled'
|
||||||
|
?>)</td>
|
||||||
|
</tr>
|
||||||
|
<? endforeach ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
24
application/views/scripts/modules/show.phtml
Normal file
24
application/views/scripts/modules/show.phtml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php $container = $this->container('modules-container',array(
|
||||||
|
"class" => "expanded_absolute"
|
||||||
|
))->beginContent() ?>
|
||||||
|
<table class="table table-bordered" style="width:100%">
|
||||||
|
<thead>
|
||||||
|
<tr style="text-align:left">
|
||||||
|
<th width="70%">Module</th>
|
||||||
|
<th width="15%">Type</th>
|
||||||
|
<th width="15%">Active</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach($this->modules as $module): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $module["name"] ?></td>
|
||||||
|
<td><?= $module["type"] ?></td>
|
||||||
|
<td><?= $module["active"] ?></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?= $container; ?>
|
@ -1,2 +1,9 @@
|
|||||||
[users]
|
[users]
|
||||||
|
backend=ldap
|
||||||
|
hostname=localhost
|
||||||
|
root_dn="ou=people,dc=icinga,dc=org"
|
||||||
|
bind_dn="cn=admin,cn=config"
|
||||||
|
bind_pw=admin
|
||||||
|
user_class=inetOrgPerson
|
||||||
|
user_name_attribute=uid
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ environment = development
|
|||||||
timezone = "Europe/Berlin"
|
timezone = "Europe/Berlin"
|
||||||
indexModule = monitoring
|
indexModule = monitoring
|
||||||
indexController = dashboard
|
indexController = dashboard
|
||||||
|
moduleFolder = "/usr/etc/icinga-modules"
|
||||||
|
|
||||||
[logging]
|
[logging]
|
||||||
; General log
|
; General log
|
||||||
|
@ -18,6 +18,7 @@ use Icinga\Exception\ConfigurationError;
|
|||||||
* Usage example for CLI:
|
* Usage example for CLI:
|
||||||
* <code>
|
* <code>
|
||||||
* use Icinga\Application\Cli;
|
* use Icinga\Application\Cli;
|
||||||
|
|
||||||
* Cli::start();
|
* Cli::start();
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
@ -99,7 +100,7 @@ abstract class ApplicationBootstrap
|
|||||||
public function moduleManager()
|
public function moduleManager()
|
||||||
{
|
{
|
||||||
if ($this->moduleManager === null) {
|
if ($this->moduleManager === null) {
|
||||||
$this->moduleManager = new ModuleManager($this);
|
$this->moduleManager = new ModuleManager($this, $this->config->global->moduleFolder);
|
||||||
}
|
}
|
||||||
return $this->moduleManager;
|
return $this->moduleManager;
|
||||||
}
|
}
|
||||||
|
@ -2,35 +2,45 @@
|
|||||||
|
|
||||||
namespace Icinga\Application\Modules;
|
namespace Icinga\Application\Modules;
|
||||||
|
|
||||||
use Icinga\Application\ApplicationBootstrap;
|
|
||||||
use Icinga\Data\ArrayDatasource;
|
|
||||||
use Icinga\Web\Notification;
|
|
||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
|
use Icinga\Exception\SystemPermissionException;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
|
||||||
// TODO: show whether enabling/disabling modules is allowed by checking enableDir
|
// TODO: show whether enabling/disabling modules is allowed by checking enableDir
|
||||||
// perms
|
// perms
|
||||||
|
|
||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
protected $installedBaseDirs;
|
protected $installedBaseDirs = null;
|
||||||
protected $enabledDirs = array();
|
protected $enabledDirs = array();
|
||||||
protected $loadedModules = array();
|
protected $loadedModules = array();
|
||||||
protected $index;
|
protected $index;
|
||||||
protected $app;
|
protected $app;
|
||||||
|
|
||||||
protected $enableDir;
|
protected $enableDir;
|
||||||
|
protected $modulePaths = array();
|
||||||
public function __construct(ApplicationBootstrap $app)
|
/**
|
||||||
|
* @param $app : The applicaiton bootstrap. This one needs a properly defined interface
|
||||||
|
* In order to test it correctly, the application now only requires a stdClass
|
||||||
|
* @param $dir :
|
||||||
|
**/
|
||||||
|
public function __construct($app, $enabledDir = null, array $availableDirs = array())
|
||||||
{
|
{
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
$this->prepareEssentials();
|
if (empty($availableDirs)) {
|
||||||
|
$availableDirs = array(ICINGA_APPDIR."/../modules");
|
||||||
|
}
|
||||||
|
$this->modulePaths = $availableDirs;
|
||||||
|
if ($enabledDir === null) {
|
||||||
|
$enabledDir = $this->app->getConfig()->getConfigDir()
|
||||||
|
. '/enabledModules';
|
||||||
|
}
|
||||||
|
$this->prepareEssentials($enabledDir);
|
||||||
$this->detectEnabledModules();
|
$this->detectEnabledModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function prepareEssentials()
|
protected function prepareEssentials($moduleDir)
|
||||||
{
|
{
|
||||||
$this->enableDir = $this->app->getConfig()->getConfigDir()
|
$this->enableDir = $moduleDir;
|
||||||
. '/enabledModules';
|
|
||||||
|
|
||||||
if (! file_exists($this->enableDir) || ! is_dir($this->enableDir)) {
|
if (! file_exists($this->enableDir) || ! is_dir($this->enableDir)) {
|
||||||
throw new ProgrammingError(
|
throw new ProgrammingError(
|
||||||
@ -42,10 +52,17 @@ class Manager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function select()
|
||||||
|
{
|
||||||
|
$source = new \Icinga\Data\ArrayDatasource($this->getModuleInfo());
|
||||||
|
return $source->select();
|
||||||
|
}
|
||||||
|
|
||||||
protected function detectEnabledModules()
|
protected function detectEnabledModules()
|
||||||
{
|
{
|
||||||
$fh = opendir($this->enableDir);
|
$fh = opendir($this->enableDir);
|
||||||
|
|
||||||
|
$this->enabledDirs = array();
|
||||||
while (false !== ($file = readdir($fh))) {
|
while (false !== ($file = readdir($fh))) {
|
||||||
|
|
||||||
if ($file[0] === '.') {
|
if ($file[0] === '.') {
|
||||||
@ -74,12 +91,18 @@ class Manager
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadModule($name)
|
public function loadModule($name, $moduleBase = null)
|
||||||
{
|
{
|
||||||
if ($this->hasLoaded($name)) {
|
if ($this->hasLoaded($name)) {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$module = null;
|
||||||
|
if ($moduleBase === null) {
|
||||||
$module = new Module($this->app, $name, $this->getModuleDir($name));
|
$module = new Module($this->app, $name, $this->getModuleDir($name));
|
||||||
|
} else {
|
||||||
|
$module = new $moduleBase($this->app, $name, $this->getModuleDir($name));
|
||||||
|
}
|
||||||
$module->register();
|
$module->register();
|
||||||
$this->loadedModules[$name] = $module;
|
$this->loadedModules[$name] = $module;
|
||||||
return $this;
|
return $this;
|
||||||
@ -96,17 +119,26 @@ class Manager
|
|||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
clearstatcache(true);
|
||||||
$target = $this->installedBaseDirs[$name];
|
$target = $this->installedBaseDirs[$name];
|
||||||
$link = $this->enableDir . '/' . $name;
|
$link = $this->enableDir . '/' . $name;
|
||||||
if (! is_writable($this->enableDir)) {
|
if (! is_writable($this->enableDir)) {
|
||||||
Notification::error("I do not have permissions to enable modules");
|
throw new SystemPermissionException(
|
||||||
|
"Insufficient system permissions for enabling modules",
|
||||||
|
"write",
|
||||||
|
$this->enableDir
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (file_exists($link) && is_link($link)) {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
if (@symlink($target, $link)) {
|
if (!@symlink($target, $link)) {
|
||||||
Notification::success("The module $name has been enabled");
|
$error = error_get_last();
|
||||||
} else {
|
if (strstr($error["message"], "File exists") === false) {
|
||||||
Notification::error("Enabling module $name failed");
|
throw new SystemPermissionException($error["message"], "symlink", $link);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
$this->enabledDirs[$name] = $link;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,17 +148,31 @@ class Manager
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
if (! is_writable($this->enableDir)) {
|
if (! is_writable($this->enableDir)) {
|
||||||
Notification::error("I do not have permissions to disable modules");
|
throw new SystemPermissionException("Can't write the module directory", "write", $this->enableDir);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
$link = $this->enableDir . '/' . $name;
|
$link = $this->enableDir . '/' . $name;
|
||||||
|
if (!file_exists($link)) {
|
||||||
|
throw new ConfigurationError("The module $name could not be found, can't disable it");
|
||||||
|
}
|
||||||
|
if (!is_link($link)) {
|
||||||
|
throw new ConfigurationError(
|
||||||
|
"The module $name can't be disabled as this would delete the whole module. ".
|
||||||
|
"It looks like you have installed this module manually and moved it to your module folder.".
|
||||||
|
"In order to dynamically enable and disable modules, you have to create a symlink to ".
|
||||||
|
"the enabled_modules folder"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (file_exists($link) && is_link($link)) {
|
if (file_exists($link) && is_link($link)) {
|
||||||
if (@unlink($link)) {
|
if (!@unlink($link)) {
|
||||||
Notification::success("The module $name has been disabled");
|
$error = error_get_last();
|
||||||
|
throw new SystemPermissionException($error["message"], "unlink", $link);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Notification::error("Disabling module $name failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
unset($this->enabledDirs[$name]);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +238,12 @@ class Manager
|
|||||||
public function getModuleInfo()
|
public function getModuleInfo()
|
||||||
{
|
{
|
||||||
$installed = $this->listInstalledModules();
|
$installed = $this->listInstalledModules();
|
||||||
|
|
||||||
$info = array();
|
$info = array();
|
||||||
|
if ($installed === null) {
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($installed as $name) {
|
foreach ($installed as $name) {
|
||||||
$info[] = (object) array(
|
$info[] = (object) array(
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -204,12 +255,6 @@ class Manager
|
|||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function select()
|
|
||||||
{
|
|
||||||
$ds = new ArrayDatasource($this->getModuleInfo());
|
|
||||||
return $ds->select();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function listEnabledModules()
|
public function listEnabledModules()
|
||||||
{
|
{
|
||||||
return array_keys($this->enabledDirs);
|
return array_keys($this->enabledDirs);
|
||||||
@ -225,14 +270,16 @@ class Manager
|
|||||||
if ($this->installedBaseDirs === null) {
|
if ($this->installedBaseDirs === null) {
|
||||||
$this->detectInstalledModules();
|
$this->detectInstalledModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->installedBaseDirs !== null) {
|
||||||
return array_keys($this->installedBaseDirs);
|
return array_keys($this->installedBaseDirs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function detectInstalledModules()
|
public function detectInstalledModules()
|
||||||
{
|
{
|
||||||
// TODO: Allow multiple paths for installed modules (e.g. web vs pkg)
|
foreach ($this->modulePaths as $basedir) {
|
||||||
$basedir = realpath(ICINGA_APPDIR . '/../modules');
|
$fh = opendir($basedir);
|
||||||
$fh = @opendir($basedir);
|
|
||||||
if ($fh === false) {
|
if ($fh === false) {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -247,3 +294,4 @@ class Manager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -38,7 +38,6 @@ class Web extends ApplicationBootstrap
|
|||||||
return $this->loadConfig()
|
return $this->loadConfig()
|
||||||
->configureErrorHandling()
|
->configureErrorHandling()
|
||||||
->setTimezone()
|
->setTimezone()
|
||||||
->configureSession()
|
|
||||||
->configureCache()
|
->configureCache()
|
||||||
->prepareZendMvc()
|
->prepareZendMvc()
|
||||||
->loadTranslations()
|
->loadTranslations()
|
||||||
@ -60,6 +59,17 @@ class Web extends ApplicationBootstrap
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->frontController->getRouter()->addRoute(
|
||||||
|
'module_javascript',
|
||||||
|
new Route(
|
||||||
|
'js/modules/:module_name/:file',
|
||||||
|
array(
|
||||||
|
'controller' => 'static',
|
||||||
|
'action' => 'javascript'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,16 +90,6 @@ class Web extends ApplicationBootstrap
|
|||||||
$this->dispatchFrontController();
|
$this->dispatchFrontController();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure web session settings
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
protected function configureSession()
|
|
||||||
{
|
|
||||||
Manager::getInstance();
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function loadTranslations()
|
protected function loadTranslations()
|
||||||
{
|
{
|
||||||
@ -173,6 +173,7 @@ class Web extends ApplicationBootstrap
|
|||||||
*/
|
*/
|
||||||
protected function configurePagination()
|
protected function configurePagination()
|
||||||
{
|
{
|
||||||
|
|
||||||
Paginator::addScrollingStylePrefixPath(
|
Paginator::addScrollingStylePrefixPath(
|
||||||
'Icinga_Web_Paginator_ScrollingStyle',
|
'Icinga_Web_Paginator_ScrollingStyle',
|
||||||
'Icinga/Web/Paginator/ScrollingStyle'
|
'Icinga/Web/Paginator/ScrollingStyle'
|
||||||
|
@ -6,6 +6,9 @@ namespace Icinga\Authentication;
|
|||||||
|
|
||||||
class Backend
|
class Backend
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var UserBackend
|
||||||
|
*/
|
||||||
protected $userBackend;
|
protected $userBackend;
|
||||||
|
|
||||||
public function __construct($config)
|
public function __construct($config)
|
||||||
|
@ -5,7 +5,10 @@
|
|||||||
namespace Icinga\Authentication\Backend;
|
namespace Icinga\Authentication\Backend;
|
||||||
|
|
||||||
use Icinga\Authentication\User as User;
|
use Icinga\Authentication\User as User;
|
||||||
|
use Icinga\Authentication\UserBackend;
|
||||||
|
use Icinga\Authentication\Credentials;
|
||||||
use Icinga\Protocol\Ldap;
|
use Icinga\Protocol\Ldap;
|
||||||
|
use Icinga\Application\Config;
|
||||||
|
|
||||||
class LdapUserBackend implements UserBackend
|
class LdapUserBackend implements UserBackend
|
||||||
{
|
{
|
||||||
@ -16,14 +19,11 @@ class LdapUserBackend implements UserBackend
|
|||||||
$this->connection = new Ldap\Connection($config);
|
$this->connection = new Ldap\Connection($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasUsername($username)
|
public function hasUsername(Credentials $credential)
|
||||||
{
|
{
|
||||||
if (!$username) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $this->connection->fetchOne(
|
return $this->connection->fetchOne(
|
||||||
$this->selectUsername($username)
|
$this->selectUsername($credential->getUsername())
|
||||||
) === $username;
|
) === $credential->getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function stripAsterisks($string)
|
protected function stripAsterisks($string)
|
||||||
@ -34,23 +34,28 @@ class LdapUserBackend implements UserBackend
|
|||||||
protected function selectUsername($username)
|
protected function selectUsername($username)
|
||||||
{
|
{
|
||||||
return $this->connection->select()
|
return $this->connection->select()
|
||||||
->from('user', array('sAMAccountName'))
|
->from(
|
||||||
->where('sAMAccountName', $this->stripAsterisks($username));
|
Config::getInstance()->authentication->users->user_class,
|
||||||
|
array(
|
||||||
|
Config::getInstance()->authentication->users->user_name_attribute
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->where(
|
||||||
|
Config::getInstance()->authentication->users->user_name_attribute,
|
||||||
|
$this->stripAsterisks($username)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function authenticate($username, $password = null)
|
public function authenticate(Credentials $credentials)
|
||||||
{
|
{
|
||||||
if (empty($username) || empty($password)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->connection->testCredentials(
|
if (!$this->connection->testCredentials(
|
||||||
$this->connection->fetchDN($this->selectUsername($username)),
|
$this->connection->fetchDN($this->selectUsername($credentials->getUsername())),
|
||||||
$password
|
$credentials->getPassword()
|
||||||
) ) {
|
)
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = new User($username);
|
$user = new User($credentials->getUsername());
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace Icinga\Authentication;
|
|||||||
|
|
||||||
use Icinga\Application\Logger as Logger;
|
use Icinga\Application\Logger as Logger;
|
||||||
use Icinga\Application\Config as Config;
|
use Icinga\Application\Config as Config;
|
||||||
|
use Icinga\Exception\ConfigurationError as ConfigError;
|
||||||
|
|
||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
@ -25,7 +26,6 @@ class Manager
|
|||||||
if ($config === null) {
|
if ($config === null) {
|
||||||
$config = Config::getInstance()->authentication;
|
$config = Config::getInstance()->authentication;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options["userBackendClass"])) {
|
if (isset($options["userBackendClass"])) {
|
||||||
$this->userBackend = $options["userBackendClass"];
|
$this->userBackend = $options["userBackendClass"];
|
||||||
} elseif ($config->users !== null) {
|
} elseif ($config->users !== null) {
|
||||||
@ -77,6 +77,15 @@ class Manager
|
|||||||
|
|
||||||
public function authenticate(Credentials $credentials, $persist = true)
|
public function authenticate(Credentials $credentials, $persist = true)
|
||||||
{
|
{
|
||||||
|
if (!$this->userBackend) {
|
||||||
|
Logger::error("No authentication backend provided, your users will never be able to login.");
|
||||||
|
throw new ConfigError(
|
||||||
|
"No authentication backend set - login will never succeed as icinga-web ".
|
||||||
|
"doesn't know how to determine your user. \n".
|
||||||
|
"To fix this error, setup your authentication.ini with a valid authentication backend."
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!$this->userBackend->hasUsername($credentials)) {
|
if (!$this->userBackend->hasUsername($credentials)) {
|
||||||
Logger::info("Unknown user %s tried to log in", $credentials->getUsername());
|
Logger::info("Unknown user %s tried to log in", $credentials->getUsername());
|
||||||
return false;
|
return false;
|
||||||
@ -115,7 +124,7 @@ class Manager
|
|||||||
public function removeAuthorization()
|
public function removeAuthorization()
|
||||||
{
|
{
|
||||||
$this->user = null;
|
$this->user = null;
|
||||||
$this->session->delete();
|
$this->session->purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUser()
|
public function getUser()
|
||||||
|
@ -28,7 +28,6 @@ class PhpSession extends Session
|
|||||||
private static $DEFAULT_COOKIEOPTIONS = array(
|
private static $DEFAULT_COOKIEOPTIONS = array(
|
||||||
'use_trans_sid' => false,
|
'use_trans_sid' => false,
|
||||||
'use_cookies' => true,
|
'use_cookies' => true,
|
||||||
'use_only_cooies' => true,
|
|
||||||
'cookie_httponly' => true,
|
'cookie_httponly' => true,
|
||||||
'use_only_cookies' => true,
|
'use_only_cookies' => true,
|
||||||
'hash_function' => true,
|
'hash_function' => true,
|
||||||
@ -51,6 +50,9 @@ class PhpSession extends Session
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!is_writable(session_save_path())) {
|
||||||
|
throw new \Icinga\Exception\ConfigurationError("Can't save session");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sessionCanBeChanged()
|
private function sessionCanBeChanged()
|
||||||
@ -78,12 +80,7 @@ class PhpSession extends Session
|
|||||||
}
|
}
|
||||||
|
|
||||||
session_name(PhpSession::SESSION_NAME);
|
session_name(PhpSession::SESSION_NAME);
|
||||||
|
session_start();
|
||||||
/*
|
|
||||||
* @todo This is not right
|
|
||||||
*/
|
|
||||||
\Zend_Session::start();
|
|
||||||
// session_start();
|
|
||||||
$this->isOpen = true;
|
$this->isOpen = true;
|
||||||
$this->setAll($_SESSION);
|
$this->setAll($_SESSION);
|
||||||
return true;
|
return true;
|
||||||
@ -138,16 +135,18 @@ class PhpSession extends Session
|
|||||||
|
|
||||||
public function purge()
|
public function purge()
|
||||||
{
|
{
|
||||||
if ($this->ensureOpen() && !$this->isFlushed) {
|
if ($this->ensureOpen()) {
|
||||||
$_SESSION = array();
|
$_SESSION = array();
|
||||||
session_destroy();
|
session_destroy();
|
||||||
$this->clearCookies();
|
$this->clearCookies();
|
||||||
|
$this->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function clearCookies()
|
private function clearCookies()
|
||||||
{
|
{
|
||||||
if (ini_get("session.use_cookies")) {
|
if (ini_get("session.use_cookies")) {
|
||||||
|
Logger::debug("Clearing cookies");
|
||||||
$params = session_get_cookie_params();
|
$params = session_get_cookie_params();
|
||||||
setcookie(
|
setcookie(
|
||||||
session_name(),
|
session_name(),
|
||||||
|
@ -20,15 +20,15 @@ namespace Icinga\Authentication;
|
|||||||
*/
|
*/
|
||||||
class User
|
class User
|
||||||
{
|
{
|
||||||
private $username = "";
|
public $username = "";
|
||||||
private $firstname = "";
|
public $firstname = "";
|
||||||
private $lastname = "";
|
public $lastname = "";
|
||||||
private $email = "";
|
public $email = "";
|
||||||
private $domain = "";
|
public $domain = "";
|
||||||
private $additionalInformation = array();
|
public $additionalInformation = array();
|
||||||
|
|
||||||
private $permissions = array();
|
public $permissions = array();
|
||||||
private $groups = array();
|
public $groups = array();
|
||||||
|
|
||||||
public function __construct($username, $firstname = null, $lastname = null, $email = null)
|
public function __construct($username, $firstname = null, $lastname = null, $email = null)
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
// {{{ICINGA_LICENSE_HEADER}}// {{{ICINGA_LICENSE_HEADER}}}
|
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}}
|
// {{{ICINGA_LICENSE_HEADER}}}}
|
||||||
|
|
||||||
namespace Icinga\Authentication;
|
namespace Icinga\Authentication;
|
||||||
|
|
||||||
interface UserBackend
|
interface UserBackend
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new object
|
||||||
|
* @param $config
|
||||||
|
*/
|
||||||
public function __construct($config);
|
public function __construct($config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the username exists
|
||||||
|
* @param Credentials $credentials
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function hasUsername(Credentials $credentials);
|
public function hasUsername(Credentials $credentials);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate
|
||||||
|
* @param Credentials $credentials
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
public function authenticate(Credentials $credentials);
|
public function authenticate(Credentials $credentials);
|
||||||
}
|
}
|
||||||
|
22
library/Icinga/Exception/SystemPermissionException.php
Normal file
22
library/Icinga/Exception/SystemPermissionException.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ProgrammingError
|
||||||
|
* @package Icinga\Exception
|
||||||
|
*/
|
||||||
|
class SystemPermissionException extends \Exception
|
||||||
|
{
|
||||||
|
public $action;
|
||||||
|
public $target;
|
||||||
|
|
||||||
|
public function __construct($message, $action, $target = "")
|
||||||
|
{
|
||||||
|
parent::__construct($message);
|
||||||
|
$this->action = $action;
|
||||||
|
$this->target = $target;
|
||||||
|
}
|
||||||
|
}
|
385
library/Icinga/Form/Builder.php
Normal file
385
library/Icinga/Form/Builder.php
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Form;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that helps building and validating forms and offers a rudimentary
|
||||||
|
* data-binding mechanismn.
|
||||||
|
*
|
||||||
|
* The underlying form can be accessed by expicitly calling $builder->getForm() or
|
||||||
|
* by directly calling the forms method (which is, in case of populate() the preferred way)
|
||||||
|
* like: $builder->getElements()
|
||||||
|
*
|
||||||
|
* @method \Zend_Form_Element getElement(string $name)
|
||||||
|
* @method \Zend_Form addElement(\string $element, string $name = null, array $options = null)
|
||||||
|
* @method \Zend_Form setView(\Zend_View $view)
|
||||||
|
* @package Icinga\Form
|
||||||
|
*/
|
||||||
|
class Builder
|
||||||
|
{
|
||||||
|
const CSRF_ID = "icinga_csrf_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Zend_Form
|
||||||
|
*/
|
||||||
|
private $form;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null
|
||||||
|
*/
|
||||||
|
private $boundModel = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $disableCSRF = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructrs a new Formbuilder, containing an empty form if no
|
||||||
|
* $form parameter is given or the Zend form from the $form parameter.
|
||||||
|
*
|
||||||
|
* @param \Zend_Form $form The form to use with this Builder
|
||||||
|
* @param Array $options an optional array of Options:
|
||||||
|
* - CSRFProtection true to add a crsf token to the
|
||||||
|
* form (default), false to remove it
|
||||||
|
* - model An referenced array or object to use
|
||||||
|
* for value binding
|
||||||
|
**/
|
||||||
|
public function __construct(\Zend_Form $form = null, array $options = array())
|
||||||
|
{
|
||||||
|
if ($form === null) {
|
||||||
|
$myModel = array(
|
||||||
|
"username" => "",
|
||||||
|
"password" => ""
|
||||||
|
);
|
||||||
|
|
||||||
|
$form = new \Zend_Form();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setZendForm($form);
|
||||||
|
|
||||||
|
if (isset($options["CSRFProtection"])) {
|
||||||
|
$this->disableCSRF = !$options["CSRFProtection"];
|
||||||
|
}
|
||||||
|
if (isset($options["model"])) {
|
||||||
|
$this->bindToModel($options["model"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for Zend_Form
|
||||||
|
* @param \Zend_Form $form
|
||||||
|
*/
|
||||||
|
public function setZendForm(\Zend_Form $form)
|
||||||
|
{
|
||||||
|
$this->form = $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for Zent_Form
|
||||||
|
* @return \Zend_Form
|
||||||
|
*/
|
||||||
|
public function getForm()
|
||||||
|
{
|
||||||
|
if (!$this->disableCSRF) {
|
||||||
|
$this->addCSRFFieldToForm();
|
||||||
|
}
|
||||||
|
if (!$this->form) {
|
||||||
|
return new \Zend_Form();
|
||||||
|
}
|
||||||
|
return $this->form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add elements to form
|
||||||
|
* @param array $elements
|
||||||
|
*/
|
||||||
|
public function addElementsFromConfig(array $elements)
|
||||||
|
{
|
||||||
|
foreach ($elements as $key => $values) {
|
||||||
|
$this->addElement($values[0], $key, $values[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick add elements to a new builder instance
|
||||||
|
* @param array $elements
|
||||||
|
* @param array $options
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public static function fromArray(array $elements, $options = array())
|
||||||
|
{
|
||||||
|
$builder = new Builder(null, $options);
|
||||||
|
$builder->addElementsFromConfig($elements);
|
||||||
|
return $builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the form is valid
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid(array $data = null)
|
||||||
|
{
|
||||||
|
if ($data === null) {
|
||||||
|
$data = $_POST;
|
||||||
|
}
|
||||||
|
return $this->hasValidToken() && $this->form->isValid($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the form was submitted
|
||||||
|
* @param string $btnName
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isSubmitted($btnName = 'submit')
|
||||||
|
{
|
||||||
|
$btn = $this->getElement($btnName);
|
||||||
|
if (!$btn || !isset($_POST[$btnName])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $_POST[$btnName] === $btn->getLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the form
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return $this->getForm()->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->getForm()->__toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable CSRF token field
|
||||||
|
*/
|
||||||
|
public function enableCSRF()
|
||||||
|
{
|
||||||
|
$this->disableCSRF = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable CSRF token field
|
||||||
|
*/
|
||||||
|
public function disableCSRF()
|
||||||
|
{
|
||||||
|
$this->disableCSRF = true;
|
||||||
|
$this->form->removeElement(self::CSRF_ID);
|
||||||
|
$this->form->removeElement(self::CSRF_ID."_seed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add CSRF field to form
|
||||||
|
*/
|
||||||
|
private function addCSRFFieldToForm()
|
||||||
|
{
|
||||||
|
if (!$this->form || $this->disableCSRF || $this->form->getElement(self::CSRF_ID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list($seed, $token) = $this->getSeedTokenPair();
|
||||||
|
|
||||||
|
$this->form->addElement("hidden", self::CSRF_ID);
|
||||||
|
$this->form->getElement(self::CSRF_ID)
|
||||||
|
->setValue($token)
|
||||||
|
->setDecorators(array('ViewHelper'));
|
||||||
|
|
||||||
|
$this->form->addElement("hidden", self::CSRF_ID."_seed");
|
||||||
|
$this->form->getElement(self::CSRF_ID."_seed")
|
||||||
|
->setValue($seed)
|
||||||
|
->setDecorators(array('ViewHelper'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind model to a form
|
||||||
|
* @param $model
|
||||||
|
*/
|
||||||
|
public function bindToModel(&$model)
|
||||||
|
{
|
||||||
|
$this->boundModel = &$model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repopulate
|
||||||
|
*/
|
||||||
|
public function repopulate()
|
||||||
|
{
|
||||||
|
if (!empty($_POST)) {
|
||||||
|
$this->populate($_POST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate form
|
||||||
|
* @param $data
|
||||||
|
* @param bool $ignoreModel
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function populate($data, $ignoreModel = false)
|
||||||
|
{
|
||||||
|
if (is_array($data)) {
|
||||||
|
$this->form->populate($data);
|
||||||
|
} elseif (is_object($data)) {
|
||||||
|
$this->populateFromObject($data);
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException("Builder::populate() expects and object or array, $data given");
|
||||||
|
}
|
||||||
|
if ($this->boundModel === null || $ignoreModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->updateModel();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate form object
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
private function populateFromObject($data)
|
||||||
|
{
|
||||||
|
/** @var \Zend_Form_Element $element */
|
||||||
|
|
||||||
|
foreach ($this->form->getElements() as $name => $element) {
|
||||||
|
if (isset($data->$name)) {
|
||||||
|
$element->setValue($data->$name);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$getter = "get".ucfirst($name);
|
||||||
|
if (method_exists($data, $getter)) {
|
||||||
|
$element->setValue($data->$getter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update model instance
|
||||||
|
*/
|
||||||
|
public function updateModel()
|
||||||
|
{
|
||||||
|
if (is_array($this->boundModel)) {
|
||||||
|
$this->updateArrayModel();
|
||||||
|
} elseif (is_object($this->boundModel)) {
|
||||||
|
$this->updateObjectModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updater for objects
|
||||||
|
*/
|
||||||
|
private function updateObjectModel()
|
||||||
|
{
|
||||||
|
/** @var \Zend_Form_Element $element */
|
||||||
|
|
||||||
|
foreach ($this->form->getElements() as $name => $element) {
|
||||||
|
if (isset($this->boundModel->$name)) {
|
||||||
|
$this->boundModel->$name = $element->getValue();
|
||||||
|
} else {
|
||||||
|
$setter = "set".ucfirst($name);
|
||||||
|
if (method_exists($this->boundModel, $setter)) {
|
||||||
|
$this->boundModel->$setter($element->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updater for arrays
|
||||||
|
*/
|
||||||
|
private function updateArrayModel()
|
||||||
|
{
|
||||||
|
/** @var \Zend_Form_Element $element */
|
||||||
|
|
||||||
|
foreach ($this->form->getElements() as $name => $element) {
|
||||||
|
if (isset($this->boundModel[$name])) {
|
||||||
|
$this->boundModel[$name] = $element->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize model with form
|
||||||
|
*/
|
||||||
|
public function syncWithModel()
|
||||||
|
{
|
||||||
|
$this->populate($this->boundModel, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic caller, pass through method calls to form
|
||||||
|
* @param $fn
|
||||||
|
* @param array $args
|
||||||
|
* @return mixed
|
||||||
|
* @throws \BadMethodCallException
|
||||||
|
*/
|
||||||
|
public function __call($fn, array $args)
|
||||||
|
{
|
||||||
|
if (method_exists($this->form, $fn)) {
|
||||||
|
return call_user_func_array(array($this->form, $fn), $args);
|
||||||
|
} else {
|
||||||
|
throw new \BadMethodCallException(
|
||||||
|
"Method $fn does not exist either ".
|
||||||
|
"in \Icinga\Form\Builder nor in Zend_Form"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the token parameter is valid
|
||||||
|
*
|
||||||
|
* @param int $maxAge Max allowed token age
|
||||||
|
* @param string $sessionId A specific session id (useful for tests?)
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasValidToken($maxAge = 600, $sessionId = null)
|
||||||
|
{
|
||||||
|
if ($this->disableCSRF) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->form->getElement(self::CSRF_ID) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sessionId = $sessionId ? $sessionId : session_id();
|
||||||
|
$seed = $this->form->getElement(self::CSRF_ID.'_seed')->getValue();
|
||||||
|
if (! is_numeric($seed)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove quantitized timestamp portion so maxAge applies
|
||||||
|
$seed -= (intval(time() / $maxAge) * $maxAge);
|
||||||
|
$token = $this->getElement(self::CSRF_ID)->getValue();
|
||||||
|
return $token === hash('sha256', $sessionId . $seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new seed/token pair
|
||||||
|
*
|
||||||
|
* @param int $maxAge Max allowed token age
|
||||||
|
* @param string $sessionId A specific session id (useful for tests?)
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSeedTokenPair($maxAge = 600, $sessionId = null)
|
||||||
|
{
|
||||||
|
$sessionId = $sessionId ? $sessionId : session_id();
|
||||||
|
$seed = mt_rand();
|
||||||
|
$hash = hash('sha256', $sessionId . $seed);
|
||||||
|
|
||||||
|
// Add quantitized timestamp portion to apply maxAge
|
||||||
|
$seed += (intval(time() / $maxAge) * $maxAge);
|
||||||
|
return array($seed, $hash);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Protocol\Ldap;
|
namespace Icinga\Protocol\Ldap;
|
||||||
|
|
||||||
|
use Icinga\Exception\ConfigurationError as ConfigError;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\Logger as Log;
|
use Icinga\Application\Logger as Log;
|
||||||
@ -69,6 +70,10 @@ class Connection
|
|||||||
// '1.3.6.1.1.8' => '8', // Cancel Extended Request
|
// '1.3.6.1.1.8' => '8', // Cancel Extended Request
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected $use_tls = false;
|
||||||
|
protected $force_tls = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@ -116,7 +121,8 @@ class Connection
|
|||||||
$this->bind_dn = $config->bind_dn;
|
$this->bind_dn = $config->bind_dn;
|
||||||
$this->bind_pw = $config->bind_pw;
|
$this->bind_pw = $config->bind_pw;
|
||||||
$this->root_dn = $config->root_dn;
|
$this->root_dn = $config->root_dn;
|
||||||
|
$this->use_tls = isset($config->tls) ? $config->tls : false;
|
||||||
|
$this->force_tls = $this->use_tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,6 +272,7 @@ class Connection
|
|||||||
// We do not support pagination right now, and there is no chance to
|
// We do not support pagination right now, and there is no chance to
|
||||||
// do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
|
// do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
|
||||||
// therefore not be hidden right now.
|
// therefore not be hidden right now.
|
||||||
|
Log::debug("Query: %s", $query->__toString());
|
||||||
$results = ldap_search(
|
$results = ldap_search(
|
||||||
$this->ds,
|
$this->ds,
|
||||||
$this->root_dn,
|
$this->root_dn,
|
||||||
@ -405,7 +412,6 @@ class Connection
|
|||||||
if (isset($result->supportedExtension)) {
|
if (isset($result->supportedExtension)) {
|
||||||
foreach ($result->supportedExtension as $oid) {
|
foreach ($result->supportedExtension as $oid) {
|
||||||
if (array_key_exists($oid, $this->ldap_extension)) {
|
if (array_key_exists($oid, $this->ldap_extension)) {
|
||||||
echo $this->ldap_extension[$oid] . "\n";
|
|
||||||
// STARTTLS -> läuft mit OpenLDAP
|
// STARTTLS -> läuft mit OpenLDAP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,17 +435,16 @@ class Connection
|
|||||||
if ($this->ds !== null) {
|
if ($this->ds !== null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$use_tls = true;
|
|
||||||
$force_tls = true;
|
|
||||||
|
|
||||||
if ($use_tls) {
|
if ($this->use_tls) {
|
||||||
$this->prepareTlsEnvironment();
|
$this->prepareTlsEnvironment();
|
||||||
}
|
}
|
||||||
Log::debug("Trying to connect to %s", $this->hostname);
|
Log::debug("Trying to connect to %s", $this->hostname);
|
||||||
$this->ds = ldap_connect($this->hostname, 389);
|
$this->ds = ldap_connect($this->hostname, 389);
|
||||||
$this->discoverCapabilities();
|
$this->discoverCapabilities();
|
||||||
|
if ($this->use_tls) {
|
||||||
Log::debug("Trying ldap_start_tls()");
|
Log::debug("Trying ldap_start_tls()");
|
||||||
if (ldap_start_tls($this->ds)) {
|
if (@ldap_start_tls($this->ds)) {
|
||||||
Log::debug("Trying ldap_start_tls() succeeded");
|
Log::debug("Trying ldap_start_tls() succeeded");
|
||||||
} else {
|
} else {
|
||||||
Log::warn(
|
Log::warn(
|
||||||
@ -447,6 +452,7 @@ class Connection
|
|||||||
ldap_error($this->ds)
|
ldap_error($this->ds)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ldap_rename requires LDAPv3:
|
// ldap_rename requires LDAPv3:
|
||||||
@ -470,12 +476,10 @@ class Connection
|
|||||||
'***',
|
'***',
|
||||||
ldap_error($this->ds)
|
ldap_error($this->ds)
|
||||||
);
|
);
|
||||||
throw new Exception(
|
throw new ConfigError(
|
||||||
sprintf(
|
sprintf(
|
||||||
'LDAP connection (%s / %s) failed: %s',
|
'Could not connect to the authentication server, please '.
|
||||||
$this->bind_dn,
|
'review your LDAP connection settings.'
|
||||||
'***' /* $this->bind_pw */,
|
|
||||||
ldap_error($this->ds)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -110,10 +110,6 @@ class ActionController extends ZfController
|
|||||||
* @todo remove this!
|
* @todo remove this!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->allowAccess = true;
|
|
||||||
$this->init();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if ($this->handlesAuthentication() ||
|
if ($this->handlesAuthentication() ||
|
||||||
Manager::getInstance(
|
Manager::getInstance(
|
||||||
@ -338,48 +334,4 @@ class ActionController extends ZfController
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the token parameter is valid
|
|
||||||
*
|
|
||||||
* TODO: Could this make use of Icinga\Web\Session once done?
|
|
||||||
*
|
|
||||||
* @param int $maxAge Max allowed token age
|
|
||||||
* @param string $sessionId A specific session id (useful for tests?)
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasValidToken($maxAge = 600, $sessionId = null)
|
|
||||||
{
|
|
||||||
$sessionId = $sessionId ? $sessionId : session_id();
|
|
||||||
$seed = $this->_getParam('seed');
|
|
||||||
if (!is_numeric($seed)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove quantitized timestamp portion so maxAge applies
|
|
||||||
$seed -= (intval(time() / $maxAge) * $maxAge);
|
|
||||||
$token = $this->_getParam('token');
|
|
||||||
return $token === hash('sha256', $sessionId . $seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a new seed/token pair
|
|
||||||
*
|
|
||||||
* TODO: Could this make use of Icinga\Web\Session once done?
|
|
||||||
*
|
|
||||||
* @param int $maxAge Max allowed token age
|
|
||||||
* @param string $sessionId A specific session id (useful for tests?)
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getSeedTokenPair($maxAge = 600, $sessionId = null)
|
|
||||||
{
|
|
||||||
$sessionId = $sessionId ? $sessionId : session_id();
|
|
||||||
$seed = mt_rand();
|
|
||||||
$hash = hash('sha256', $sessionId . $seed);
|
|
||||||
|
|
||||||
// Add quantitized timestamp portion to apply maxAge
|
|
||||||
$seed += (intval(time() / $maxAge) * $maxAge);
|
|
||||||
return array($seed, $hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ namespace Icinga\Web;
|
|||||||
use Icinga\Exception\ProgrammingError;
|
use Icinga\Exception\ProgrammingError;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Application\Logger as Log;
|
use Icinga\Application\Logger as Log;
|
||||||
use Zend_Session_Namespace as SessionNamespace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Notification
|
* Class Notification
|
||||||
@ -149,10 +148,10 @@ class Notification
|
|||||||
*/
|
*/
|
||||||
final private function __construct()
|
final private function __construct()
|
||||||
{
|
{
|
||||||
$this->session = new SessionNamespace('IcingaNotification');
|
//$this->session = new SessionNamespace('IcingaNotification');
|
||||||
if (!is_array($this->session->messages)) {
|
//if (!is_array($this->session->messages)) {
|
||||||
$this->session->messages = array();
|
$this->session->messages = array();
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (Platform::isCli()) {
|
if (Platform::isCli()) {
|
||||||
$this->cliFlag = true;
|
$this->cliFlag = true;
|
||||||
|
@ -41,20 +41,27 @@ define(['jquery','logging','icinga/util/async'],function($,log,async) {
|
|||||||
|
|
||||||
if(typeof target === "undefined") {
|
if(typeof target === "undefined") {
|
||||||
if(a.parents("#icinga-detail").length) {
|
if(a.parents("#icinga-detail").length) {
|
||||||
|
log.debug("Parent is detail, loading into detail");
|
||||||
async.loadToTarget("icinga-detail",href);
|
async.loadToTarget("icinga-detail",href);
|
||||||
} else {
|
} else {
|
||||||
|
log.debug("Parent is not detail, loading into main");
|
||||||
async.loadToTarget("icinga-main",href);
|
async.loadToTarget("icinga-main",href);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(target) {
|
switch(target) {
|
||||||
|
case "body":
|
||||||
|
async.loadToTarget("body", href);
|
||||||
|
break;
|
||||||
case "main":
|
case "main":
|
||||||
async.loadToTarget("icinga-main",href);
|
async.loadToTarget("icinga-main",href);
|
||||||
collapseDetailView();
|
collapseDetailView();
|
||||||
break;
|
break;
|
||||||
case "detail":
|
case "detail":
|
||||||
|
log.debug("Target: detail");
|
||||||
async.loadToTarget("icinga-detail",href);
|
async.loadToTarget("icinga-detail",href);
|
||||||
break;
|
break;
|
||||||
case "popup":
|
case "popup":
|
||||||
|
log.debug("No target");
|
||||||
async.loadToTarget(null,href);
|
async.loadToTarget(null,href);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -88,7 +95,5 @@ define(['jquery','logging','icinga/util/async'],function($,log,async) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return new MainDetailBehaviour();
|
return new MainDetailBehaviour();
|
||||||
});
|
});
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
var containerMgrInstance = null;
|
var containerMgrInstance = null;
|
||||||
var async;
|
var async;
|
||||||
|
|
||||||
var ContainerMgr = function($,log,Widgets,SubTable,holder) {
|
var ContainerMgr = function($,log,Widgets,SubTable) {
|
||||||
|
|
||||||
|
|
||||||
var enhanceDetachLinks = function() {
|
var enhanceDetachLinks = function() {
|
||||||
@ -24,7 +24,7 @@
|
|||||||
this.updateContainer = function(id,content,req) {
|
this.updateContainer = function(id,content,req) {
|
||||||
var target = id;
|
var target = id;
|
||||||
if (typeof id === "string") {
|
if (typeof id === "string") {
|
||||||
target = $('div[container-id='+id+']');
|
target = this.getContainer(id);
|
||||||
}
|
}
|
||||||
var ctrl = $('.container-controls',target);
|
var ctrl = $('.container-controls',target);
|
||||||
target.html(content);
|
target.html(content);
|
||||||
@ -34,14 +34,12 @@
|
|||||||
}
|
}
|
||||||
target.focus();
|
target.focus();
|
||||||
this.initializeContainers(target);
|
this.initializeContainers(target);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateControlTargets = function(ctrl, req) {
|
this.updateControlTargets = function(ctrl, req) {
|
||||||
$('a',ctrl).each(function() {
|
$('a',ctrl).each(function() {
|
||||||
$(this).attr("href",req.url);
|
$(this).attr("href",req.url);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initControlBehaviour = function(root) {
|
this.initControlBehaviour = function(root) {
|
||||||
@ -86,7 +84,6 @@
|
|||||||
this.initExpandables(root);
|
this.initExpandables(root);
|
||||||
this.drawImplicitWidgets(root);
|
this.drawImplicitWidgets(root);
|
||||||
this.loadAsyncContainers(root);
|
this.loadAsyncContainers(root);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createPopupContainer = function(content,req) {
|
this.createPopupContainer = function(content,req) {
|
||||||
@ -96,10 +93,12 @@
|
|||||||
.append($("<div>").addClass('modal-body').html(content)).appendTo(document.body);
|
.append($("<div>").addClass('modal-body').html(content)).appendTo(document.body);
|
||||||
|
|
||||||
closeButton.on("click",function() {container.remove();});
|
closeButton.on("click",function() {container.remove();});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getContainer = function(id) {
|
this.getContainer = function(id) {
|
||||||
|
if(id == 'body') {
|
||||||
|
return $(document.body);
|
||||||
|
}
|
||||||
return $('div[container-id='+id+']');
|
return $('div[container-id='+id+']');
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,6 +108,5 @@
|
|||||||
containerMgrInstance = new ContainerMgr($,log,widgets,subTable);
|
containerMgrInstance = new ContainerMgr($,log,widgets,subTable);
|
||||||
}
|
}
|
||||||
return containerMgrInstance;
|
return containerMgrInstance;
|
||||||
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -13,12 +13,13 @@ define([
|
|||||||
* Icinga prototype
|
* Icinga prototype
|
||||||
*/
|
*/
|
||||||
var Icinga = function() {
|
var Icinga = function() {
|
||||||
var internalModules = ['icinga/modules/actionTable','icinga/modules/mainDetail'];
|
var internalModules = ['icinga/components/actionTable','icinga/components/mainDetail'];
|
||||||
|
|
||||||
this.modules = {};
|
this.modules = {};
|
||||||
var failedModules = [];
|
var failedModules = [];
|
||||||
|
|
||||||
var initialize = function () {
|
var initialize = function () {
|
||||||
|
registerLazyModuleLoading();
|
||||||
enableInternalModules();
|
enableInternalModules();
|
||||||
|
|
||||||
containerMgr.registerAsyncMgr(async);
|
containerMgr.registerAsyncMgr(async);
|
||||||
@ -28,7 +29,9 @@ define([
|
|||||||
enableModules();
|
enableModules();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var registerLazyModuleLoading = function() {
|
||||||
|
async.registerHeaderListener("X-Icinga-Enable-Module", loadModuleScript, this);
|
||||||
|
};
|
||||||
|
|
||||||
var enableInternalModules = function() {
|
var enableInternalModules = function() {
|
||||||
$.each(internalModules,function(idx,module) {
|
$.each(internalModules,function(idx,module) {
|
||||||
@ -37,7 +40,8 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var loadModuleScript = function(name) {
|
var loadModuleScript = function(name) {
|
||||||
moduleMgr.enableModule("modules/"+name, function(error) {
|
console.log("Loading ", name);
|
||||||
|
moduleMgr.enableModule("modules/"+name+"/"+name, function(error) {
|
||||||
failedModules.push({
|
failedModules.push({
|
||||||
name: name,
|
name: name,
|
||||||
errorMessage: error
|
errorMessage: error
|
||||||
@ -81,5 +85,3 @@ define([
|
|||||||
};
|
};
|
||||||
return new Icinga();
|
return new Icinga();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
define(['icinga/container','logging','jquery'],function(containerMgr,log,$) {
|
define(['icinga/container','logging','jquery'],function(containerMgr,log,$) {
|
||||||
|
|
||||||
|
var headerListeners = {};
|
||||||
|
|
||||||
var pending = {
|
var pending = {
|
||||||
|
|
||||||
@ -46,11 +47,30 @@
|
|||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleResponse = function(html) {
|
var applyHeaderListeners = function(headers) {
|
||||||
|
for (var header in headerListeners) {
|
||||||
|
if (headers.getResponseHeader(header) === null) {
|
||||||
|
// see if the browser/server converts headers to lowercase
|
||||||
|
if (headers.getResponseHeader(header.toLowerCase()) === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
header = header.toLowerCase();
|
||||||
|
}
|
||||||
|
var value = headers.getResponseHeader(header);
|
||||||
|
var listeners = headerListeners[header];
|
||||||
|
for (var i=0;i<listeners.length;i++) {
|
||||||
|
listeners[i].fn.apply(listeners[i].scope, [value, header, headers]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var handleResponse = function(html, status, response) {
|
||||||
|
applyHeaderListeners(response);
|
||||||
if(this.destination) {
|
if(this.destination) {
|
||||||
containerMgr.updateContainer(this.destination,html,this);
|
containerMgr.updateContainer(this.destination,html,this);
|
||||||
} else {
|
} else {
|
||||||
containerMgr.createPopupContainer(html,this);
|
// tbd
|
||||||
|
// containerMgr.createPopupContainer(html,this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,6 +96,8 @@
|
|||||||
|
|
||||||
var CallInterface = function() {
|
var CallInterface = function() {
|
||||||
|
|
||||||
|
this.__internalXHRImplementation = $.ajax;
|
||||||
|
|
||||||
this.clearPendingRequestsFor = function(destination) {
|
this.clearPendingRequestsFor = function(destination) {
|
||||||
if(!$.isArray(pending)) {
|
if(!$.isArray(pending)) {
|
||||||
pending = [];
|
pending = [];
|
||||||
@ -95,7 +117,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.createRequest = function(url,data) {
|
this.createRequest = function(url,data) {
|
||||||
var req = $.ajax({
|
var req = this.__internalXHRImplementation({
|
||||||
type : data ? 'POST' : 'GET',
|
type : data ? 'POST' : 'GET',
|
||||||
url : url,
|
url : url,
|
||||||
data : data,
|
data : data,
|
||||||
@ -109,6 +131,7 @@
|
|||||||
|
|
||||||
this.loadToTarget = function(destination,url,data) {
|
this.loadToTarget = function(destination,url,data) {
|
||||||
if(destination) {
|
if(destination) {
|
||||||
|
log.debug("Laoding to container", destination, url);
|
||||||
this.clearPendingRequestsFor(destination);
|
this.clearPendingRequestsFor(destination);
|
||||||
}
|
}
|
||||||
var req = this.createRequest(url,data);
|
var req = this.createRequest(url,data);
|
||||||
@ -132,8 +155,12 @@
|
|||||||
this.loadCSS = function(name) {
|
this.loadCSS = function(name) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.registerHeaderListener = function(header, fn, scope) {
|
||||||
|
headerListeners[header] = headerListeners[header] || [];
|
||||||
|
headerListeners[header].push({fn: fn, scope:scope});
|
||||||
|
};
|
||||||
};
|
};
|
||||||
return new CallInterface();
|
return new CallInterface();
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -24,4 +24,3 @@ define(['jquery','Holder'], function ($) {
|
|||||||
window.Icinga = Icinga;
|
window.Icinga = Icinga;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
35
test/js/test/icinga/asyncTest.js
Normal file
35
test/js/test/icinga/asyncTest.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
// {{LICENSE_HEADER}}
|
||||||
|
// {{LICENSE_HEADER}}
|
||||||
|
var should = require("should");
|
||||||
|
var rjsmock = require("requiremock.js");
|
||||||
|
var asyncMock = require("asyncmock.js");
|
||||||
|
|
||||||
|
GLOBAL.document = $('body');
|
||||||
|
|
||||||
|
|
||||||
|
describe('The async module', function() {
|
||||||
|
it("Allows to react on specific headers", function(done) {
|
||||||
|
rjsmock.purgeDependencies();
|
||||||
|
rjsmock.registerDependencies({
|
||||||
|
'icinga/container' : {
|
||||||
|
updateContainer : function() {},
|
||||||
|
createPopupContainer: function() {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
requireNew("icinga/util/async.js");
|
||||||
|
var async = rjsmock.getDefine();
|
||||||
|
var headerValue = null;
|
||||||
|
asyncMock.setNextAsyncResult(async, "result", false, {
|
||||||
|
'X-Dont-Care' : 'Ignore-me',
|
||||||
|
'X-Test-Header' : 'Testme123'
|
||||||
|
});
|
||||||
|
async.registerHeaderListener("X-Test-Header", function(value, header) {
|
||||||
|
should.equal("Testme123", value);
|
||||||
|
done();
|
||||||
|
},this);
|
||||||
|
var test = async.createRequest();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -9,12 +9,12 @@
|
|||||||
// {{LICENSE_HEADER}}
|
// {{LICENSE_HEADER}}
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var rjsmock = require("requiremock.js");
|
var rjsmock = require("requiremock.js");
|
||||||
|
var asyncMock = require("asyncmock.js");
|
||||||
|
|
||||||
var BASE = "../../../../public/js/";
|
requireNew("icinga/module.js");
|
||||||
require(BASE+"icinga/module.js");
|
|
||||||
|
|
||||||
var module = rjsmock.getDefine();
|
var module = rjsmock.getDefine();
|
||||||
GLOBAL.document = $('body');
|
GLOBAL.document = $('body');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test module that only uses eventhandlers and
|
* Test module that only uses eventhandlers and
|
||||||
* no custom logic
|
* no custom logic
|
||||||
@ -195,7 +195,10 @@ describe('The icinga module bootstrap', function() {
|
|||||||
var testClick = false;
|
var testClick = false;
|
||||||
rjsmock.registerDependencies({
|
rjsmock.registerDependencies({
|
||||||
"icinga/module": module,
|
"icinga/module": module,
|
||||||
"modules/test" : {
|
"icinga/util/async" : {
|
||||||
|
registerHeaderListener: function() {}
|
||||||
|
},
|
||||||
|
"modules/test/test" : {
|
||||||
eventHandler: {
|
eventHandler: {
|
||||||
"a.test" : {
|
"a.test" : {
|
||||||
click : function() {
|
click : function() {
|
||||||
@ -214,7 +217,7 @@ describe('The icinga module bootstrap', function() {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
tearDownTestDOM();
|
tearDownTestDOM();
|
||||||
require(BASE+"icinga/icinga.js");
|
requireNew("icinga/icinga.js");
|
||||||
var icinga = rjsmock.getDefine();
|
var icinga = rjsmock.getDefine();
|
||||||
$('body').append($("<a class='test'></a>"));
|
$('body').append($("<a class='test'></a>"));
|
||||||
$('a.test').click();
|
$('a.test').click();
|
||||||
@ -223,4 +226,55 @@ describe('The icinga module bootstrap', function() {
|
|||||||
should.equal(icinga.getFailedModules()[0].name, "test2");
|
should.equal(icinga.getFailedModules()[0].name, "test2");
|
||||||
tearDownTestDOM();
|
tearDownTestDOM();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should load modules lazily when discovering a X-Icinga-Enable-Module header", function() {
|
||||||
|
rjsmock.purgeDependencies();
|
||||||
|
|
||||||
|
requireNew("icinga/util/async.js");
|
||||||
|
var async = rjsmock.getDefine();
|
||||||
|
|
||||||
|
rjsmock.registerDependencies({
|
||||||
|
"icinga/module": module,
|
||||||
|
"icinga/util/async": async,
|
||||||
|
"modules/test/test" : {
|
||||||
|
eventHandler: {
|
||||||
|
"a.test" : {
|
||||||
|
click : function() {
|
||||||
|
testClick = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icinga/container" : {
|
||||||
|
registerAsyncMgr: function() {},
|
||||||
|
initializeContainers: function() {}
|
||||||
|
},
|
||||||
|
"modules/list" : [
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDownTestDOM();
|
||||||
|
|
||||||
|
requireNew("icinga/icinga.js");
|
||||||
|
var icinga = rjsmock.getDefine();
|
||||||
|
|
||||||
|
var testClick = false;
|
||||||
|
// The module shouldn't be loaded
|
||||||
|
$('body').append($("<a class='test'></a>"));
|
||||||
|
$('a.test').click();
|
||||||
|
should.equal(testClick, false, "Unregistered module was loaded");
|
||||||
|
|
||||||
|
asyncMock.setNextAsyncResult(async,"result", false, {
|
||||||
|
"X-Icinga-Enable-Module" : "test"
|
||||||
|
});
|
||||||
|
async.createRequest();
|
||||||
|
// The module shouldn't be loaded
|
||||||
|
$('body').append($("<a class='test'></a>"));
|
||||||
|
$('a.test').click();
|
||||||
|
should.equal(testClick, true, "Module wasn't automatically loaded on header!");
|
||||||
|
|
||||||
|
|
||||||
|
tearDownTestDOM();
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
33
test/js/testlib/asyncmock.js
Normal file
33
test/js/testlib/asyncmock.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Helper for mocking $.async's XHR requests
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var getCallback = function(empty, response, succeed, headers) {
|
||||||
|
if (empty)
|
||||||
|
return function() {};
|
||||||
|
return function(callback) {
|
||||||
|
callback(response, succeed, {
|
||||||
|
getAllResponseHeaders: function() {
|
||||||
|
return headers;
|
||||||
|
},
|
||||||
|
getResponseHeader: function(header) {
|
||||||
|
return headers[header] || null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
setNextAsyncResult: function(async, response, fails, headers) {
|
||||||
|
headers = headers || {};
|
||||||
|
var succeed = fails ? "fail" : "success";
|
||||||
|
async.__internalXHRImplementation = function(config) {
|
||||||
|
return {
|
||||||
|
done: getCallback(fails, response, succeed, headers),
|
||||||
|
fail: getCallback(!fails, response, succeed, headers)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
@ -13,6 +13,7 @@
|
|||||||
* to console.
|
* to console.
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
var path = require('path');
|
||||||
var registeredDependencies = {};
|
var registeredDependencies = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +22,12 @@ var registeredDependencies = {};
|
|||||||
* in dependencies and calls fn with them as the parameter
|
* in dependencies and calls fn with them as the parameter
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
var debug = false;
|
||||||
var requireJsMock = function(dependencies, fn) {
|
var requireJsMock = function(dependencies, fn) {
|
||||||
var fnArgs = [];
|
var fnArgs = [];
|
||||||
for (var i=0;i<dependencies.length;i++) {
|
for (var i=0;i<dependencies.length;i++) {
|
||||||
if (typeof registeredDependencies[dependencies[i]] === "undefined") {
|
if (typeof registeredDependencies[dependencies[i]] === "undefined") {
|
||||||
|
if (debug === true)
|
||||||
console.warn("Unknown dependency "+dependencies[i]+" in define()");
|
console.warn("Unknown dependency "+dependencies[i]+" in define()");
|
||||||
}
|
}
|
||||||
fnArgs.push(registeredDependencies[dependencies[i]]);
|
fnArgs.push(registeredDependencies[dependencies[i]]);
|
||||||
@ -55,7 +58,7 @@ var defineMock = function() {
|
|||||||
var argList = arguments[currentArg];
|
var argList = arguments[currentArg];
|
||||||
fn = arguments[currentArg+1];
|
fn = arguments[currentArg+1];
|
||||||
for (var i=0;i<argList.length;i++) {
|
for (var i=0;i<argList.length;i++) {
|
||||||
if (typeof registerDependencies[argList[i]] === "undefined") {
|
if (typeof registerDependencies[argList[i]] === "undefined" && debug) {
|
||||||
console.warn("Unknown dependency "+argList[i]+" in define()");
|
console.warn("Unknown dependency "+argList[i]+" in define()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +94,6 @@ initRequireMethods();
|
|||||||
function purgeDependencies() {
|
function purgeDependencies() {
|
||||||
registeredDependencies = {
|
registeredDependencies = {
|
||||||
'jquery' : GLOBAL.$,
|
'jquery' : GLOBAL.$,
|
||||||
'__define__' : registeredDependencies.__define__,
|
|
||||||
'logging' : console
|
'logging' : console
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -107,6 +109,12 @@ function registerDependencies(obj) {
|
|||||||
registeredDependencies[name] = obj[name];
|
registeredDependencies[name] = obj[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var base = path.normalize(__dirname+"../../../../public/js");
|
||||||
|
GLOBAL.requireNew = function(key) {
|
||||||
|
key = path.normalize(base+"/"+key);
|
||||||
|
delete require.cache[key];
|
||||||
|
return require(key);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The API for this module
|
* The API for this module
|
||||||
@ -122,3 +130,4 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,21 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
if(!class_exists('Zend_View_Helper_Abstract')) {
|
|
||||||
abstract class Zend_View_Helper_Abstract {
|
|
||||||
public $basename;
|
|
||||||
|
|
||||||
public function __construct($basename = '') {
|
require_once('Zend/View/Helper/Abstract.php');
|
||||||
$this->view = $this;
|
require_once('Zend/View.php');
|
||||||
$this->basename = $basename;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function baseUrl($url) {
|
require_once('../../application/views/helpers/Qlink.php');
|
||||||
return $this->basename.$url;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
require('../../application/views/helpers/Qlink.php');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,30 +19,37 @@ class Zend_View_Helper_QlinkTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testURLPathParameter()
|
public function testURLPathParameter()
|
||||||
{
|
{
|
||||||
|
$view = new Zend_View();
|
||||||
|
|
||||||
$helper = new Zend_View_Helper_Qlink();
|
$helper = new Zend_View_Helper_Qlink();
|
||||||
$pathTpl = "path/%s/to/%s";
|
$helper->setView($view);
|
||||||
|
$pathTpl = "/path/%s/to/%s";
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
"path/param1/to/param2",
|
"/path/param1/to/param2",
|
||||||
$helper->getFormattedURL($pathTpl,array('param1','param2'))
|
$helper->getFormattedURL($pathTpl,array('param1','param2'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUrlGETParameter()
|
public function testUrlGETParameter()
|
||||||
{
|
{
|
||||||
|
$view = new Zend_View();
|
||||||
$helper = new Zend_View_Helper_Qlink();
|
$helper = new Zend_View_Helper_Qlink();
|
||||||
|
$helper->setView($view);
|
||||||
$pathTpl = 'path';
|
$pathTpl = 'path';
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'path?param1=value1&param2=value2',
|
'/path?param1=value1&param2=value2',
|
||||||
$helper->getFormattedURL($pathTpl,array('param1'=>'value1','param2'=>'value2'))
|
$helper->getFormattedURL($pathTpl,array('param1'=>'value1','param2'=>'value2'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMixedParameters()
|
public function testMixedParameters()
|
||||||
{
|
{
|
||||||
|
$view = new Zend_View();
|
||||||
$helper = new Zend_View_Helper_Qlink();
|
$helper = new Zend_View_Helper_Qlink();
|
||||||
|
$helper->setView($view);
|
||||||
$pathTpl = 'path/%s/to/%s';
|
$pathTpl = 'path/%s/to/%s';
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'path/path1/to/path2?param1=value1&param2=value2',
|
'/path/path1/to/path2?param1=value1&param2=value2',
|
||||||
$helper->getFormattedURL($pathTpl,array(
|
$helper->getFormattedURL($pathTpl,array(
|
||||||
'path1','path2',
|
'path1','path2',
|
||||||
'param1'=>'value1',
|
'param1'=>'value1',
|
||||||
|
111
test/php/library/Icinga/Application/Modules/Manager.php
Normal file
111
test/php/library/Icinga/Application/Modules/Manager.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Application\Module\Manager;
|
||||||
|
|
||||||
|
require_once("../../library/Icinga/Application/Modules/Manager.php");
|
||||||
|
require_once("../../library/Icinga/Exception/ProgrammingError.php");
|
||||||
|
require_once("../../library/Icinga/Exception/ConfigurationError.php");
|
||||||
|
require_once("../../library/Icinga/Exception/SystemPermissionException.php");
|
||||||
|
|
||||||
|
use Icinga\Application\Modules\Manager as ModuleManager;
|
||||||
|
|
||||||
|
class ModuleMock
|
||||||
|
{
|
||||||
|
|
||||||
|
public $name = "";
|
||||||
|
public $dir = "";
|
||||||
|
|
||||||
|
public function __construct($app, $name, $dir)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->dir = $dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ManagerTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
const MODULE_TARGET = "/tmp";
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$moduleDir = self::MODULE_TARGET;
|
||||||
|
if (!is_writable($moduleDir)) {
|
||||||
|
$this->markTestSkipped("Temporary folder not writable for this user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_dir($moduleDir."/enabledModules")) {
|
||||||
|
exec("rm -r $moduleDir/enabledModules");
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir($moduleDir."/enabledModules");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDetectEnabledModules()
|
||||||
|
{
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("none"));
|
||||||
|
$this->assertEmpty($manager->listEnabledModules());
|
||||||
|
|
||||||
|
symlink(getcwd()."/res/testModules/module1", "/tmp/enabledModules/module1");
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("none"));
|
||||||
|
$this->assertEquals(array("module1"), $manager->listEnabledModules());
|
||||||
|
symlink(getcwd()."/res/testModules/module2", "/tmp/enabledModules/module2");
|
||||||
|
symlink(getcwd()."/res/???", "/tmp/enabledModules/module3");
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("none"));
|
||||||
|
$this->assertEquals(array("module1", "module2"), $manager->listEnabledModules());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadModule()
|
||||||
|
{
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules"));
|
||||||
|
$this->assertEmpty($manager->getLoadedModules());
|
||||||
|
$manager->loadModule("module1", "Tests\Icinga\Application\Module\Manager\ModuleMock");
|
||||||
|
$elems = $manager->getLoadedModules();
|
||||||
|
$this->assertNotEmpty($elems);
|
||||||
|
$this->assertTrue(isset($elems["module1"]));
|
||||||
|
// assert the changes not to be permanent:
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules"));
|
||||||
|
$this->assertEmpty($manager->getLoadedModules());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEnableModule()
|
||||||
|
{
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array(getcwd()."/res/testModules"));
|
||||||
|
$this->assertEmpty($manager->listEnabledModules());
|
||||||
|
$manager->enableModule("module1");
|
||||||
|
$elems = $manager->listEnabledModules();
|
||||||
|
$this->assertNotEmpty($elems);
|
||||||
|
$this->assertEquals($elems[0], "module1");
|
||||||
|
$this->assertTrue(is_link("/tmp/enabledModules/module1"));
|
||||||
|
// assert the changes to be permanent:
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules"));
|
||||||
|
$this->assertNotEmpty($manager->listEnabledModules());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDisableModule()
|
||||||
|
{
|
||||||
|
clearstatcache(true);
|
||||||
|
symlink(getcwd()."/res/testModules/module1", "/tmp/enabledModules/module1");
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array(getcwd()."/res/testModules"));
|
||||||
|
$elems = $manager->listEnabledModules();
|
||||||
|
$this->assertNotEmpty($elems);
|
||||||
|
$this->assertEquals($elems[0], "module1");
|
||||||
|
$manager->disableModule("module1");
|
||||||
|
$this->assertFalse(file_exists("/tmp/enabledModules/module1"));
|
||||||
|
$this->assertEmpty($manager->listEnabledModules());
|
||||||
|
// assert the changes to be permanent:
|
||||||
|
$manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules"));
|
||||||
|
$this->assertEmpty($manager->listEnabledModules());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$moduleDir = self::MODULE_TARGET;
|
||||||
|
exec("rm -r $moduleDir/enabledModules");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ namespace Tests\Icinga\Authentication;
|
|||||||
require_once("../../library/Icinga/Authentication/Session.php");
|
require_once("../../library/Icinga/Authentication/Session.php");
|
||||||
require_once("../../library/Icinga/Authentication/PhpSession.php");
|
require_once("../../library/Icinga/Authentication/PhpSession.php");
|
||||||
require_once("../../library/Icinga/Application/Logger.php");
|
require_once("../../library/Icinga/Application/Logger.php");
|
||||||
|
require_once("../../library/Icinga/Exception/ConfigurationError.php");
|
||||||
require_once("Zend/Log.php");
|
require_once("Zend/Log.php");
|
||||||
|
|
||||||
use Icinga\Authentication\PhpSession as PhpSession;
|
use Icinga\Authentication\PhpSession as PhpSession;
|
||||||
|
224
test/php/library/Icinga/Form/BuilderTest.php
Normal file
224
test/php/library/Icinga/Form/BuilderTest.php
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Test\Icinga\Form;
|
||||||
|
|
||||||
|
require_once("Zend/Form.php");
|
||||||
|
require_once("Zend/View.php");
|
||||||
|
require_once("../../library/Icinga/Form/Builder.php");
|
||||||
|
|
||||||
|
use Icinga\Form\Builder as Builder;
|
||||||
|
|
||||||
|
class BuilderTestModel
|
||||||
|
{
|
||||||
|
public $username = '';
|
||||||
|
public $password = '';
|
||||||
|
private $test;
|
||||||
|
|
||||||
|
public function getTest()
|
||||||
|
{
|
||||||
|
return $this->test;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTest($test)
|
||||||
|
{
|
||||||
|
$this->test = $test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuilderTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
public function testFormCreation()
|
||||||
|
{
|
||||||
|
$builder = new Builder(null, array("CSRFProtection" => false));
|
||||||
|
$this->assertInstanceOf("Zend_Form", $builder->getForm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
public function testCSRFProtectionTokenCreation()
|
||||||
|
{
|
||||||
|
$view = new \Zend_View();
|
||||||
|
$builder = new Builder(); // when no token is given, a CRSF field should be added
|
||||||
|
$builder->setView($view);
|
||||||
|
|
||||||
|
$DOM = new \DOMDocument;
|
||||||
|
$DOM->loadHTML($builder);
|
||||||
|
$this->assertNotNull($DOM->getElementById(Builder::CSRF_ID));
|
||||||
|
|
||||||
|
$builder->disableCSRF();
|
||||||
|
$DOM->loadHTML($builder);
|
||||||
|
$this->assertNull($DOM->getElementById(Builder::CSRF_ID));
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test whether form methods are passed to the Zend_Form object
|
||||||
|
* When called in the Builder instance
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
public function testMethodPassing()
|
||||||
|
{
|
||||||
|
$DOM = new \DOMDocument;
|
||||||
|
$view = new \Zend_View();
|
||||||
|
$builder = new Builder(null, array("CSRFProtection" => false));
|
||||||
|
$builder->setView($view);
|
||||||
|
|
||||||
|
$DOM->loadHTML($builder);
|
||||||
|
$this->assertEquals(0, $DOM->getElementsByTagName("input")->length);
|
||||||
|
|
||||||
|
$builder->addElement("text", "username");
|
||||||
|
$DOM->loadHTML($builder);
|
||||||
|
$inputEls = $DOM->getElementsByTagName("input");
|
||||||
|
$this->assertEquals(1, $inputEls->length);
|
||||||
|
$this->assertEquals("username", $inputEls->item(0)->attributes->getNamedItem("name")->value);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
public function testCreateByArray()
|
||||||
|
{
|
||||||
|
$DOM = new \DOMDocument;
|
||||||
|
$view = new \Zend_View();
|
||||||
|
$builder = Builder::fromArray(
|
||||||
|
array(
|
||||||
|
'username' => array(
|
||||||
|
'text',
|
||||||
|
array(
|
||||||
|
'label' => 'Username',
|
||||||
|
'required' => true,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
'password',
|
||||||
|
array(
|
||||||
|
'label' => 'Password',
|
||||||
|
'required' => true,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'submit' => array(
|
||||||
|
'submit',
|
||||||
|
array(
|
||||||
|
'label' => 'Login'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
"CSRFProtection" => false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$builder->setView($view);
|
||||||
|
|
||||||
|
$DOM->loadHTML($builder);
|
||||||
|
$inputEls = $DOM->getElementsByTagName("input");
|
||||||
|
$this->assertEquals(3, $inputEls->length);
|
||||||
|
|
||||||
|
$username = $inputEls->item(0);
|
||||||
|
$this->assertEquals("username", $username->attributes->getNamedItem("name")->value);
|
||||||
|
|
||||||
|
$password= $inputEls->item(1);
|
||||||
|
$this->assertEquals("password", $password->attributes->getNamedItem("name")->value);
|
||||||
|
$this->assertEquals("password", $password->attributes->getNamedItem("type")->value);
|
||||||
|
|
||||||
|
$submitBtn= $inputEls->item(2);
|
||||||
|
$this->assertEquals("submit", $submitBtn->attributes->getNamedItem("name")->value);
|
||||||
|
$this->assertEquals("submit", $submitBtn->attributes->getNamedItem("type")->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function testModelBindingWithArray()
|
||||||
|
{
|
||||||
|
$view = new \Zend_View();
|
||||||
|
|
||||||
|
$myModel = array(
|
||||||
|
"username" => "",
|
||||||
|
"password" => ""
|
||||||
|
);
|
||||||
|
|
||||||
|
$builder = new Builder(
|
||||||
|
null,
|
||||||
|
array(
|
||||||
|
"CSRFProtection" => false,
|
||||||
|
"model" => &$myModel
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$builder->setView($view);
|
||||||
|
|
||||||
|
// $builder->bindToModel($myModel);
|
||||||
|
$builder->addElement("text", "username");
|
||||||
|
$builder->addElement("password", "password");
|
||||||
|
// test sync from form to model
|
||||||
|
$builder->populate(
|
||||||
|
array(
|
||||||
|
"username" => "User input<html>",
|
||||||
|
"password" => "Secret$123"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEquals("User input<html>", $myModel["username"]);
|
||||||
|
$this->assertEquals("Secret$123", $myModel["password"]);
|
||||||
|
|
||||||
|
// test sync from model to form
|
||||||
|
$myModel["username"] = "Another user";
|
||||||
|
$myModel["password"] = "Another pass";
|
||||||
|
|
||||||
|
$builder->syncWithModel();
|
||||||
|
$this->assertEquals("Another user", $builder->getElement("username")->getValue());
|
||||||
|
$this->assertEquals("Another pass", $builder->getElement("password")->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function testModelBindingWithObject()
|
||||||
|
{
|
||||||
|
$view = new \Zend_View();
|
||||||
|
$builder = new Builder(null, array("CSRFProtection" => false));
|
||||||
|
$builder->setView($view);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$myModel = new BuilderTestModel();
|
||||||
|
|
||||||
|
$builder->bindToModel($myModel);
|
||||||
|
$builder->addElement("text", "username");
|
||||||
|
$builder->addElement("password", "password");
|
||||||
|
$builder->addElement("text", "test");
|
||||||
|
// test sync from form to model
|
||||||
|
$builder->populate(
|
||||||
|
(object) array(
|
||||||
|
"username" => "User input<html>",
|
||||||
|
"password" => "Secret$123",
|
||||||
|
"test" => 'test334'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEquals("User input<html>", $myModel->username);
|
||||||
|
$this->assertEquals("Secret$123", $myModel->password);
|
||||||
|
$this->assertEquals("test334", $myModel->getTest());
|
||||||
|
|
||||||
|
// test sync from model to form
|
||||||
|
$myModel->username = "Another user";
|
||||||
|
$myModel->password = "Another pass";
|
||||||
|
|
||||||
|
$builder->syncWithModel();
|
||||||
|
$this->assertEquals("Another user", $builder->getElement("username")->getValue());
|
||||||
|
$this->assertEquals("Another pass", $builder->getElement("password")->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \BadMethodCallException
|
||||||
|
* @expectedExceptionMessage Method doesNotExist123 does not exist either in \Icinga\Form\Builder nor in Zend_Form
|
||||||
|
*/
|
||||||
|
public function testBadCall1()
|
||||||
|
{
|
||||||
|
$builder = new Builder(null, array("CSRFProtection" => false));
|
||||||
|
$builder->doesNotExist123();
|
||||||
|
}
|
||||||
|
}
|
@ -1,80 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Icinga\Web\ActionController;
|
namespace Tests\Icinga\Web\ActionController;
|
||||||
use Icinga\Web\ActionController as Action;
|
|
||||||
|
|
||||||
require_once('Zend/Controller/Action.php');
|
|
||||||
require_once('../../library/Icinga/Web/ActionController.php');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is not a nice hack, but doesn't affect the behaviour of
|
|
||||||
* the tested methods, allowing us to avoid bootstrapping
|
|
||||||
* the request/response System for every test
|
|
||||||
*
|
|
||||||
* Class ActionTestWrap
|
|
||||||
* @package Tests\Icinga\Mvc\Controller
|
|
||||||
*/
|
|
||||||
class ActionTestWrap extends Action {
|
|
||||||
private $args;
|
|
||||||
public function __construct(\Zend_Controller_Request_Abstract $request = null,
|
|
||||||
\Zend_Controller_Response_Abstract $response = null, array $invokeArgs = array())
|
|
||||||
{}
|
|
||||||
|
|
||||||
public function setArguments($args) {
|
|
||||||
$this->args = $args;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function _getParam($paramName, $default = null) {
|
|
||||||
if(isset($this->args[$paramName]))
|
|
||||||
return $this->args[$paramName];
|
|
||||||
return $default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ActionTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testSeedGeneration()
|
|
||||||
{
|
|
||||||
$action = new ActionTestWrap();
|
|
||||||
list($seed1,$token1) = $action->getSeedTokenPair(600,"test");
|
|
||||||
list($seed2,$token2) = $action->getSeedTokenPair(600,"test");
|
|
||||||
list($seed3,$token3) = $action->getSeedTokenPair(600,"test");
|
|
||||||
$this->assertTrue($seed1 != $seed2 && $seed2 != $seed3 && $seed1 != $seed3);
|
|
||||||
$this->assertTrue($token1 != $token2 && $token2 != $token3 && $token1 != $token3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSeedValidation()
|
|
||||||
{
|
|
||||||
$action = new ActionTestWrap();
|
|
||||||
list($seed,$token) = $action->getSeedTokenPair(600,"test");
|
|
||||||
$action->setArguments(array(
|
|
||||||
"seed" => $seed,
|
|
||||||
"token" => $token
|
|
||||||
));
|
|
||||||
$this->assertTrue($action->hasValidToken(600,"test"));
|
|
||||||
$this->assertFalse($action->hasValidToken(600,"test2"));
|
|
||||||
$action->setArguments(array(
|
|
||||||
"seed" => $seed."ds",
|
|
||||||
"token" => $token
|
|
||||||
));
|
|
||||||
$this->assertFalse($action->hasValidToken(600,"test"));
|
|
||||||
$action->setArguments(array(
|
|
||||||
"seed" => $seed,
|
|
||||||
"token" => $token."afs"
|
|
||||||
));
|
|
||||||
$this->assertFalse($action->hasValidToken(600,"test"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMaxAge()
|
|
||||||
{
|
|
||||||
$action = new ActionTestWrap();
|
|
||||||
list($seed,$token) = $action->getSeedTokenPair(1,"test");
|
|
||||||
$action->setArguments(array(
|
|
||||||
"seed" => $seed,
|
|
||||||
"token" => $token
|
|
||||||
));
|
|
||||||
$this->assertTrue($action->hasValidToken(1,"test"));
|
|
||||||
sleep(1);
|
|
||||||
$this->assertFalse($action->hasValidToken(1,"test"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user