/** * Checks if a node's type requires a redirect. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The event to process. */ public function purlCheckNodeContext(GetResponseEvent $event, $eventName, EventDispatcherInterface $dispatcher_interface) { $route_options = $this->routeMatch->getRouteObject()->getOptions(); $isAdminRoute = array_key_exists('_admin_route', $route_options) && $route_options['_admin_route']; if (!$isAdminRoute && ($matched = $this->matchedModifiers->getMatched() && ($entity = $this->routeMatch->getParameter('node')))) { $node_type = $this->entityStorage->load($entity->bundle()); $purl_settings = $node_type->getThirdPartySettings('purl'); if (!isset($purl_settings['keep_context']) || !$purl_settings['keep_context']) { $url = \Drupal\Core\Url::fromRoute($this->routeMatch->getRouteName(), $this->routeMatch->getRawParameters()->all(), ['host' => Settings::get('purl_base_domain'), 'absolute' => TRUE]); try { $redirect_response = new TrustedRedirectResponse($url->toString()); $redirect_response->getCacheableMetadata()->setCacheMaxAge(0); $modifiers = $event->getRequest()->attributes->get('purl.matched_modifiers', []); $new_event = new ExitedContextEvent($event->getRequest(), $redirect_response, $this->routeMatch, $modifiers); $dispatcher_interface->dispatch(PurlEvents::EXITED_CONTEXT, $new_event); $event->setResponse($new_event->getResponse()); return; } catch (RedirectLoopException $e) { \Drupal::logger('redirect')->warning($e->getMessage()); $response = new Response(); $response->setStatusCode(503); $response->setContent('Service unavailable'); $event->setResponse($response); return; } } } }
/** * Test the forcedLogin redirect. * * @covers ::forceLogin * @covers ::__construct */ public function testForceLogin() { $request = $this->getMock('\\Symfony\\Component\\HttpFoundation\\Request'); $query = $this->getMock('\\Symfony\\Component\\HttpFoundation\\ParameterBag'); $request->query = $query; $this->requestStack->expects($this->once())->method('getCurrentRequest')->will($this->returnValue($request)); $parameters = array('returnto' => 'node/1', 'foo' => 'bar'); $query->expects($this->once())->method('all')->will($this->returnValue($parameters)); $this->casHelper->expects($this->once())->method('getServerLoginUrl')->with($this->equalTo($parameters))->will($this->returnValue('https://example.com')); $cacheableMetadata = new CacheableMetadata(); $cacheableMetadata->addCacheTags(array('config:cas.settings')); $expected_response = new TrustedRedirectResponse('https://example.com', 302); $expected_response->addCacheableDependency($cacheableMetadata); $force_login_controller = new ForceLoginController($this->casHelper, $this->requestStack); $response = $force_login_controller->forceLogin(); $this->assertEquals($expected_response, $response); }
/** * Handles a page request for our forced login route. */ public function forceLogin() { // TODO: What if CAS is not configured? need to handle that case. $query_params = $this->requestStack->getCurrentRequest()->query->all(); $cas_login_url = $this->casHelper->getServerLoginUrl($query_params); $this->casHelper->log("Cas forced login route, redirecting to: {$cas_login_url}"); return TrustedRedirectResponse::create($cas_login_url, 302); }
/** * @covers ::createFromRedirectResponse * @dataProvider providerCreateFromRedirectResponse */ public function testCreateFromRedirectResponse($redirect_response) { $trusted_redirect_response = TrustedRedirectResponse::createFromRedirectResponse($redirect_response); // The trusted redirect response is always a CacheableResponseInterface instance. $this->assertTrue($trusted_redirect_response instanceof CacheableResponseInterface); // But it is only actually cacheable (non-zero max-age) if the redirect // response passed to TrustedRedirectResponse::createFromRedirectResponse() // is itself cacheable. $expected_cacheability = $redirect_response instanceof CacheableResponseInterface ? $redirect_response->getCacheableMetadata() : (new CacheableMetadata())->setCacheMaxAge(0); $this->assertEquals($expected_cacheability, $trusted_redirect_response->getCacheableMetadata()); }
/** * Handles a page request for our forced login route. */ public function forceLogin() { // TODO: What if CAS is not configured? need to handle that case. $query_params = $this->requestStack->getCurrentRequest()->query->all(); $cas_login_url = $this->casHelper->getServerLoginUrl($query_params); $this->casHelper->log("Cas forced login route, redirecting to: {$cas_login_url}"); // This response is OK to cache, but since the redirect URL is dependent on // the configured server settings, we need to add some cache metadata tied // to the settings. $cacheable_metadata = new CacheableMetadata(); $cacheable_metadata->addCacheTags(array('config:cas.settings')); $response = TrustedRedirectResponse::create($cas_login_url, 302); $response->addCacheableDependency($cacheable_metadata); return $response; }
/** * @covers ::setTargetUrl */ public function testSetTargetUrlWithTrustedUrl() { $redirect_response = new TrustedRedirectResponse('/example'); $redirect_response->setTrustedTargetUrl('http://good-external-url.com/example'); $this->assertEquals('http://good-external-url.com/example', $redirect_response->getTargetUrl()); }
/** * Prior to set the response it check if we can redirect. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The event object. * @param \Drupal\Core\Url $url * The Url where we want to redirect. */ protected function setResponse(GetResponseEvent $event, Url $url) { $request = $event->getRequest(); $this->context->fromRequest($request); parse_str($request->getQueryString(), $query); $url->setOption('query', $query); $url->setAbsolute(TRUE); // We can only check access for routed URLs. if (!$url->isRouted() || $this->checker->canRedirect($request, $url->getRouteName())) { // Add the 'rendered' cache tag, so that we can invalidate all responses // when settings are changed. $response = new TrustedRedirectResponse($url->toString(), 301); $response->addCacheableDependency(CacheableMetadata::createFromRenderArray([])->addCacheTags(['rendered'])); $event->setResponse($response); } }
/** * Check if we should implement the CAS gateway feature. * * @param GetResponseEvent $event * The response event from the kernel. * * @return bool * TRUE if gateway mode was implemented, FALSE otherwise. */ private function handleGateway(GetResponseEvent $event) { // Only implement gateway feature for GET requests, to prevent users from // being redirected to CAS server for things like form submissions. if (!$this->requestStack->getCurrentRequest()->isMethod('GET')) { return FALSE; } $config = $this->configFactory->get('cas.settings'); $check_frequency = $config->get('gateway.check_frequency'); if ($check_frequency === CasHelper::CHECK_NEVER) { return FALSE; } // User can indicate specific paths to enable (or disable) gateway mode. $condition = $this->conditionManager->createInstance('request_path'); $condition->setConfiguration($config->get('gateway.paths')); if (!$this->conditionManager->execute($condition)) { return FALSE; } // If set to only implement gateway once per session, we use a session // variable to store the fact that we've already done the gateway check // so we don't keep doing it. if ($check_frequency === CasHelper::CHECK_ONCE) { // If the session var is already set, we know to back out. if (isset($_SESSION['cas_gateway_checked'])) { $this->casHelper->log("Gateway already checked, will not check again."); return FALSE; } $_SESSION['cas_gateway_checked'] = TRUE; } $cas_login_url = $this->casHelper->getServerLoginUrl(array('returnto' => $this->requestStack->getCurrentRequest()->getUri(), 'cas_temp_disable' => TRUE), TRUE); $this->casHelper->log("Gateway activated, redirecting to {$cas_login_url}"); $event->setResponse(TrustedRedirectResponse::create($cas_login_url)); return TRUE; }