Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPENEUROPA-2502: Add param groups to validation path. #99

Merged
merged 9 commits into from
Dec 13, 2019
7 changes: 6 additions & 1 deletion oe_authentication.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ services:
class: \Drupal\oe_authentication\Event\EuLoginEventSubscriber
tags:
- { name: event_subscriber }
arguments: ['@config.factory', '@messenger']
arguments: ['@config.factory']
oe_authentication.messenger.event_subscriber:
class: \Drupal\oe_authentication\Event\MessengerEuLoginEventSubscriber
tags:
- { name: event_subscriber }
arguments: ['@messenger']
56 changes: 45 additions & 11 deletions src/CasProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ public static function convertCasAttributesToFieldValues(array $attributes): arr
* An array containing the parsed attributes.
*/
public static function processValidationResponseAttributes(string $source): array {
if (!CasProcessor::isValidResponse($source)) {
if (!static::isValidResponse($source)) {
throw new \InvalidArgumentException();
}
// Load cas attributes.
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = FALSE;
$dom->encoding = "utf-8";
$dom->encoding = 'utf-8';
@$dom->loadXML($source);
$success_elements = $dom->getElementsByTagName("authenticationSuccess");
$success_elements = $dom->getElementsByTagName('authenticationSuccess');

// There should only be one success element, grab it and extract username.
$success_element = $success_elements->item(0);
// Parse the attributes coming from Eu Login
// and add them to the default ones.
$eulogin_attributes = CasProcessor::parseAttributes($success_element);
$eulogin_attributes = static::parseAttributes($success_element);
return $eulogin_attributes;
}

Expand All @@ -72,26 +72,60 @@ public static function processValidationResponseAttributes(string $source): arra
*
* @param \DOMElement $node
* An XML element containing attributes.
* @param bool $toplevel
* Whether the method is called from out of the recursive loop.
*
* @return array
* An associative array of attributes.
* An array of attributes.
*/
private static function parseAttributes(\DOMElement $node): array {
protected static function parseAttributes(\DOMElement $node, bool $toplevel = TRUE): array {
// Check if we can return an associative array or if
// we must use numeric keys.
$associative = $toplevel || static::isAssociative($node);

$attributes = [];
// @var \DOMElement $child
foreach ($node->childNodes as $child) {
foreach ($node->childNodes as $key => $child) {
$name = $child->localName;
// If the child has sub-levels, recursively parse the attributes
// underneath.
if ($child->hasAttribute('number')) {
$value = CasProcessor::parseAttributes($child);
$value = static::parseAttributes($child, FALSE);
}
else {
$value = $child->nodeValue;
}
$attributes[$name] = $value;

if ($associative) {
$attributes[$name] = $value;
}
else {
$attributes[] = $value;
}

}
return $attributes;
}

/**
* Checks if the node children can be represented as an associative array.
*
* Array can be associative if it will get different names for all keys.
*
* @param \DOMElement $node
* The node element.
*
* @return bool
* Whether the node children should be mapped to an associated array.
*/
protected static function isAssociative(\DOMElement $node): bool {
$names = $counter = [];
foreach ($node->childNodes as $child) {
$names[$child->localName] = $counter[] = $child->localName;
}
return count($names) === count($counter);
}

/**
* Check whether the validation response is valid or not.
*
Expand All @@ -104,15 +138,15 @@ private static function parseAttributes(\DOMElement $node): array {
public static function isValidResponse(string $response) {
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = FALSE;
$dom->encoding = "utf-8";
$dom->encoding = 'utf-8';

// Suppress errors from this function, as we intend to allow other
// event subscribers to work on the data.
if (@$dom->loadXML($response) === FALSE) {
return FALSE;
}

$success_elements = $dom->getElementsByTagName("authenticationSuccess");
$success_elements = $dom->getElementsByTagName('authenticationSuccess');
return $success_elements->length !== 0;
}

Expand Down
8 changes: 2 additions & 6 deletions src/Event/EuLoginEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Drupal\cas\Event\CasPreValidateEvent;
use Drupal\cas\Service\CasHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Expand Down Expand Up @@ -45,12 +44,9 @@ class EuLoginEventSubscriber implements EventSubscriberInterface {
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The config factory.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(ConfigFactoryInterface $configFactory, MessengerInterface $messenger) {
public function __construct(ConfigFactoryInterface $configFactory) {
$this->configFactory = $configFactory;
$this->messenger = $messenger;
}

/**
Expand Down Expand Up @@ -111,7 +107,6 @@ public function processUserProperties(CasPreRegisterEvent $event): void {
$user_settings = $this->configFactory->get('user.settings');
if ($user_settings->get('register') === USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) {
$event->setPropertyValue('status', 0);
$this->messenger->addStatus($this->t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'));
}
}

Expand Down Expand Up @@ -145,6 +140,7 @@ public function alterValidationPath(CasPreValidateEvent $event): void {
'assuranceLevel' => $config->get('assurance_level'),
'ticketTypes' => $config->get('ticket_types'),
'userDetails' => 'true',
'groups' => '*',
];
$event->addParameters($params);
}
Expand Down
70 changes: 70 additions & 0 deletions src/Event/MessengerEuLoginEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_authentication\Event;

use Drupal\cas\Event\CasPreRegisterEvent;
use Drupal\cas\Service\CasHelper;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Event subscriber for CAS module events.
*
* The class subscribes to the events provided by the CAS module and shows
* messages accordingly.
*/
class MessengerEuLoginEventSubscriber implements EventSubscriberInterface {

use StringTranslationTrait;

/**
* The messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;

/**
* Constructs the MessengerEuLoginEventSubscriber.
*
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
*/
public function __construct(MessengerInterface $messenger) {
$this->messenger = $messenger;
}

/**
* Returns an array of event names this subscriber wants to listen to.
*
* @return array
* The event names to listen to.
*/
public static function getSubscribedEvents(): array {
$events = [];
$events[CasHelper::EVENT_PRE_REGISTER] = ['showUserMessage', -100];
return $events;
}

/**
* Show user message about its activation status.
*
* @param \Drupal\cas\Event\CasPreRegisterEvent $event
* The triggered event.
*/
public function showUserMessage(CasPreRegisterEvent $event): void {
$properties = $event->getPropertyValues();

if (!isset($properties['status'])) {
return;
}

if (!$properties['status']) {
$this->messenger->addStatus($this->t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'));
}
}

}