cas-8.x-1.x-dev/tests/src/Functional/CasGatewayAuthSubscriberTest.php

tests/src/Functional/CasGatewayAuthSubscriberTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\cas\Functional;

use Drupal\Component\Utility\UrlHelper;
use Drupal\cas\Model\GatewayMethod;

/**
 * Tests the CAS gateway login subscriber.
 *
 * @group cas
 */
class CasGatewayAuthSubscriberTest extends CasBrowserTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'cas',
    'path',
    'filter',
    'node',
    'page_cache',
    'dynamic_page_cache',
  ];

  /**
   * Test that the gateway auth works as expected.
   */
  public function testGatewayPaths(): void {
    $admin = $this->drupalCreateUser(['administer account settings']);
    $this->drupalLogin($admin);

    // Create some dummy nodes so we have some content paths to work with.
    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
    $this->drupalCreateNode();
    $this->drupalCreateNode();

    // Configure CAS with server-side gateway auth enabled for both nodes.
    $edit = [
      'server[hostname]' => 'fakecasserver.localhost',
      'server[path]' => '/auth',
      'gateway[enabled]' => TRUE,
      'gateway[recheck_time]' => 720,
      'gateway[paths][pages]' => "/node/1\n/node/2",
      'gateway[method]' => GatewayMethod::ServerSide->value,
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');

    // Check that settings saved correctly.
    $config = $this->config('cas.settings');
    $this->assertEquals(TRUE, $config->get('gateway.enabled'));
    $this->assertEquals(720, $config->get('gateway.recheck_time'));
    $this->assertEquals(GatewayMethod::ServerSide->value, $config->get('gateway.method'));
    $this->assertEquals("/node/1\n/node/2", $config->get('gateway.paths')['pages']);

    $session = $this->getSession();

    // Ensure that after visiting a node once and redirected, we are not
    // redirected AGAIN after visiting another gateway enabled path again.
    // This is because we are set to only check once per X amount of time for
    // user session.
    // We disable redirects so the browser doesn't attempt to actually go
    // to the fake CAS server and so we can inspect the redirect.
    $this->drupalLogout();
    $this->disableRedirects();
    $this->prepareRequest();
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $this->assertEquals(302, $session->getStatusCode());
    $this->assertEquals($this->getExpectedRedirectUrl(1), $session->getResponseHeader('Location'));
    // A cookie should have been set indicating we've checked for gateway.
    $this->assertNotEmpty($this->getSession()->getCookie('cas_gateway_checked_ss'));
    // Visiting another page that has gateway enabled should NOT redirect there
    // because of the cookie that's set.
    // Revisit same page again first to flush the session var that gateway
    // subscriber uses to disable next request.
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $session->visit($this->buildUrl('node/2', ['absolute' => TRUE]));
    $this->assertEquals(200, $session->getStatusCode());
    $this->assertNotEmpty($this->getSession()->getCookie('cas_gateway_checked_ss'));

    // But if we clear cookies between requests, we should be redirected both
    // times.
    $session->reset();
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $this->assertEquals(302, $session->getStatusCode());
    $this->assertEquals($this->getExpectedRedirectUrl(1), $session->getResponseHeader('Location'));
    $this->assertNotEmpty($this->getSession()->getCookie('cas_gateway_checked_ss'));
    $session->reset();
    $session->visit($this->buildUrl('node/2', ['absolute' => TRUE]));
    $this->assertEquals(302, $session->getStatusCode());
    $this->assertEquals($this->getExpectedRedirectUrl(2), $session->getResponseHeader('Location'));

    // Now configure it so that it checks EVERY Request and confirm that it
    // works, even without resetting cookies.
    $session->reset();
    $this->drupalLogin($admin);
    $edit = [
      'gateway[recheck_time]' => "-1",
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');
    $this->drupalLogout();
    $this->disableRedirects();
    $this->prepareRequest();

    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $this->assertEquals(302, $session->getStatusCode());
    $this->assertEquals($this->getExpectedRedirectUrl(1), $session->getResponseHeader('Location'));
    $this->assertEmpty($this->getSession()->getCookie('cas_gateway_checked_ss'));

    // Revisit same page again first to flush the session var that gateway
    // subscriber uses to disable next request.
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $session->visit($this->buildUrl('node/2', ['absolute' => TRUE]));
    $this->assertEquals(302, $session->getStatusCode());
    $this->assertEquals($this->getExpectedRedirectUrl(2), $session->getResponseHeader('Location'));
    $this->assertEmpty($this->getSession()->getCookie('cas_gateway_checked_ss'));

    // Restrict the redirects to only the first node and not the second node,
    // confirm we aren't redirected at all for second node.
    $session->reset();
    $this->drupalLogin($admin);
    $edit = [
      'gateway[paths][pages]' => '/node/1',
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');
    $this->drupalLogout();
    $this->disableRedirects();
    $this->prepareRequest();
    $session->visit($this->buildUrl('node/2', ['absolute' => TRUE]));
    $this->assertEquals(200, $session->getStatusCode());

    // Disable gateway auth and verify it does NOT redirect the user when
    // visiting the configured path.
    $session->reset();
    $this->drupalLogin($admin);
    $edit = [
      'gateway[enabled]' => FALSE,
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');
    $this->drupalLogout();
    $this->disableRedirects();
    $this->prepareRequest();

    $session = $this->getSession();
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $this->assertEquals(200, $session->getStatusCode());

    // Test that client side redirect cannot be enabled when using the
    // "every page request" recheck option.
    $this->drupalLogin($admin);
    $edit = [
      'gateway[enabled]' => TRUE,
      'gateway[recheck_time]' => "-1",
      'gateway[method]' => GatewayMethod::ClientSide->value,
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');
    $this->assertSession()->pageTextContains('The "Every page request" recheck time is not compatible with the "Client-side" method');

    // Enable client side redirect and confirm that the user is not redirected
    // to CAS via server-side, but the page contains the JS library to redirect.
    // @todo test with a JS driver as well so we know the JS code works?
    $edit = [
      'gateway[enabled]' => TRUE,
      'gateway[recheck_time]' => 720,
      'gateway[method]' => GatewayMethod::ClientSide->value,
    ];
    $this->drupalGet('/admin/config/people/cas');
    $this->submitForm($edit, 'Save configuration');
    $this->drupalLogout();
    $this->disableRedirects();
    $this->prepareRequest();
    $session->visit($this->buildUrl('node/1', ['absolute' => TRUE]));
    $this->assertEquals(200, $session->getStatusCode());

    // Drupal settings should be populated with the redirect URL.
    $drupalSettings = $this->getDrupalSettings();
    $this->assertEquals($this->getExpectedRedirectUrl(1), $drupalSettings['cas']['gatewayRedirectUrl']);
    $this->assertEquals(720, $drupalSettings['cas']['recheckTime']);

    // The JS data should not be added on paths that aren't configured to have
    // gateway enabled.
    $session->visit($this->buildUrl('node/2', ['absolute' => TRUE]));
    $this->assertEquals(200, $session->getStatusCode());
    $this->assertEmpty($this->getDrupalSettings());

    // @todo Test that visiting page as a bot does NOT trigger a redirect.
    // We cannot do this at the moment because we can't spoof a user agent!
    // See https://www.drupal.org/node/2820515.
  }

  /**
   * Returns the expected redirect URL.
   *
   * @param int $nid
   *   The node ID.
   *
   * @return string
   *   The expected redirect URL.
   */
  protected function getExpectedRedirectUrl(int $nid): string {
    return 'https://fakecasserver.localhost/auth/login?' . UrlHelper::buildQuery([
      'gateway' => 'true',
      'service' => $this->buildServiceUrlWithParams([
        'destination' => "{$GLOBALS['base_path']}node/{$nid}",
        'from_gateway' => 1,
      ]),
    ]);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc