View source
<?php
namespace Drupal\Tests\cas_attributes\Unit\Subscriber;
use Drupal\cas\CasPropertyBag;
use Drupal\cas\Event\CasPreLoginEvent;
use Drupal\cas\Event\CasPreRegisterEvent;
use Drupal\cas\Event\CasPostLoginEvent;
use Drupal\cas_attributes\Form\CasAttributesSettings;
use Drupal\cas_attributes\Subscriber\CasAttributesSubscriber;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Session\Session;
class CasAttributesSubscriberTest extends UnitTestCase {
protected $account;
protected $tokenService;
protected $propertyBag;
protected $requestStack;
protected $session;
protected $sessionData = [];
protected function setUp() {
parent::setUp();
$this->account = $this
->createMock('\\Drupal\\user\\UserInterface');
$this->tokenService = $this
->getMockBuilder('\\Drupal\\Core\\Utility\\Token')
->disableOriginalConstructor()
->getMock();
$this->propertyBag = $this
->getMockBuilder('\\Drupal\\cas\\CasPropertyBag')
->disableOriginalConstructor()
->getMock();
$this->requestStack = $this
->getMockBuilder('\\Symfony\\Component\\HttpFoundation\\RequestStack')
->disableOriginalConstructor()
->getMock();
$this->session = $this
->getMockBuilder('\\Symfony\\Component\\HttpFoundation\\Session\\Session')
->disableOriginalConstructor()
->getMock();
}
public function testMapFieldsOnLogin($mappings, $attributes, $overwrite, $empty) {
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'field.mappings' => $mappings,
'field.overwrite' => $overwrite,
'field.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
],
]);
$this->propertyBag
->expects($this
->any())
->method('getAttributes')
->willReturn($attributes);
$this->tokenService
->expects($this
->any())
->method('replace')
->will($this
->returnCallback([
$this,
'tokenReplace',
]));
if ($empty || $overwrite) {
$this->account
->expects($this
->once())
->method('set')
->with('name', $attributes[$mappings['name']][0]);
}
else {
$this->account
->expects($this
->never())
->method('setUsername');
}
$event = new CasPreLoginEvent($this->account, $this->propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreLogin($event);
}
public function mapFieldsOnLogin() {
$params[] = [
[
'name' => 'usernameAttribute',
],
[
'usernameAttribute' => [
$this
->randomMachineName(8),
],
],
TRUE,
FALSE,
];
$params[] = [
[
'name' => 'usernameAttribute',
],
[
'usernameAttribute' => [
$this
->randomMachineName(8),
],
],
FALSE,
FALSE,
];
$params[] = [
[
'name' => 'usernameAttribute',
],
[
'usernameAttribute' => [
$this
->randomMachineName(8),
],
],
FALSE,
TRUE,
];
$params[] = [
[
'name' => 'usernameAttribute',
],
[
'usernameAttribute' => [
$this
->randomMachineName(8),
],
],
TRUE,
TRUE,
];
return $params;
}
public function tokenReplace($input, array $data) {
$supplied_attribute = preg_replace('/\\[|\\]/', '', $input);
if (isset($data['cas_attributes']) && is_array($data['cas_attributes'])) {
if (isset($data['cas_attributes'][$supplied_attribute])) {
return $data['cas_attributes'][$supplied_attribute][0];
}
}
return $input;
}
public function testDenyRegistrationOnNoRoleMatch() {
$roleMapping = [
[
'rid' => $this
->randomMachineName(8),
'method' => 'exact_any',
'attribute' => 'fruit',
'value' => 'apple',
'remove_without_match' => FALSE,
],
];
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
'role.deny_registration_no_match' => TRUE,
'role.mappings' => $roleMapping,
],
]);
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'orange',
]);
$preRegisterEvent = new CasPreRegisterEvent($propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreRegister($preRegisterEvent);
$this
->assertFalse($preRegisterEvent
->getAllowAutomaticRegistration());
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'apple',
]);
$preRegisterEvent = new CasPreRegisterEvent($propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreRegister($preRegisterEvent);
$this
->assertTrue($preRegisterEvent
->getAllowAutomaticRegistration());
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.deny_registration_no_match' => FALSE,
'role.role_mapping' => $roleMapping,
],
]);
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'orange',
]);
$preRegisterEvent = new CasPreRegisterEvent($propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreRegister($preRegisterEvent);
$this
->assertTrue($preRegisterEvent
->getAllowAutomaticRegistration());
}
public function testDenyLoginOnNoRoleMatch() {
$roleMapping = [
[
'rid' => $this
->randomMachineName(8),
'method' => 'exact_any',
'attribute' => 'fruit',
'value' => 'apple',
'remove_without_match' => FALSE,
],
];
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
'role.deny_login_no_match' => TRUE,
'role.mappings' => $roleMapping,
],
]);
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'orange',
]);
$preLoginEvent = new CasPreLoginEvent($this->account, $propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreLogin($preLoginEvent);
$this
->assertFalse($preLoginEvent
->getAllowLogin());
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'apple',
]);
$preLoginEvent = new CasPreLoginEvent($this->account, $propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreLogin($preLoginEvent);
$this
->assertTrue($preLoginEvent
->getAllowLogin());
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
'role.deny_login_no_match' => FALSE,
'role.mappings' => $roleMapping,
],
]);
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('fruit', [
'orange',
]);
$preLoginEvent = new CasPreLoginEvent($this->account, $propertyBag);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreLogin($preLoginEvent);
$this
->assertTrue($preLoginEvent
->getAllowLogin());
}
public function testRoleMappingComparisonMethodsOnRegistration($scenarioData) {
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
'role.mappings' => $scenarioData['mappings'],
],
]);
$this->propertyBag
->method('getAttributes')
->willReturn($scenarioData['attributes_user_has']);
$event = new CasPreRegisterEvent($this->propertyBag);
$event
->setPropertyValue('roles', $scenarioData['roles_before']);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$subscriber
->onPreRegister($event);
$this
->assertEquals($scenarioData['roles_after'], $event
->getPropertyValues()['roles']);
}
public function roleMappingComparisonMethodsDataProvider() {
$scenarios = [];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
'roleB',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
'roleB',
],
'attributes_user_has' => [
'attra' => [
'bananas',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
'roleB',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attra',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'banan',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
'roleB',
'roleC',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
],
'attrB' => [
'cucumbers',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
[
'rid' => 'roleC',
'method' => 'exact_single',
'attribute' => 'attrB',
'value' => 'cucumbers',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
'cucumbers',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleA',
'roleB',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
'cucumbers',
],
],
'mappings' => [
[
'rid' => 'roleB',
'method' => 'exact_any',
'attribute' => 'attrA',
'value' => 'bananas',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [
'roleA',
],
'roles_after' => [
'roleB',
],
'attributes_user_has' => [
'attrA' => [
'bananas',
],
'attrB' => [
'cucumbers',
],
],
'mappings' => [
[
'rid' => 'roleA',
'method' => 'exact_single',
'attribute' => 'attrA',
'value' => 'cherries',
'remove_without_match' => TRUE,
],
[
'rid' => 'roleB',
'method' => 'exact_single',
'attribute' => 'attrB',
'value' => 'cucumbers',
'remove_without_match' => FALSE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [],
'roles_after' => [
'student',
],
'attributes_user_has' => [
'groups' => [
'Linux User',
'First Year Student',
],
],
'mappings' => [
[
'rid' => 'student',
'method' => 'contains_any',
'attribute' => 'groups',
'value' => 'Student',
'remove_without_match' => TRUE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [],
'roles_after' => [
'student',
],
'attributes_user_has' => [
'groups' => [
'Linux User',
'First Year Student',
],
],
'mappings' => [
[
'rid' => 'student',
'method' => 'regex_any',
'attribute' => 'groups',
'value' => '/.+student$/i',
'remove_without_match' => TRUE,
],
],
],
];
$scenarios[] = [
[
'roles_before' => [],
'roles_after' => [
'undergrad',
],
'attributes_user_has' => [
'groups' => [
'Linux User',
'First Year Student',
],
],
'mappings' => [
[
'rid' => 'undergrad',
'method' => 'contains_any',
'attribute' => 'groups',
'value' => 'Graduate Student',
'negate' => TRUE,
'remove_without_match' => TRUE,
],
],
],
[
'roles_before' => [],
'roles_after' => [],
'attributes_user_has' => [
'groups' => [
'Linux User',
'Graduate Student',
],
],
'mappings' => [
[
'rid' => 'undergrad',
'method' => 'contains_any',
'attribute' => 'groups',
'value' => 'Graduate Student',
'negate' => TRUE,
'remove_without_match' => TRUE,
],
],
],
];
return $scenarios;
}
public function testRoleMappingOnLogin() {
$role_map = [
[
'rid' => 'bananarole',
'method' => 'exact_single',
'attribute' => 'fruit',
'value' => 'banana',
'remove_without_match' => FALSE,
],
[
'rid' => 'orangerole',
'method' => 'exact_single',
'attribute' => 'FRUIT',
'value' => 'orange',
'remove_without_match' => FALSE,
],
];
$config_factory = $this
->getConfigFactoryStub([
'cas_attributes.settings' => [
'role.sync_frequency' => CasAttributesSettings::SYNC_FREQUENCY_EVERY_LOGIN,
'role.mappings' => $role_map,
],
]);
$account = $this
->createMock('\\Drupal\\user\\UserInterface');
$account
->expects($this
->once())
->method('addRole')
->with('bananarole');
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttribute('FRUIT', [
'banana',
]);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$event = new CasPreLoginEvent($account, $propertyBag);
$subscriber
->onPreLogin($event);
}
public function testAllowedAttributesSettings($settings, $cas_attributes, $expected_attributes) {
$config_factory = $this
->getConfigFactoryStub($settings);
$request = $this
->getMockBuilder('\\Symfony\\Component\\HttpFoundation\\Request')
->disableOriginalConstructor()
->getMock();
$request
->expects($this
->any())
->method('getSession')
->willReturn($this->session);
$this->requestStack
->expects($this
->any())
->method('getCurrentRequest')
->willReturn($request);
$this->session
->expects($this
->any())
->method('set')
->will($this
->returnCallback([
$this,
'setSessionAttr',
]));
$this->session
->expects($this
->any())
->method('get')
->will($this
->returnCallback([
$this,
'getSessionAttr',
]));
$account = $this
->createMock('\\Drupal\\user\\UserInterface');
$propertyBag = new CasPropertyBag('test');
$propertyBag
->setAttributes($cas_attributes);
$subscriber = new CasAttributesSubscriber($config_factory, $this->tokenService, $this->requestStack);
$event = new CasPostLoginEvent($account, $propertyBag);
$subscriber
->onPostLogin($event);
$session = $this->requestStack
->getCurrentRequest()
->getSession();
$attributes = $session
->get('cas_attributes');
$this
->assertEquals($attributes, $expected_attributes);
}
public function allowedAttributesSettings() {
$scenarios = [
'Not allowed attributes are filtered out' => [
[
'cas_attributes.settings' => [
'sitewide_token_support' => TRUE,
'token_allowed_attributes' => [
'id',
'name',
'EMAIL',
],
],
],
[
'id' => [
'user_id',
],
'NAME' => [
'user_name',
],
'email' => [
'user@example.com',
],
'not_allowed' => [
'not_allowed',
],
'one_more_not_allowed' => [
'not_allowed',
],
],
[
'id' => [
'user_id',
],
'NAME' => [
'user_name',
],
'email' => [
'user@example.com',
],
],
],
'Allowed more attributes than existed' => [
[
'cas_attributes.settings' => [
'sitewide_token_support' => TRUE,
'token_allowed_attributes' => [
'id',
'name',
'email',
],
],
],
[
'id' => [
'user_id',
],
'name' => [
'user_name',
],
],
[
'id' => [
'user_id',
],
'name' => [
'user_name',
],
],
],
];
return $scenarios;
}
public function setSessionAttr($name, $value) {
$this->sessionData[$name] = $value;
}
public function getSessionAttr($name, $default = null) {
if (isset($this->sessionData[$name])) {
return $this->sessionData[$name];
}
return $default;
}
}