From 5cddbd1162d5f057a9e1ee8111c89a2d1a8705eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?= Date: Mon, 24 Jun 2013 18:40:37 +0200 Subject: [PATCH 01/10] Add Form\Builder The builder class allows to create forms and bind them to models. The tests are currently failing because of the zend pluginloader, this must be evaluated refs #4302 --- library/Icinga/Form/Builder.php | 280 +++++++++++++++++++ test/php/library/Icinga/Form/BuilderTest.php | 183 ++++++++++++ 2 files changed, 463 insertions(+) create mode 100644 library/Icinga/Form/Builder.php create mode 100644 test/php/library/Icinga/Form/BuilderTest.php diff --git a/library/Icinga/Form/Builder.php b/library/Icinga/Form/Builder.php new file mode 100644 index 000000000..4526f7624 --- /dev/null +++ b/library/Icinga/Form/Builder.php @@ -0,0 +1,280 @@ +getForm() or +* by directly calling the forms method (which is, in case of populate() the preferred way) +* like: $builder->getElements() +* +**/ +class Builder +{ + const CSRF_ID = "icinga_csrf_id"; + + private $form; + private $boundModel = null; + 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 The form to use with this Builder + * @param Array 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) { + $form = new \Zend_Form(); + } + + $this->form = $form; + if (isset($options["CSRFProtection"])) { + $this->disableCSRF = !$options["CSRFProtection"]; + } + if (isset($options["model"])) { + $this->boundModel = &$options["model"]; + } + } + + public function setZendForm(\Zend_Form $form) + { + $this->form = $form; + } + + public function getForm() + { + if (!$this->disableCSRF) { + $this->addCSRFFieldToForm(); + } + if (!$this->form) { + return new \Zend_Form(); + } + return $this->form; + } + + public function addElementsFromConfig(array $elements) + { + foreach ($elements as $key => $values) { + $this->addElement($values[0], $key, $values[1]); + } + } + + public static function fromArray(array $elements, $options = array()) + { + $builder = new Builder(null, $options); + $builder->addElementsFromConfig($elements); + return $builder; + } + + public function isValid(array $data = null) + { + if ($data === null) { + $data = $_POST; + } + return $this->hasValidToken() && $this->form->isValid($data); + } + + public function isSubmitted($btnName = 'submit') + { + $btn = $this->getElement($btnName); + if (!$btn || !isset($_POST[$btnName])) { + return false; + } + return $_POST[$btnName] === $btn->getLabel(); + } + + public function render() + { + return $this->getForm()->render(); + } + + public function __toString() + { + return $this->getForm()->__toString(); + } + + public function enableCSRF() + { + $this->disableCSRF = false; + } + + public function disableCSRF() + { + $this->disableCSRF = true; + $this->form->removeElement(self::CSRF_ID); + $this->form->removeElement(self::CSRF_ID."_seed"); + } + + 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')); + + } + + public function bindToModel(&$model) + { + $this->boundModel = &$model; + } + + public function repopulate() + { + if (!empty($_POST)) { + $this->populate($_POST); + } + } + + 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(); + + } + + private function populateFromObject($data) + { + 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()); + } + } + } + } + + public function updateModel() + { + if (is_array($this->boundModel)) { + $this->updateArrayModel(); + } elseif (is_object($this->boundModel)) { + $this->updateObjectModel(); + } + } + + private function updateObjectModel() + { + 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()); + } + + } + } + } + + private function updateArrayModel() + { + foreach ($this->form->getElements() as $name => $element) { + if (isset($this->boundModel[$name])) { + $this->boundModel[$name] = $element->getValue(); + } + } + } + + public function syncWithModel() + { + $this->populate($this->boundModel, true); + } + + 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); + } +} diff --git a/test/php/library/Icinga/Form/BuilderTest.php b/test/php/library/Icinga/Form/BuilderTest.php new file mode 100644 index 000000000..8cae3062b --- /dev/null +++ b/test/php/library/Icinga/Form/BuilderTest.php @@ -0,0 +1,183 @@ + 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(); + $builder = new Builder(null, array("CSRFProtection" => false)); + $builder->setView($view); + $myModel = array( + "username" => "", + "password" => "" + ); + $builder->bindToModel($myModel); + $builder->addElement("text", "username"); + $builder->addElement("password", "password"); + // test sync from form to model + $builder->populate( + array( + "username" => "User input", + "password" => "Secret$123" + ) + ); + $this->assertEquals("User input", $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 = (object) array( + "username" => "", + "password" => "" + ); + $builder->bindToModel($myModel); + $builder->addElement("text", "username"); + $builder->addElement("password", "password"); + // test sync from form to model + $builder->populate( + (object) array( + "username" => "User input", + "password" => "Secret$123" + ) + ); + $this->assertEquals("User input", $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()); + } +} From 8d1038e6221ab36ff9f06a1582e5cc3f9bf20534 Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Tue, 25 Jun 2013 09:43:55 +0200 Subject: [PATCH 02/10] Refactor and test \Icinga\Web\Form Fix inspection issues, added some other code for testing to have more coverage, fix test for QLink view helper. refs #4302 refs #4341 --- library/Icinga/Form/Builder.php | 145 +++++++++++++++--- .../application/views/helpers/QlinkTest.php | 30 ++-- test/php/library/Icinga/Form/BuilderTest.php | 57 ++++++- 3 files changed, 187 insertions(+), 45 deletions(-) diff --git a/library/Icinga/Form/Builder.php b/library/Icinga/Form/Builder.php index 4526f7624..cc2b08591 100644 --- a/library/Icinga/Form/Builder.php +++ b/library/Icinga/Form/Builder.php @@ -5,28 +5,43 @@ 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() -* -**/ + * 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 The form to use with this Builder - * @param Array an optional array of Options: + * @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 @@ -35,23 +50,37 @@ class Builder public function __construct(\Zend_Form $form = null, array $options = array()) { if ($form === null) { + $myModel = array( + "username" => "", + "password" => "" + ); + $form = new \Zend_Form(); } - $this->form = $form; + $this->setZendForm($form); + if (isset($options["CSRFProtection"])) { $this->disableCSRF = !$options["CSRFProtection"]; } if (isset($options["model"])) { - $this->boundModel = &$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) { @@ -62,7 +91,11 @@ class Builder } return $this->form; } - + + /** + * Add elements to form + * @param array $elements + */ public function addElementsFromConfig(array $elements) { foreach ($elements as $key => $values) { @@ -70,6 +103,12 @@ class Builder } } + /** + * 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); @@ -77,6 +116,12 @@ class Builder return $builder; } + /** + * Test that the form is valid + * + * @param array $data + * @return bool + */ public function isValid(array $data = null) { if ($data === null) { @@ -85,6 +130,11 @@ class Builder 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); @@ -94,6 +144,10 @@ class Builder return $_POST[$btnName] === $btn->getLabel(); } + /** + * Render the form + * @return string + */ public function render() { return $this->getForm()->render(); @@ -103,12 +157,18 @@ class Builder { return $this->getForm()->__toString(); } - + + /** + * Enable CSRF token field + */ public function enableCSRF() { $this->disableCSRF = false; } + /** + * Disable CSRF token field + */ public function disableCSRF() { $this->disableCSRF = true; @@ -116,6 +176,9 @@ class Builder $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)) { @@ -135,11 +198,18 @@ class Builder } + /** + * Bind model to a form + * @param $model + */ public function bindToModel(&$model) { $this->boundModel = &$model; } + /** + * Repopulate + */ public function repopulate() { if (!empty($_POST)) { @@ -147,6 +217,12 @@ class Builder } } + /** + * Populate form + * @param $data + * @param bool $ignoreModel + * @throws \InvalidArgumentException + */ public function populate($data, $ignoreModel = false) { if (is_array($data)) { @@ -154,7 +230,7 @@ class Builder } elseif (is_object($data)) { $this->populateFromObject($data); } else { - throw new InvalidArgumentException("Builder::populate() expects and object or array, $data given"); + throw new \InvalidArgumentException("Builder::populate() expects and object or array, $data given"); } if ($this->boundModel === null || $ignoreModel) { return; @@ -163,8 +239,14 @@ class Builder } + /** + * 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); @@ -178,6 +260,9 @@ class Builder } } + /** + * Update model instance + */ public function updateModel() { if (is_array($this->boundModel)) { @@ -187,8 +272,13 @@ class Builder } } + /** + * 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(); @@ -202,8 +292,13 @@ class Builder } } + /** + * 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(); @@ -211,11 +306,21 @@ class Builder } } + /** + * 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)) { @@ -235,7 +340,7 @@ class Builder * @param int $maxAge Max allowed token age * @param string $sessionId A specific session id (useful for tests?) * - * return bool + * @return bool */ public function hasValidToken($maxAge = 600, $sessionId = null) { @@ -265,7 +370,7 @@ class Builder * @param int $maxAge Max allowed token age * @param string $sessionId A specific session id (useful for tests?) * - * return array + * @return array */ public function getSeedTokenPair($maxAge = 600, $sessionId = null) { diff --git a/test/php/application/views/helpers/QlinkTest.php b/test/php/application/views/helpers/QlinkTest.php index ad4c5e3be..7e8030ee8 100755 --- a/test/php/application/views/helpers/QlinkTest.php +++ b/test/php/application/views/helpers/QlinkTest.php @@ -1,19 +1,8 @@ view = $this; - $this->basename = $basename; - } - - public function baseUrl($url) { - return $this->basename.$url; - } - }; -} +require_once('Zend/View/Helper/Abstract.php'); +require_once('Zend/View.php'); require('../../application/views/helpers/Qlink.php'); @@ -30,30 +19,37 @@ class Zend_View_Helper_QlinkTest extends \PHPUnit_Framework_TestCase public function testURLPathParameter() { + $view = new Zend_View(); + $helper = new Zend_View_Helper_Qlink(); - $pathTpl = "path/%s/to/%s"; + $helper->setView($view); + $pathTpl = "/path/%s/to/%s"; $this->assertEquals( - "path/param1/to/param2", + "/path/param1/to/param2", $helper->getFormattedURL($pathTpl,array('param1','param2')) ); } public function testUrlGETParameter() { + $view = new Zend_View(); $helper = new Zend_View_Helper_Qlink(); + $helper->setView($view); $pathTpl = 'path'; $this->assertEquals( - 'path?param1=value1&param2=value2', + '/path?param1=value1&param2=value2', $helper->getFormattedURL($pathTpl,array('param1'=>'value1','param2'=>'value2')) ); } public function testMixedParameters() { + $view = new Zend_View(); $helper = new Zend_View_Helper_Qlink(); + $helper->setView($view); $pathTpl = 'path/%s/to/%s'; $this->assertEquals( - 'path/path1/to/path2?param1=value1&param2=value2', + '/path/path1/to/path2?param1=value1&param2=value2', $helper->getFormattedURL($pathTpl,array( 'path1','path2', 'param1'=>'value1', diff --git a/test/php/library/Icinga/Form/BuilderTest.php b/test/php/library/Icinga/Form/BuilderTest.php index 8cae3062b..ede5919fc 100644 --- a/test/php/library/Icinga/Form/BuilderTest.php +++ b/test/php/library/Icinga/Form/BuilderTest.php @@ -8,6 +8,23 @@ 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 { /** @@ -118,13 +135,23 @@ class BuilderTest extends \PHPUnit_Framework_TestCase public function testModelBindingWithArray() { $view = new \Zend_View(); - $builder = new Builder(null, array("CSRFProtection" => false)); - $builder->setView($view); + $myModel = array( "username" => "", "password" => "" ); - $builder->bindToModel($myModel); + + $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 @@ -155,22 +182,26 @@ class BuilderTest extends \PHPUnit_Framework_TestCase $view = new \Zend_View(); $builder = new Builder(null, array("CSRFProtection" => false)); $builder->setView($view); - $myModel = (object) array( - "username" => "", - "password" => "" - ); + + + + $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", - "password" => "Secret$123" + "password" => "Secret$123", + "test" => 'test334' ) ); $this->assertEquals("User input", $myModel->username); $this->assertEquals("Secret$123", $myModel->password); + $this->assertEquals("test334", $myModel->getTest()); // test sync from model to form $myModel->username = "Another user"; @@ -180,4 +211,14 @@ class BuilderTest extends \PHPUnit_Framework_TestCase $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(); + } } From 0f8648dcb1a3cc27f7fcc6a060b4cc285dc53e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?= Date: Thu, 20 Jun 2013 13:47:51 +0200 Subject: [PATCH 03/10] Add SystemPermissionException This exception should be fired when the OS restricts the web user from executing certain actions. Also the template for errors has been modified so it displays the action and the target that was prevented. refs #4092 --- application/controllers/ErrorController.php | 3 +-- application/views/scripts/error/error.phtml | 11 ++++++++-- .../Exception/SystemPermissionException.php | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 library/Icinga/Exception/SystemPermissionException.php diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php index efcc20e9b..c523bb77f 100755 --- a/application/controllers/ErrorController.php +++ b/application/controllers/ErrorController.php @@ -34,7 +34,6 @@ class ErrorController extends ActionController $this->view->message = 'Application error'; break; } - // conditionally display exceptions if ($this->getInvokeArg('displayExceptions') == true) { $this->view->exception = $errors->exception; @@ -44,4 +43,4 @@ class ErrorController extends ActionController } } -// @codingStandardsIgnoreEnd \ No newline at end of file +// @codingStandardsIgnoreEnd diff --git a/application/views/scripts/error/error.phtml b/application/views/scripts/error/error.phtml index 9ae6ecd1f..b5cfcddcb 100755 --- a/application/views/scripts/error/error.phtml +++ b/application/views/scripts/error/error.phtml @@ -9,8 +9,15 @@

Exception information:

-

- Message: exception->getMessage() ?> +

+ Message: exception->getMessage() ?> + exception->action)): ?> +
Action: exception->action; ?> + + exception->action)): ?> +
Target: exception->target; ?> + +

Stack trace:

diff --git a/library/Icinga/Exception/SystemPermissionException.php b/library/Icinga/Exception/SystemPermissionException.php new file mode 100644 index 000000000..02849ec34 --- /dev/null +++ b/library/Icinga/Exception/SystemPermissionException.php @@ -0,0 +1,22 @@ +action = $action; + $this->target = $target; + } +} From 81e27689bb79c0901975bb24bdfab9eb6605c6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?= Date: Thu, 20 Jun 2013 14:02:58 +0200 Subject: [PATCH 04/10] Add rule for 'body' container and QLink property 'target' QLinks can now define the target for their link. Additionally, the targte 'body' is now always the tag. This allows the modulemanager to reload the whole page (with the navigation bar). refs #4092 --- .../layouts/scripts/just-the-body.phtml | 8 --- application/layouts/scripts/layout.phtml | 4 +- .../layouts/scripts/parts/navigation.phtml | 3 +- application/views/helpers/Qlink.php | 5 +- public/js/icinga/modules/mainDetail.js | 71 ++++++++++--------- public/js/icinga/util/async.js | 8 +-- 6 files changed, 49 insertions(+), 50 deletions(-) diff --git a/application/layouts/scripts/just-the-body.phtml b/application/layouts/scripts/just-the-body.phtml index e243e63ed..ee29c44e6 100755 --- a/application/layouts/scripts/just-the-body.phtml +++ b/application/layouts/scripts/just-the-body.phtml @@ -12,14 +12,6 @@
-
- - - - - - -
diff --git a/application/layouts/scripts/layout.phtml b/application/layouts/scripts/layout.phtml index cfe89626c..d70627d1b 100755 --- a/application/layouts/scripts/layout.phtml +++ b/application/layouts/scripts/layout.phtml @@ -21,12 +21,12 @@ ICINGA_DEBUG = true; - + - + render('parts/topbar.phtml') ?>
diff --git a/application/layouts/scripts/parts/navigation.phtml b/application/layouts/scripts/parts/navigation.phtml index 1184d1830..e7de8f369 100755 --- a/application/layouts/scripts/parts/navigation.phtml +++ b/application/layouts/scripts/parts/navigation.phtml @@ -5,7 +5,8 @@ $item = $this->navigation->listAll("menu"); ?> -auth()->isAuthenticated()): ?> +auth()->isAuthenticated()): ?> +