simple_ldap_user.test in Simple LDAP 7
Same filename and directory in other branches
Tests for Simple LDAP User module.
File
simple_ldap_user/simple_ldap_user.testView source
<?php
/**
* @file
* Tests for Simple LDAP User module.
*/
abstract class SimpleLdapUserTestCase extends SimpleLdapServerTestCase {
protected $drupalUser;
protected $ldapUser;
protected $userPassword;
/**
* Inherited parent::setUp().
*/
public function setUp() {
// Get the live simple_ldap_user configuration.
$basedn = simple_ldap_user_variable_get('simple_ldap_user_basedn');
$scope = simple_ldap_user_variable_get('simple_ldap_user_scope');
$objectclass = simple_ldap_user_variable_get('simple_ldap_user_objectclass');
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
$attribute_mail = simple_ldap_user_variable_get('simple_ldap_user_attribute_mail');
$attribute_pass = simple_ldap_user_variable_get('simple_ldap_user_attribute_pass');
$attribute_rdn = simple_ldap_user_variable_get('simple_ldap_user_attribute_rdn');
$attribute_map = simple_ldap_user_variable_get('simple_ldap_user_attribute_map');
$password_hash = simple_ldap_user_variable_get('simple_ldap_user_password_hash');
$filter = simple_ldap_user_variable_get('simple_ldap_user_filter');
$source = simple_ldap_user_variable_get('simple_ldap_user_source');
$sync = simple_ldap_user_variable_get('simple_ldap_user_sync');
$delete_ldap_user = simple_ldap_user_variable_get('simple_ldap_user_delete_from_ldap');
// Make sure the variables from settings.php are written to the database.
// Otherwise subsequent tests will not be able to read them. These are
// cleaned up in $this->tearDown().
variable_set('simple_ldap_user_attribute_map', $attribute_map);
// Create the simpletest sandbox.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
$modules = $modules[0];
}
parent::setUp($modules);
// Initialize an LDAP server object.
$server = SimpleLdapServer::singleton();
// Create a set of drupal-only users before enabling Simple LDAP User so
// that they are only present in Drupal.
for ($i = 0; $i < 5; $i++) {
$this->drupalUser[$i] = $this
->drupalCreateUser();
}
// Get a list of required attributes for the configured objectclass(es).
$must = array();
foreach ($objectclass as $o) {
foreach ($server->schema
->must($o, TRUE) as $m) {
if (!in_array($m, $must)) {
$must[] = strtolower($m);
}
}
}
// Add mapped fields to user entity.
foreach ($attribute_map as $attribute) {
// Clean up the attribute. We can't use simple_ldap_user_variable_get()
// yet because simple_ldap_user is not enabled yet. The module can't be
// enabled until after the Drupal users are initialized, or they would
// sync to LDAP, and invalidate the tests. Chicken and egg problem here.
$attribute['ldap'] = strtolower($attribute['ldap']);
if (!is_array($attribute['drupal'])) {
$attribute['drupal'] = array(
$attribute['drupal'],
);
}
// Skip one-to-many mappings.
if (count($attribute['drupal']) > 1) {
continue;
}
// Get the drupal name and type.
$drupal_attribute = reset($attribute['drupal']);
$type = substr($drupal_attribute, 0, 1);
// Create user fields.
if ($type == '#') {
$drupal_attribute = substr($drupal_attribute, 1);
$required = in_array($attribute['ldap'], $must);
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
$type = 'number_integer';
}
else {
$type = 'text';
}
field_create_field(array(
'field_name' => $drupal_attribute,
'type' => $type,
'cardinality' => 1,
));
field_create_instance(array(
'field_name' => $drupal_attribute,
'entity_type' => 'user',
'label' => $drupal_attribute,
'bundle' => 'user',
'required' => $required,
'settings' => array(
'user_register_form' => $required,
),
));
// Populate the field value of each of the test Drupal users.
foreach ($this->drupalUser as $drupal_user) {
if ($type == 'number_integer') {
$edit[$drupal_attribute]['und'][0]['value'] = $drupal_user->uid + 1000;
}
else {
$edit[$drupal_attribute]['und'][0]['value'] = $this
->randomName();
}
$drupal_user = user_save($drupal_user, $edit);
}
}
}
// Enable the Simple LDAP User module.
$modules = array(
'simple_ldap_user',
);
$success = module_enable($modules);
$this
->assertTrue($success, t('Enabled modules: %modules', array(
'%modules' => implode(', ', $modules),
)));
// Configure the sandboxed simple_ldap_user.
variable_set('simple_ldap_user_basedn', $basedn);
variable_set('simple_ldap_user_scope', $scope);
variable_set('simple_ldap_user_objectclass', $objectclass);
variable_set('simple_ldap_user_attribute_name', $attribute_name);
variable_set('simple_ldap_user_attribute_mail', $attribute_mail);
variable_set('simple_ldap_user_attribute_pass', $attribute_pass);
variable_set('simple_ldap_user_attribute_rdn', $attribute_rdn);
variable_set('simple_ldap_user_attribute_map', $attribute_map);
variable_set('simple_ldap_user_password_hash', $password_hash);
variable_set('simple_ldap_user_filter', $filter);
variable_set('simple_ldap_user_source', $source);
variable_set('simple_ldap_user_sync', $sync);
variable_set('simple_ldap_user_delete_from_ldap', $delete_ldap_user);
// Get the fully qualified attribute map.
$mapObject = SimpleLdapUserMap::singleton();
// Create a set of LDAP entries to use during testing.
for ($i = 0; $i < 5; $i++) {
// Create a new LDAP User object, and set the attributes.
$name = $this
->randomName();
$this->ldapUser[$i] = new SimpleLdapUser($name);
$this->ldapUser[$i]->{$attribute_mail} = $this
->randomName() . '@example.com';
foreach ($mapObject->map as $attribute) {
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
$this->ldapUser[$i]->{$attribute['ldap']} = 1000 + $i;
}
else {
$this->ldapUser[$i]->{$attribute['ldap']} = $this
->randomName();
}
}
// Set the DN.
if (empty($attribute_rdn)) {
$this->ldapUser[$i]->dn = $attribute_name . '=' . $name . ',' . $basedn;
}
else {
$this->ldapUser[$i]->dn = $attribute_rdn . '=' . $this->ldapUser[$i]->{$attribute_rdn}[0] . ',' . $basedn;
}
// Set the user's password.
$this->userPassword[$i] = $this
->randomName();
SimpleLdapUser::hash($this->userPassword[$i], $this->userPassword[$i]);
$this->ldapUser[$i]->{$attribute_pass} = $this->userPassword[$i];
// Save the entry to LDAP.
$this->ldapUser[$i]
->save();
// If no exception is thrown by save() then the save was successful, but
// show the DN to make the tester feel better.
$this
->assertTrue($this->ldapUser[$i]->exists, t(':dn was added to LDAP', array(
':dn' => $this->ldapUser[$i]->dn,
)));
// Verify that the LDAP user can bind.
$result = $server
->bind($this->ldapUser[$i]->dn, $this->userPassword[$i]);
$this
->assertTrue($result, t('Successful bind with :dn using password :pw', array(
':dn' => $this->ldapUser[$i]->dn,
':pw' => $this->userPassword[$i],
)));
}
}
/**
* Inherited parent::tearDown().
*/
protected function tearDown() {
// Get module configuration.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Clean up variables written to the database in setUp().
variable_del('simple_ldap_user_attribute_map');
// Clean up the LDAP entries that were added for testing.
foreach ($this->ldapUser as $lu) {
// Create a new SimpleLdapUser object, which performs a new search based
// on the name attribute. This accounts for the possibility that the LDAP
// entry has changed since it was created.
$ldap_user = new SimpleLdapUser($lu->{$attribute_name}[0]);
$ldap_user
->delete();
$this
->assertFalse($ldap_user->exists, t(':dn was removed from LDAP', array(
':dn' => $ldap_user->dn,
)));
}
parent::tearDown();
}
/**
* Verify that a user is unable to log in.
*/
public function drupalNoLogin(stdClass $user) {
if ($this->loggedInUser) {
$this
->drupalLogout();
}
$edit = array(
'name' => $user->name,
'pass' => $user->pass_raw,
);
$this
->drupalPost('user', $edit, t('Log in'));
// Verify that the user was unable to log in.
$pass = $this
->assertNoLink(t('Log out'), 0, t('User %name unable to log in.', array(
'%name' => $user->name,
)), t('User login'));
if (!$pass) {
$this->loggedInUser = $user;
}
}
/**
* Log in with User 1.
*/
public function drupalUser1Login() {
if ($this->loggedInUser) {
$this
->drupalLogout();
}
// Load password hashing API.
if (!function_exists('user_hash_password')) {
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
}
// Set user1's password to something random in the database.
$pass = hash('sha256', microtime());
db_query("UPDATE {users} SET pass = :hash WHERE uid = 1", array(
':hash' => user_hash_password($pass),
));
// Log in as user1.
$admin_user = user_load(1);
$admin_user->pass_raw = $pass;
$this
->drupalLogin($admin_user);
}
/**
* Verifies that Drupal, LDAP, and the test user values match.
*/
public function verifySync($suffix = '', $name = NULL, $multi = FALSE) {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
$attribute_mail = simple_ldap_user_variable_get('simple_ldap_user_attribute_mail');
$server = SimpleLdapServer::singleton();
// Load the LDAP user.
if ($name === NULL) {
$ldap_user = new SimpleLdapUser($this->ldapUser[0]->{$attribute_name}[0]);
$control = $this->ldapUser[0];
}
else {
$ldap_user = new SimpleLdapUser($name);
$control = $ldap_user;
}
// Load the Drupal user.
$drupal_user = user_load_multiple(array(), array(
'name' => $ldap_user->{$attribute_name}[0],
), TRUE);
$drupal_user = reset($drupal_user);
// Check the mapped fields.
$mapObject = SimpleLdapUserMap::singleton();
$attribute_map = $mapObject->map;
array_unshift($attribute_map, array(
'drupal' => array(
'mail',
),
'ldap' => $attribute_mail,
));
foreach ($attribute_map as $attribute) {
// Skip drupal-to-ldap, one-to-many maps, unless explicitely requested.
if (count($attribute['drupal']) == 1 || $multi) {
// Parse the drupal attribute name.
$drupal = '';
foreach ($attribute['drupal'] as $drupal_attribute) {
$type = substr($drupal_attribute, 0, 1);
switch ($type) {
case '#':
$drupal_attribute = substr($drupal_attribute, 1);
$items = field_get_items('user', $drupal_user, $drupal_attribute);
$drupal .= ' ' . $items[0]['value'];
break;
default:
$drupal .= ' ' . $drupal_user->{$drupal_attribute};
}
}
$drupal = trim($drupal);
// Make sure drupal and ldap match.
$this
->assertEqual($ldap_user->{$attribute['ldap']}[0], $drupal, t('The @ldap LDAP attribute :ldap and the @drupal Drupal field :drupal are synchronized.', array(
'@ldap' => $attribute['ldap'],
'@drupal' => $drupal_attribute,
':ldap' => $ldap_user->{$attribute['ldap']}[0],
':drupal' => $drupal,
)));
// Only single-valued fields will have a control to check.
if (count($attribute['drupal']) == 1) {
// Make sure simple entries match the control.
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
if ($suffix) {
$value = hexdec(substr(sha1($suffix), 0, 2));
}
else {
$value = $control->{$attribute['ldap']}[0];
}
}
else {
$value = $control->{$attribute['ldap']}[0] . $suffix;
}
$this
->assertEqual($value, $drupal, t(':value matches the control value :control', array(
':value' => $drupal,
':control' => $value,
)));
}
}
}
}
}
class SimpleLdapUserAuthenticationWebTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Authentication',
'description' => 'Tests that an LDAP user can authenticate to Drupal with the correct LDAP credentials.',
'group' => 'Simple LDAP User',
);
}
/**
* Test user authentication.
*/
public function testGoodAuthentication() {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Initialize a user account object.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0];
// Verify that the test user does not exist in Drupal.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertIdentical($drupal_user, FALSE, t('The test user does not exist in Drupal.'));
// Verify that the user can log in.
$this
->drupalLogin($account);
// Verify that the Drupal user was created during authentication.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertNotIdentical($drupal_user, FALSE, t('The test user was created in Drupal.'));
// Verify again that the user can log in, now that the account exists in
// both Drupal and LDAP.
$this
->drupalLogin($account);
// Create a new Drupal user that is not in LDAP.
$account = $this->drupalUser[0];
// Verify that the user does not exist in LDAP by random chance.
$ldap_user = new SimpleLdapUser($account->name);
$this
->assertFalse($ldap_user->exists, t('The user account does not exist in LDAP.'));
// Verify that the user cannot log in.
$this
->drupalNoLogin($account);
}
/**
* Tests invalid login credentials.
*/
public function testBadAuthentication() {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Initialize a user account object, with an invalid password.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0] . 'invalid';
// Verify that the test user exists in LDAP.
$ldap_user = new SimpleLdapUser($account->name);
$this
->assertTrue($ldap_user->exists, t(':name exists in LDAP.', array(
':name' => $account->name,
)));
// Verify that the test user does not exist in Drupal.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertIdentical($drupal_user, FALSE, t('The test user does not exist in Drupal.'));
// Verify that the user cannot log in.
$this
->drupalNoLogin($account);
// Verify that the Drupal user was created during the authentication
// attempt.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertNotIdentical($drupal_user, FALSE, t('The test user was created in Drupal.'));
// Verify again that the user cannot log in, now that the account exists in
// both Drupal and LDAP.
$this
->drupalNoLogin($account);
// Create a new Drupal user that is not in LDAP.
$account = $this->drupalUser[0];
$account->pass_raw = $account->pass_raw . 'invalid';
// Verify that the user does not exist in LDAP (by random chance).
$ldap_user = new SimpleLdapUser($account->name);
$this
->assertFalse($ldap_user->exists, t('The user account does not exist in LDAP.'));
// Verify that the user cannot log in.
$this
->drupalNoLogin($account);
// Initialize a random user object.
$account = new stdClass();
$account->name = $this
->randomName();
$account->pass_raw = $this
->randomName();
// Verify that the user does not exist in LDAP (by random chance).
$ldap_user = new SimpleLdapUser($account->name);
$this
->assertFalse($ldap_user->exists, t('The user account does not exist in LDAP.'));
// Verify that the user does not exist in Drupal (by random chance).
$drupal_user = user_load_by_name($account->name);
$this
->assertIdentical($drupal_user, FALSE, t('The user does not exist in Drupal.'));
// Attempt to log in.
$this
->drupalNoLogin($account);
// Verify that the user was not created in LDAP.
$ldap_user = new SimpleLdapUser($account->name);
$this
->assertFalse($ldap_user->exists, t('The user account does not exist in LDAP.'));
// Verify that the user was not created in Drupal.
$drupal_user = user_load_by_name($account->name);
$this
->assertIdentical($drupal_user, FALSE, t('The user does not exist in Drupal.'));
}
}
class SimpleLdapUserUserOneLoginWebTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'User 1 login',
'description' => 'Tests whether User 1 can log in, skipping LDAP authentication.',
'group' => 'Simple LDAP User',
);
}
/**
* Test User 1 authentication.
*/
public function testUserOneLogin() {
// Load user-1.
$admin_user = user_load(1);
// Verify that user-1 does not exist in LDAP.
$ldap_user = new SimpleLdapUser($admin_user->name);
$this
->assertFalse($ldap_user->exists, t('User 1 does not exist in LDAP.'));
// Attempt to log in.
$this
->drupalUser1Login();
// Verify that user-1 still does not exist in LDAP.
$ldap_user = new SimpleLdapUser($admin_user->name);
$this
->assertFalse($ldap_user->exists, t('User 1 does not exist in LDAP.'));
}
}
class SimpleLdapUserModifyProfileWebTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'User can modify profile',
'description' => 'Tests whether a user can modify their profile, and that the changes are synchronized to LDAP.',
'group' => 'Simple LDAP User',
);
}
/**
* Submits the user profile edit form.
*
* Values are taken from the configured test user, and appended by $suffix.
*/
public function postProfileForm($suffix = '') {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
$attribute_mail = simple_ldap_user_variable_get('simple_ldap_user_attribute_mail');
$server = SimpleLdapServer::singleton();
// Get the drupal user.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
// Create the form variable array.
$edit = array();
$edit['current_pass'] = $this->userPassword[0];
$edit['mail'] = $this->ldapUser[0]->{$attribute_mail}[0] . $suffix;
$mapObject = SimpleLdapUserMap::singleton();
foreach ($mapObject->map as $attribute) {
// Skip drupal-to-ldap many-to-one mappings.
if (count($attribute['drupal']) > 1) {
continue;
}
// Get the field name and type.
$drupal_attribute = reset($attribute['drupal']);
$type = substr($drupal_attribute, 0, 1);
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
if ($suffix) {
$value = hexdec(substr(sha1($suffix), 0, 2));
}
else {
$value = $this->ldapUser[0]->{$attribute['ldap']}[0];
}
}
else {
$value = $this->ldapUser[0]->{$attribute['ldap']}[0] . $suffix;
}
switch ($type) {
case '#':
$drupal_attribute = substr($drupal_attribute, 1);
$edit[$drupal_attribute . '[und][0][value]'] = $value;
break;
default:
$edit[$drupal_attribute] = $value;
}
}
// Submit user edit form.
$this
->drupalPost('user/' . $drupal_user->uid . '/edit', $edit, t('Save'));
}
/**
* User edits profile information.
*/
public function testUserChangesProfile() {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Generate a random suffix for testing.
$suffix = $this
->randomName();
// Initialize a user account object.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0];
// Log in user. This should create/sync an LDAP user (tested elsewhere).
$this
->drupalLogin($account);
// Submit the profile edit form, and verify synchronization.
$this
->postProfileForm($suffix);
$this
->verifySync($suffix);
// Reset the values, and verify again.
$this
->postProfileForm();
$this
->verifySync('', NULL, TRUE);
}
}
class SimpleLdapUserRegistrationTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'User registration',
'description' => 'Test registration of user under different configurations.',
'group' => 'Simple LDAP User',
);
}
/**
* Generate random data for user registration form.
*/
public function formData(&$name, &$mail) {
// Generate form data.
$edit['name'] = $name = $this
->randomName();
$edit['mail'] = $mail = $edit['name'] . '@example.com';
// Fill in required fields from the user attribute map.
$server = SimpleLdapServer::singleton();
$objectclass = simple_ldap_user_variable_get('simple_ldap_user_objectclass');
$must = array();
foreach ($objectclass as $o) {
foreach ($server->schema
->must($o, TRUE) as $m) {
if (!in_array($m, $must)) {
$must[] = strtolower($m);
}
}
}
$mapObject = SimpleLdapUserMap::singleton();
foreach ($mapObject->map as $attribute) {
if (in_array($attribute['ldap'], $must)) {
if (count($attribute['drupal']) > 1) {
continue;
}
$drupal_attribute = reset($attribute['drupal']);
if (substr($drupal_attribute, 0, 1) == '#') {
$drupal_attribute = substr($drupal_attribute, 1);
}
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
$edit[$drupal_attribute . '[und][0][value]'] = rand(1000, 65535);
}
else {
$edit[$drupal_attribute . '[und][0][value]'] = $this
->randomName();
}
}
}
return $edit;
}
/**
* Tests user registration with email verification.
*/
public function testRegistrationWithEmailVerification() {
// Require e-mail verification.
variable_set('user_email_verification', TRUE);
// Set registration to administrator only.
variable_set('user_register', USER_REGISTER_ADMINISTRATORS_ONLY);
$this
->drupalGet('user/register');
$this
->assertResponse(403, t('Registration page is inaccessible when only administrators can create accounts.'));
// Allow registration by site visitors without administrator approvial.
variable_set('user_register', USER_REGISTER_VISITORS);
$edit = $this
->formData($name, $mail);
$this
->drupalPost('user/register', $edit, t('Create new account'));
$this
->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), t('User registered successfully.'));
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$new_user = reset($accounts);
$this
->assertTrue($new_user->status, t('New account is active after registration.'));
$ldap_user = new SimpleLdapUser($name);
$this
->assertTrue($ldap_user->exists, t('New account was provisioned to LDAP.'));
// Cleanup.
$ldap_user
->delete();
// Allow registration by site visitors, but require administrator approval.
variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL);
$edit = $this
->formData($name, $mail);
$this
->drupalPost('user/register', $edit, t('Create new account'));
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$new_user = reset($accounts);
$this
->assertFalse($new_user->status, t('New account is blocked until approved by an administrator.'));
$ldap_user = new SimpleLdapUser($name);
$this
->assertTrue($ldap_user->exists, t('New account was provisioned to LDAP.'));
// Cleanup.
$ldap_user
->delete();
}
/**
* Tests user registration without requiring email verification.
*/
public function testRegistrationWithoutEmailVerification() {
// Don't require e-mail verification.
variable_set('user_email_verification', FALSE);
// Allow registration by site visitors without administrator approval.
variable_set('user_register', USER_REGISTER_VISITORS);
$edit = $this
->formData($name, $mail);
// Try entering a mismatching password.
$edit['pass[pass1]'] = '99999.0';
$edit['pass[pass2]'] = '99999';
$this
->drupalPost('user/register', $edit, t('Create new account'));
$this
->assertText(t('The specified passwords do not match.'), t('Typing mismatched passwords displays an error message.'));
// Enter a correct password.
$edit['pass[pass1]'] = $new_pass = $this
->randomName();
$edit['pass[pass2]'] = $new_pass;
$this
->drupalPost('user/register', $edit, t('Create new account'));
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$new_user = reset($accounts);
$this
->assertText(t('Registration successful. You are now logged in.'), t('Users are logged in after registering.'));
$this
->drupalLogout();
$ldap_user = new SimpleLdapUser($name);
$this
->assertTrue($ldap_user->exists, t('New account has been provisioned to LDAP.'));
// Cleanup.
$ldap_user
->delete();
// Allow registration by site visitors, but require administrator approval.
variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL);
$edit = $this
->formData($name, $mail);
$edit['pass[pass1]'] = $pass = $this
->randomName();
$edit['pass[pass2]'] = $pass;
$this
->drupalPost('user/register', $edit, t('Create new account'));
$this
->assertText(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'), t('Users are notified of pending approval'));
$ldap_user = new SimpleLdapUser($name);
$this
->assertTrue($ldap_user->exists, t('New account has been provisioned to LDAP.'));
// Try to login before administrator approval.
$auth = array(
'name' => $name,
'pass' => $pass,
);
$this
->drupalPost('user/login', $auth, t('Log in'));
$this
->assertText(t('The username @name has not been activated or is blocked.', array(
'@name' => $name,
)), t('User cannot login yet.'));
// Activate the new account.
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$new_user = reset($accounts);
$this
->drupalUser1Login();
$edit = array(
'status' => 1,
);
$this
->drupalPost('user/' . $new_user->uid . '/edit', $edit, t('Save'));
$this
->drupalLogout();
// Login after administrator approval.
$this
->drupalPost('user/login', $auth, t('Log in'));
$this
->assertText(t('Member for'), t('The user can log in after administrator approval.'));
// Cleanup.
$ldap_user
->delete();
}
/**
* Tests that the values used to register are properly saved.
*/
public function testRegistrationValues() {
// Get simple_ldap_user config.
$objectclass = simple_ldap_user_variable_get('simple_ldap_user_objectclass');
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
$attribute_mail = simple_ldap_user_variable_get('simple_ldap_user_attribute_mail');
$mapObject = SimpleLdapUserMap::singleton();
// Get a list of required LDAP attributes for the user objectclass.
$server = SimpleLdapServer::singleton();
$must = array();
foreach ($objectclass as $o) {
foreach ($server->schema
->must($o, TRUE) as $m) {
if (!in_array($m, $must)) {
$must[] = strtolower($m);
}
}
}
// Allow registration by site visitors without administrator approval.
variable_set('user_register', USER_REGISTER_VISITORS);
// Don't require e-mail verification.
variable_set('user_email_verification', FALSE);
// Set the default timezone to Brussels.
variable_set('configurable_timezones', 1);
variable_set('date_default_timezone', 'Europe/Brussels');
// Verify that the required mapped fields show up on the registration form.
$this
->drupalGet('user/register');
foreach ($mapObject->map as $field) {
if (count($field['drupal']) > 1) {
continue;
}
$drupal_attribute = reset($field['drupal']);
$type = substr($drupal_attribute, 0, 1);
if (in_array($field['ldap'], $must) && $type == '#') {
$drupal_attribute = substr($drupal_attribute, 1);
$this
->assertText($drupal_attribute, t(':field appears on the user registration form', array(
':field' => $drupal_attribute,
)));
}
}
// Submit registration form.
$edit = $this
->formData($name, $mail);
$edit['pass[pass1]'] = $new_pass = $this
->randomName();
$edit['pass[pass2]'] = $new_pass;
$this
->drupalPost(NULL, $edit, t('Create new account'));
// Load the Drupal user.
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$new_user = reset($accounts);
// Load the LDAP user.
$ldap_user = new SimpleLdapUser($name);
// Check the LDAP objectclass(es).
foreach ($ldap_user->objectclass as $o) {
$this
->assertTrue(in_array($o, $objectclass), t('The LDAP entry has the :o objectclass', array(
':o' => $o,
)));
}
// Check user fields.
$this
->assertEqual($new_user->name, $name, t('Drupal username matches.'));
$this
->assertEqual($ldap_user->{$attribute_name}[0], $name, t('LDAP username matches.'));
$this
->assertEqual($new_user->mail, $mail, t('Drupal e-mail address matches.'));
$this
->assertEqual($ldap_user->{$attribute_mail}[0], $mail, t('LDAP e-mail address matches.'));
foreach ($mapObject->map as $field) {
if (count($field['drupal']) > 1) {
continue;
}
$drupal_attribute = reset($field['drupal']);
$type = substr($drupal_attribute, 0, 1);
if (in_array($field['ldap'], $must) && $type == '#') {
$drupal_attribute = substr($drupal_attribute, 1);
$this
->assertEqual($new_user->{$drupal_attribute}[LANGUAGE_NONE][0]['value'], $edit[$drupal_attribute . '[und][0][value]'], t('The :field Drupal field value was correctly saved.', array(
':field' => $drupal_attribute,
)));
$this
->assertEqual($ldap_user->{$field['ldap']}[0], $edit[$drupal_attribute . '[und][0][value]'], t('The :field LDAP attribute was correctly saved.', array(
':field' => $field['ldap'],
)));
}
}
// Cleanup.
$ldap_user
->delete();
}
}
class SimpleLdapUserSyncTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'User data synchronization',
'description' => 'Test data synchronization between LDAP and Drupal.',
'group' => 'Simple LDAP User',
);
}
/**
* Modifies the test user account in LDAP.
*/
public function modifyLdap($suffix = '') {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
$attribute_mail = simple_ldap_user_variable_get('simple_ldap_user_attribute_mail');
// Load the LDAP Server.
$server = SimpleLdapServer::singleton();
// Search for the User account.
$ldap_user = new SimpleLdapUser($this->ldapUser[0]->{$attribute_name}[0]);
// Modify the mapped attributes.
$mapObject = SimpleLdapUserMap::singleton();
$attribute_map = $mapObject->map;
array_unshift($attribute_map, array(
'drupal' => array(
'mail',
),
'ldap' => $attribute_mail,
));
foreach ($attribute_map as $attribute) {
if (count($attribute['drupal']) == 1) {
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
if ($suffix) {
$value = hexdec(substr(sha1($suffix), 0, 2));
}
else {
$value = $this->ldapUser[0]->{$attribute['ldap']}[0];
}
}
else {
$value = $this->ldapUser[0]->{$attribute['ldap']}[0] . $suffix;
}
try {
$server
->modify($ldap_user->dn, array(
$attribute['ldap'] => $value,
), 'replace');
$entry = $server
->entry($ldap_user->dn);
$this
->assertEqual($value, $entry[0][$attribute['ldap']][0], t('Modified @attr LDAP attribute to :value.', array(
'@attr' => $attribute['ldap'],
':value' => $value,
)));
} catch (SimpleLdapException $e) {
$this
->error($e
->getMessage());
}
}
}
}
/**
* Tests data synchronization using hook_user_login().
*/
public function testSyncOnHookUserLogin() {
// Set the sync trigger to hook_user_login
variable_set('simple_ldap_user_sync', 'hook_user_login');
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Initialize a user account object.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0];
// Log in with the test user, this should do the initial account sync
// (tested elsewhere).
$this
->drupalLogin($account);
// Generate a random value to append.
$suffix = $this
->randomName();
// Drupal is the authoritative source, Change all of the mapped fields,
// login, and verify synchronization.
variable_set('simple_ldap_user_source', 'drupal');
$this
->modifyLdap($suffix);
$this
->drupalLogin($account);
$this
->verifySync();
// LDAP is the authoritative source. Change all of the mapped fields, login,
// and verify synchronization.
variable_set('simple_ldap_user_source', 'ldap');
$this
->modifyLdap($suffix);
$this
->drupalLogin($account);
$this
->verifySync($suffix);
// Clean up by removing the suffix from the LDAP entry, and resyncing.
$this
->modifyLdap();
$this
->drupalLogin($account);
$this
->verifySync();
}
/**
* Tests synchronization using hook_user_load().
*/
public function testSyncOnHookUserLoad() {
// Set the sync trigger to hook_user_load
variable_set('simple_ldap_user_sync', 'hook_user_load');
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Initialize a user account object.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0];
// Log in with the test user, this should do the initial account sync
// (tested elsewhere).
$this
->drupalLogin($account);
// Generate a random value to append.
$suffix = $this
->randomName();
// Drupal is the authoritative source. Change all of the mapped fields, load
// the user, and verify synchronization.
variable_set('simple_ldap_user_source', 'drupal');
$this
->modifyLdap();
$drupal_user = user_load_multiple(array(), array(
'name' => $this->ldapUser[0]->{$attribute_name}[0],
), TRUE);
$this
->verifySync();
// LDAP is the authoritative source. Change all of the mapped fields, load
// the user, and verify synchronization.
variable_set('simple_ldap_user_source', 'ldap');
$this
->modifyLdap($suffix);
$drupal_user = user_load_multiple(array(), array(
'name' => $this->ldapUser[0]->{$attribute_name}[0],
), TRUE);
$this
->verifySync($suffix);
// Clean up by removing the suffix from the LDAP entry, and resyncing.
$this
->modifyLdap();
$drupal_user = user_load_multiple(array(), array(
'name' => $this->ldapUser[0]->{$attribute_name}[0],
), TRUE);
$this
->verifySync();
}
}
class SimpleLdapUserPasswordResetTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'User password change',
'description' => 'Ensure that a user can change their password and that it is updated in LDAP.',
'group' => 'Simple LDAP User',
);
}
/**
* Tests that a user can change thier password.
*/
public function testPasswordChange() {
// Load configuration variables.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Initialize a user account object.
$account = new stdClass();
$account->name = $this->ldapUser[0]->{$attribute_name}[0];
$account->pass_raw = $this->userPassword[0];
// Log in user. This should create/sync an LDAP user (tested elsewhere).
$this
->drupalLogin($account);
// Get the drupal user.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
// Create the form variable array.
$edit = array();
$edit['current_pass'] = $this->userPassword[0];
$edit['pass[pass1]'] = $this
->randomName();
$edit['pass[pass2]'] = $edit['pass[pass1]'];
// Submit user edit form.
$this
->drupalPost('user/' . $drupal_user->uid . '/edit', $edit, 'Save');
// Verify that the old password no longer works.
$this
->drupalNoLogin($account);
// Verify that the new password works.
$account->pass_raw = $edit['pass[pass1]'];
$this
->drupalLogin($account);
// Reset the password.
$edit['current_pass'] = $edit['pass[pass1]'];
$edit['pass[pass1]'] = $this->userPassword[0];
$edit['pass[pass2]'] = $edit['pass[pass1]'];
// Submit user edit form.
$this
->drupalPost('user/' . $drupal_user->uid . '/edit', $edit, 'Save');
// Verify that it was changed back.
$account->pass_raw = $edit['pass[pass1]'];
$this
->drupalLogin($account);
}
/**
* Tests password reset before a Drupal user is created.
*/
public function testLdapNoDrupalPasswordReset() {
// Get the configuration.
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Verify that the test user does not exist in Drupal.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertIdentical($drupal_user, FALSE, t('The test user does not exist in Drupal.'));
// Submit the password reset form.
$edit = array(
'name' => $this->ldapUser[0]->{$attribute_name}[0],
);
$this
->drupalPost('user/password', $edit, t('E-mail new password'));
$this
->assertText(t('Further instructions have been sent to your e-mail address.'), t('A new password was successfully requested.'));
// Verify that the Drupal user was created.
$drupal_user = user_load_by_name($this->ldapUser[0]->{$attribute_name}[0]);
$this
->assertNotIdentical($drupal_user, FALSE, t('The test user was created in Drupal.'));
}
}
class SimpleLdapUserDeleteUserTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Delete user',
'description' => 'Tests that deleting a user in Drupal also deletes the user from LDAP.',
'group' => 'Simple LDAP User',
);
}
/**
* Tests user deletion.
*/
public function testDeleteUser() {
// Disable email verification and admin approval.
variable_set('user_email_verification', FALSE);
variable_set('user_register', USER_REGISTER_VISITORS);
// Make sure the system is set to delete from LDAP
variable_set('simple_ldap_user_delete_from_ldap', 1);
// Generate user registration formdata.
$edit['name'] = $name = $this
->randomName();
$edit['mail'] = $mail = $name . '@example.com';
$edit['pass[pass1]'] = $pass = $this
->randomName();
$edit['pass[pass2]'] = $pass;
// Fill in required fields from the user attribute map.
$server = SimpleLdapServer::singleton();
$objectclass = simple_ldap_user_variable_get('simple_ldap_user_objectclass');
$must = array();
foreach ($objectclass as $o) {
foreach ($server->schema
->must($o, TRUE) as $m) {
if (!in_array($m, $must)) {
$must[] = strtolower($m);
}
}
}
$mapObject = SimpleLdapUserMap::singleton();
foreach ($mapObject->map as $attribute) {
if (in_array($attribute['ldap'], $must)) {
if (count($attribute['drupal']) > 1) {
continue;
}
$drupal_attribute = reset($attribute['drupal']);
if (substr($drupal_attribute, 0, 1) == '#') {
$drupal_attribute = substr($drupal_attribute, 1);
}
$attributetype = $server->schema
->get('attributetypes', $attribute['ldap']);
// A syntax type of 1.3.6.1.4.1.1466.115.121.1.27 is an integer.
if (isset($attributetype['syntax']) && $attributetype['syntax'] == '1.3.6.1.4.1.1466.115.121.1.27') {
$edit[$drupal_attribute . '[und][0][value]'] = rand(1000, 65535);
}
else {
$edit[$drupal_attribute . '[und][0][value]'] = $this
->randomName();
}
}
}
// Submit the registration form to create the user.
$this
->drupalPost('user/register', $edit, t('Create new account'));
$accounts = user_load_multiple(array(), array(
'name' => $name,
'mail' => $mail,
));
$drupal_user = reset($accounts);
$this
->assertText(t('Registration successful. You are now logged in.'), t('Users are logged in after registering.'));
$this
->drupalLogout();
// Verify that the user exists in LDAP.
$ldap_user = new SimpleLdapUser($name);
$this
->assertTrue($ldap_user->exists, t('The user was created in LDAP.'));
// Log in as user1.
$this
->drupalUser1Login();
// Submit the delete-user form.
$edit = array();
$edit['user_cancel_method'] = 'user_cancel_delete';
$this
->drupalPost('user/' . $drupal_user->uid . '/cancel', $edit, t('Cancel account'));
$this
->assertText(t('@name has been deleted.', array(
'@name' => $name,
)), t('The user was deleted from Drupal.'));
// Verify that the user was deleted from LDAP.
$ldap_user = new SimpleLdapUser($name);
$this
->assertFalse($ldap_user->exists, t('The user was deleted from LDAP.'));
}
}
class SimpleLdapUserMassImportExportTestCase extends SimpleLdapUserTestCase {
/**
* Inherited parent::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Mass Import/Export',
'description' => 'Tests mass user import from LDAP, and export to LDAP.',
'group' => 'Simple LDAP User',
);
}
/**
* Test mass export.
*/
public function testExport() {
// Log in as user 1.
$this
->drupalUser1Login();
// Clear cache, otherwise the export option is not present.
$this
->drupalPost('admin/config/development/performance', array(), t('Clear all caches'));
// Verify that the drupal users do not exist in LDAP.
foreach ($this->drupalUser as $drupal_user) {
$ldap_user = new SimpleLdapUser($drupal_user->name);
$this
->assertFalse($ldap_user->exists, t(':name does not exist in LDAP.', array(
':name' => $drupal_user->name,
)));
}
// Submit the export user form.
$edit = array(
'operation' => 'simple_ldap_user_export',
);
foreach ($this->drupalUser as $drupal_user) {
$edit['accounts[' . $drupal_user->uid . ']'] = TRUE;
}
$this
->drupalPost('admin/people', $edit, t('Update'));
// Verify that the users were exported to LDAP.
foreach ($this->drupalUser as $drupal_user) {
$ldap_user = new SimpleLdapUser($drupal_user->name);
$this
->assertTrue($ldap_user->exists, t(':name exists in LDAP at :dn.', array(
':name' => $drupal_user->name,
':dn' => $ldap_user->dn,
)));
$this
->verifySync('', $drupal_user->name);
// Cleanup LDAP.
$ldap_user
->delete();
$this
->assertFalse($ldap_user->exists, t(':dn was removed from LDAP', array(
':dn' => $ldap_user->dn,
)));
}
}
/**
* Test mass import.
*/
public function testImport() {
// Get configuration.
$server = SimpleLdapServer::singleton();
$basedn = simple_ldap_user_variable_get('simple_ldap_user_basedn');
$scope = simple_ldap_user_variable_get('simple_ldap_user_scope');
$attribute_name = simple_ldap_user_variable_get('simple_ldap_user_attribute_name');
// Log in as user 1.
$this
->drupalUser1Login();
// Clear cache, otherwise the import menu item doesn't work.
$this
->drupalPost('admin/config/development/performance', array(), t('Clear all caches'));
// Verify that the LDAP users do not exist in Drupal.
foreach ($this->ldapUser as $ldap_user) {
$drupal_user = user_load_by_name($ldap_user->{$attribute_name}[0]);
$this
->assertIdentical($drupal_user, FALSE, t('The user :name does not exist in Drupal.', array(
':name' => $ldap_user->{$attribute_name}[0],
)));
}
// Submit the import user form.
$edit = array();
// Perform the same search that is done to generate the form, so all of the
// extra entries can be set to false. We just want to import the users
// created specifically for this test.
$filter = '(&(' . $attribute_name . '=*)' . SimpleLdapUser::filter() . ')';
$ldap_users = SimpleLdap::clean($server
->search($basedn, $filter, $scope, array(
'dn',
$attribute_name,
)));
foreach ($ldap_users as $ldap_user) {
$edit['users[' . $ldap_user[$attribute_name][0] . ']'] = FALSE;
}
// Select the users that were created for this test.
foreach ($this->ldapUser as $ldap_user) {
$edit['users[' . $ldap_user->{$attribute_name}[0] . ']'] = TRUE;
}
$this
->drupalPost('admin/people/simple_ldap_user_import', $edit, t('Import'));
// Verify that the users were imported into Drupal.
foreach ($this->ldapUser as $ldap_user) {
$drupal_user = user_load_by_name($ldap_user->{$attribute_name}[0]);
$this
->assertNotIdentical($drupal_user, FALSE, t('The test user :name was created in Drupal.', array(
':name' => $ldap_user->{$attribute_name}[0],
)));
$this
->verifySync('', $ldap_user->{$attribute_name}[0]);
}
}
}