summaryrefslogtreecommitdiffstats
path: root/vendor/gipfl/icingaweb2/src/CompatController.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gipfl/icingaweb2/src/CompatController.php')
-rw-r--r--vendor/gipfl/icingaweb2/src/CompatController.php581
1 files changed, 581 insertions, 0 deletions
diff --git a/vendor/gipfl/icingaweb2/src/CompatController.php b/vendor/gipfl/icingaweb2/src/CompatController.php
new file mode 100644
index 0000000..952b4b5
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/CompatController.php
@@ -0,0 +1,581 @@
+<?php
+
+namespace gipfl\IcingaWeb2;
+
+use gipfl\IcingaWeb2\Controller\Extension\AutoRefreshHelper;
+use gipfl\IcingaWeb2\Controller\Extension\ConfigHelper;
+use gipfl\Translation\StaticTranslator;
+use gipfl\Translation\TranslationHelper;
+use gipfl\IcingaWeb2\Controller\Extension\ControlsAndContentHelper;
+use gipfl\IcingaWeb2\Widget\ControlsAndContent;
+use gipfl\IcingaWeb2\Zf1\SimpleViewRenderer;
+use GuzzleHttp\Psr7\ServerRequest;
+use Icinga\Application\Benchmark;
+use Icinga\Application\Icinga;
+use Icinga\Application\Modules\Manager;
+use Icinga\Application\Modules\Module;
+use Icinga\Authentication\Auth;
+use Icinga\Exception\ProgrammingError;
+use Icinga\File\Pdf;
+use Icinga\Security\SecurityException;
+use Icinga\User;
+use Icinga\Web\Notification;
+use Icinga\Web\Session;
+use Icinga\Web\UrlParams;
+use Icinga\Web\Url as WebUrl;
+use Icinga\Web\Window;
+use InvalidArgumentException;
+use Psr\Http\Message\ServerRequestInterface;
+use RuntimeException;
+use Zend_Controller_Action;
+use Zend_Controller_Action_HelperBroker as ZfHelperBroker;
+use Zend_Controller_Request_Abstract as ZfRequest;
+use Zend_Controller_Response_Abstract as ZfResponse;
+
+/**
+ * Class CompatController
+ * @method \Icinga\Web\Request getRequest() {
+ * {@inheritdoc}
+ * @return \Icinga\Web\Request
+ * }
+ *
+ * @method \Icinga\Web\Response getResponse() {
+ * {@inheritdoc}
+ * @return \Icinga\Web\Response
+ * }
+ */
+class CompatController extends Zend_Controller_Action implements ControlsAndContent
+{
+ use AutoRefreshHelper;
+ use ControlsAndContentHelper;
+ use ConfigHelper;
+ use TranslationHelper;
+
+ /** @var bool Whether the controller requires the user to be authenticated */
+ protected $requiresAuthentication = true;
+
+ protected $applicationName = 'Icinga Web';
+
+ /** @var string The current module's name */
+ private $moduleName;
+
+ private $module;
+
+ private $window;
+
+ // https://github.com/joshbuchea/HEAD
+
+ /** @var SimpleViewRenderer */
+ protected $viewRenderer;
+
+ /** @var bool */
+ private $reloadCss = false;
+
+ /** @var bool */
+ private $rerenderLayout = false;
+
+ /** @var string */
+ private $xhrLayout = 'inline';
+
+ /** @var \Zend_Layout */
+ private $layout;
+
+ /** @var string The inner layout (inside the body) to use */
+ private $innerLayout = 'body';
+
+ /**
+ * Authentication manager
+ *
+ * @var Auth|null
+ */
+ private $auth;
+
+ /** @var UrlParams */
+ protected $params;
+
+ /**
+ * The constructor starts benchmarking, loads the configuration and sets
+ * other useful controller properties
+ *
+ * @param ZfRequest $request
+ * @param ZfResponse $response
+ * @param array $invokeArgs Any additional invocation arguments
+ * @throws SecurityException
+ */
+ public function __construct(
+ ZfRequest $request,
+ ZfResponse $response,
+ array $invokeArgs = array()
+ ) {
+ /** @var \Icinga\Web\Request $request */
+ /** @var \Icinga\Web\Response $response */
+ $this->setRequest($request)
+ ->setResponse($response)
+ ->_setInvokeArgs($invokeArgs);
+
+ $this->prepareViewRenderer();
+ $this->_helper = new ZfHelperBroker($this);
+
+ $this->handlerBrowserWindows();
+ $this->initializeTranslator();
+ $this->initializeLayout();
+
+ $this->view->compact = $request->getParam('view') === 'compact';
+ $url = $this->url();
+ $this->params = $url->getParams();
+
+ if ($url->shift('showCompact')) {
+ $this->view->compact = true;
+ }
+
+ $this->checkPermissionBasics();
+ Benchmark::measure('Ready to initialize the controller');
+ $this->prepareInit();
+ $this->init();
+ }
+
+ protected function initializeLayout()
+ {
+ $url = $this->url();
+ $layout = $this->layout = $this->_helper->layout();
+ $layout->isIframe = $url->shift('isIframe');
+ $layout->showFullscreen = $url->shift('showFullscreen');
+ $layout->moduleName = $this->getModuleName();
+ if ($this->rerenderLayout = $url->shift('renderLayout')) {
+ $this->xhrLayout = $this->innerLayout;
+ }
+ if ($url->shift('_disableLayout')) {
+ $this->layout->disableLayout();
+ }
+ }
+
+ /**
+ * Prepare controller initialization
+ *
+ * As it should not be required for controllers to call the parent's init() method,
+ * base controllers should use prepareInit() in order to prepare the controller
+ * initialization.
+ *
+ * @see \Zend_Controller_Action::init() For the controller initialization method.
+ */
+ protected function prepareInit()
+ {
+ }
+
+ /**
+ * Return the current module's name
+ *
+ * @return string
+ */
+ public function getModuleName()
+ {
+ if ($this->moduleName === null) {
+ $this->moduleName = $this->getRequest()->getModuleName();
+ }
+
+ return $this->moduleName;
+ }
+
+ protected function setModuleName($name)
+ {
+ $this->moduleName = $name;
+
+ return $this;
+ }
+
+ /**
+ * Return this controller's module
+ *
+ * @return Module
+ * @codingStandardsIgnoreStart
+ */
+ public function Module()
+ {
+ // @codingStandardsIgnoreEnd
+ if ($this->module === null) {
+ try {
+ $this->module = Icinga::app()->getModuleManager()->getModule($this->getModuleName());
+ } catch (ProgrammingError $e) {
+ throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ return $this->module;
+ }
+
+ /**
+ * @return Window
+ * @codingStandardsIgnoreStart
+ */
+ public function Window()
+ {
+ // @codingStandardsIgnoreEnd
+ if ($this->window === null) {
+ $this->window = new Window(
+ $this->getRequestHeader('X-Icinga-WindowId', Window::UNDEFINED)
+ );
+ }
+ return $this->window;
+ }
+
+ protected function handlerBrowserWindows()
+ {
+ if ($this->isXhr()) {
+ $id = $this->getRequestHeader('X-Icinga-WindowId', Window::UNDEFINED);
+
+ if ($id === Window::UNDEFINED) {
+ $this->window = new Window($id);
+ $this->_response->setHeader('X-Icinga-WindowId', Window::generateId());
+ }
+ }
+ }
+
+ /**
+ * @return ServerRequestInterface
+ */
+ protected function getServerRequest()
+ {
+ return ServerRequest::fromGlobals();
+ }
+
+ protected function getRequestHeader($key, $default = null)
+ {
+ try {
+ $value = $this->getRequest()->getHeader($key);
+ } catch (\Zend_Controller_Request_Exception $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+
+ if ($value === null) {
+ return $default;
+ } else {
+ return $value;
+ }
+ }
+
+ /**
+ * @throws SecurityException
+ */
+ protected function checkPermissionBasics()
+ {
+ $request = $this->getRequest();
+ // $auth->authenticate($request, $response, $this->requiresLogin());
+ if ($this->requiresLogin()) {
+ if (! $request->isXmlHttpRequest() && $request->isApiRequest()) {
+ Auth::getInstance()->challengeHttp();
+ }
+ $this->redirectToLogin(Url::fromRequest());
+ }
+ if (($this->Auth()->isAuthenticated() || $this->requiresLogin())
+ && $this->getFrontController()->getDefaultModule() !== $this->getModuleName()) {
+ $this->assertPermission(Manager::MODULE_PERMISSION_NS . $this->getModuleName());
+ }
+ }
+
+ protected function initializeTranslator()
+ {
+ $moduleName = $this->getModuleName();
+ $domain = $moduleName !== 'default' ? $moduleName : 'icinga';
+ $this->view->translationDomain = $domain;
+ StaticTranslator::set(new Translator($domain));
+ }
+
+ public function init()
+ {
+ // Hint: we intentionally do not call our parent's init() method
+ }
+
+ /**
+ * Get the authentication manager
+ *
+ * @return Auth
+ * @codingStandardsIgnoreStart
+ */
+ public function Auth()
+ {
+ // @codingStandardsIgnoreEnd
+ if ($this->auth === null) {
+ $this->auth = Auth::getInstance();
+ }
+ return $this->auth;
+ }
+
+ /**
+ * Whether the current user has the given permission
+ *
+ * @param string $permission Name of the permission
+ *
+ * @return bool
+ */
+ public function hasPermission($permission)
+ {
+ return $this->Auth()->hasPermission($permission);
+ }
+
+ /**
+ * Assert that the current user has the given permission
+ *
+ * @param string $permission Name of the permission
+ *
+ * @throws SecurityException If the current user lacks the given permission
+ */
+ public function assertPermission($permission)
+ {
+ if (! $this->Auth()->hasPermission($permission)) {
+ throw new SecurityException('No permission for %s', $permission);
+ }
+ }
+
+ /**
+ * Return restriction information for an eventually authenticated user
+ *
+ * @param string $name Restriction name
+ *
+ * @return array
+ */
+ public function getRestrictions($name)
+ {
+ return $this->Auth()->getRestrictions($name);
+ }
+
+ /**
+ * Check whether the controller requires a login. That is when the controller requires authentication and the
+ * user is currently not authenticated
+ *
+ * @return bool
+ */
+ protected function requiresLogin()
+ {
+ if (! $this->requiresAuthentication) {
+ return false;
+ }
+
+ return ! $this->Auth()->isAuthenticated();
+ }
+
+ public function prepareViewRenderer()
+ {
+ $this->viewRenderer = new SimpleViewRenderer();
+ $this->viewRenderer->replaceZendViewRenderer();
+ $this->view = $this->viewRenderer->view;
+ }
+
+ /**
+ * @return SimpleViewRenderer
+ */
+ public function getViewRenderer()
+ {
+ return $this->viewRenderer;
+ }
+
+ protected function redirectXhr($url)
+ {
+ if (! $url instanceof WebUrl) {
+ $url = Url::fromPath($url);
+ }
+
+ if ($this->rerenderLayout) {
+ $this->getResponse()->setHeader('X-Icinga-Rerender-Layout', 'yes');
+ }
+ if ($this->reloadCss) {
+ $this->getResponse()->setHeader('X-Icinga-Reload-Css', 'now');
+ }
+
+ $this->shutdownSession();
+
+ $this->getResponse()
+ ->setHeader('X-Icinga-Redirect', rawurlencode($url->getAbsoluteUrl()))
+ ->sendHeaders();
+
+ exit;
+ }
+
+ /**
+ * Detect whether the current request requires changes in the layout and apply them before rendering
+ *
+ * @see Zend_Controller_Action::postDispatch()
+ */
+ public function postDispatch()
+ {
+ Benchmark::measure('Action::postDispatch()');
+
+ $layout = $this->layout;
+ $req = $this->getRequest();
+ $layout->innerLayout = $this->innerLayout;
+
+ /** @var User $user */
+ if ($user = $req->getUser()) {
+ if ((bool) $user->getPreferences()->getValue('icingaweb', 'show_benchmark', false)) {
+ if ($layout->isEnabled()) {
+ $layout->benchmark = $this->renderBenchmark();
+ }
+ }
+
+ if (! (bool) $user->getPreferences()->getValue('icingaweb', 'auto_refresh', true)) {
+ $this->disableAutoRefresh();
+ }
+ }
+
+ if ($req->getParam('format') === 'pdf') {
+ $this->shutdownSession();
+ $this->sendAsPdf();
+ return;
+ }
+
+ if ($this->isXhr()) {
+ $this->postDispatchXhr();
+ }
+
+ $this->shutdownSession();
+ }
+
+ public function postDispatchXhr()
+ {
+ $this->layout->setLayout($this->xhrLayout);
+ $resp = $this->getResponse();
+
+ $notifications = Notification::getInstance();
+ if ($notifications->hasMessages()) {
+ $notificationList = array();
+ foreach ($notifications->popMessages() as $m) {
+ $notificationList[] = rawurlencode($m->type . ' ' . $m->message);
+ }
+ $resp->setHeader('X-Icinga-Notification', implode('&', $notificationList), true);
+ }
+
+ if ($this->reloadCss) {
+ $resp->setHeader('X-Icinga-CssReload', 'now', true);
+ }
+
+ if ($this->title) {
+ if (preg_match('~[\r\n]~', $this->title)) {
+ // TODO: Innocent exception and error log for hack attempts
+ throw new InvalidArgumentException('No newlines allowed in page title');
+ }
+ $resp->setHeader(
+ 'X-Icinga-Title',
+ // TODO: Config
+ rawurlencode($this->title . ' :: ' . $this->applicationName),
+ true
+ );
+ } else {
+ // TODO: config
+ $resp->setHeader('X-Icinga-Title', rawurlencode($this->applicationName), true);
+ }
+
+ if ($this->rerenderLayout) {
+ $this->getResponse()->setHeader('X-Icinga-Container', 'layout', true);
+ }
+
+ if (isset($this->autorefreshInterval)) {
+ $resp->setHeader('X-Icinga-Refresh', $this->autorefreshInterval, true);
+ }
+
+ if ($name = $this->getModuleName()) {
+ $this->getResponse()->setHeader('X-Icinga-Module', $name, true);
+ }
+ }
+
+ /**
+ * Redirect to login
+ *
+ * XHR will always redirect to __SELF__ if an URL to redirect to after successful login is set. __SELF__ instructs
+ * JavaScript to redirect to the current window's URL if it's an auto-refresh request or to redirect to the URL
+ * which required login if it's not an auto-refreshing one.
+ *
+ * XHR will respond with HTTP status code 403 Forbidden.
+ *
+ * @param Url|string $redirect URL to redirect to after successful login
+ */
+ protected function redirectToLogin($redirect = null)
+ {
+ $login = Url::fromPath('authentication/login');
+ if ($this->isXhr()) {
+ if ($redirect !== null) {
+ $login->setParam('redirect', '__SELF__');
+ }
+
+ $this->_response->setHttpResponseCode(403);
+ } elseif ($redirect !== null) {
+ if (! $redirect instanceof Url) {
+ $redirect = Url::fromPath($redirect);
+ }
+
+ if (($relativeUrl = $redirect->getRelativeUrl())) {
+ $login->setParam('redirect', $relativeUrl);
+ }
+ }
+
+ $this->rerenderLayout()->redirectNow($login);
+ }
+
+ protected function sendAsPdf()
+ {
+ $pdf = new Pdf();
+ $pdf->renderControllerAction($this);
+ }
+
+ /**
+ * Render the benchmark
+ *
+ * @return string Benchmark HTML
+ */
+ protected function renderBenchmark()
+ {
+ $this->viewRenderer->postDispatch();
+ Benchmark::measure('Response ready');
+ return Benchmark::renderToHtml()/*
+ . '<pre style="height: 16em; vertical-overflow: scroll">'
+ . print_r(get_included_files(), 1)
+ . '</pre>'*/;
+ }
+
+ public function isXhr()
+ {
+ return $this->getRequest()->isXmlHttpRequest();
+ }
+
+ protected function redirectHttp($url)
+ {
+ if (! $url instanceof Url) {
+ $url = Url::fromPath($url);
+ }
+ $this->shutdownSession();
+ $this->_helper->Redirector->gotoUrlAndExit($url->getRelativeUrl());
+ }
+
+ /**
+ * Redirect to a specific url, updating the browsers URL field
+ *
+ * @param Url|string $url The target to redirect to
+ **/
+ public function redirectNow($url)
+ {
+ if ($this->isXhr()) {
+ $this->redirectXhr($url);
+ } else {
+ $this->redirectHttp($url);
+ }
+ }
+
+ protected function shutdownSession()
+ {
+ $session = Session::getSession();
+ if ($session->hasChanged()) {
+ $session->write();
+ }
+ }
+
+ protected function rerenderLayout()
+ {
+ $this->rerenderLayout = true;
+ $this->xhrLayout = 'layout';
+ return $this;
+ }
+
+ protected function reloadCss()
+ {
+ $this->reloadCss = true;
+ return $this;
+ }
+}