You are here

simple_ldap_role.module in Simple LDAP 7.2

Same filename and directory in other branches
  1. 7 simple_ldap_role/simple_ldap_role.module

Main simple_ldap_role module file.

File

simple_ldap_role/simple_ldap_role.module
View source
<?php

/**
 * @file
 * Main simple_ldap_role module file.
 */

/**
 * Implements hook_menu().
 */
function simple_ldap_role_menu() {
  $items = array();
  $items['admin/config/people/simple_ldap/role'] = array(
    'title' => 'Roles',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'simple_ldap_role_admin',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'simple_ldap_role.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  return $items;
}

/**
 * Implements hook_user_load().
 */
function simple_ldap_role_user_load($users) {
  $sync = simple_ldap_role_variable_get('simple_ldap_role_sync');
  if ($sync == 'hook_user_load') {
    foreach ($users as $user) {
      if ($user->uid == 1) {
        continue;
      }
      switch (simple_ldap_role_variable_get('simple_ldap_role_source')) {
        case 'ldap':
          simple_ldap_role_sync_user_to_drupal($user);
          break;
        case 'drupal':
          simple_ldap_role_sync_user_to_ldap($user);
          break;
      }
    }
  }
}

/**
 * Implements hook_user_login().
 */
function simple_ldap_role_user_login(&$edit, $account) {
  if ($account->uid == 1) {
    return;
  }
  $sync = simple_ldap_role_variable_get('simple_ldap_role_sync');
  if ($sync == 'hook_user_login') {
    switch (simple_ldap_role_variable_get('simple_ldap_role_source')) {
      case 'ldap':
        simple_ldap_role_sync_user_to_drupal($account);
        break;
      case 'drupal':
        simple_ldap_role_sync_user_to_ldap($account);
        break;
    }
  }
}

/**
 * Implements hook_user_presave().
 */
function simple_ldap_role_user_presave(&$edit, $account, $category) {

  // The Authenticated User role will be present on the edit form.
  $exclude = array(
    DRUPAL_AUTHENTICATED_RID,
  );

  // Allow altering excluded roles.
  drupal_alter('simple_ldap_role_exclude', $exclude);

  // Loop through roles submitted on form.
  if (isset($edit['name']) && isset($edit['roles'])) {
    foreach ($edit['roles'] as $rid => $value) {
      if ($value && !in_array($rid, $exclude)) {
        $role = user_role_load($rid);
        $ldap_role = SimpleLdapRole::singleton($role->name);
        $ldap_role
          ->addUser($edit['name']);
        $ldap_role
          ->save();
      }
    }
  }
}

/**
 * Implements hook_user_role_presave().
 */
function simple_ldap_role_user_role_presave($role) {
  if (isset($role->op) && $role->op == 'Save role') {

    // Get the module configuration.
    $attribute_name = simple_ldap_role_variable_get('simple_ldap_role_attribute_name');

    // Get the original role values.
    $original = user_role_load($role->rid);
    $ldap_role = SimpleLdapRole::singleton($original->name);

    // Rename the LDAP role.
    $ldap_role->{$attribute_name} = $role->name;
    $ldap_role
      ->save();
  }
}

/**
 * Implements hook_user_role_insert().
 */
function simple_ldap_role_user_role_insert($role) {
  $ldap_role = SimpleLdapRole::singleton($role->name);
  $ldap_role
    ->save();
}

/**
 * Implements hook_user_role_delete().
 */
function simple_ldap_role_user_role_delete($role) {
  $ldap_role = SimpleLdapRole::singleton($role->name);
  $ldap_role
    ->delete();
}

/**
 * Implements hook_cron().
 */
function simple_ldap_role_cron() {

  // Get the module configuration.
  $basedn = simple_ldap_role_variable_get('simple_ldap_role_basedn');
  $scope = simple_ldap_role_variable_get('simple_ldap_role_scope');
  $attribute_name = simple_ldap_role_variable_get('simple_ldap_role_attribute_name');

  // Get an LDAP server object.
  $server = SimpleLdapServer::singleton();

  // Get a list of LDAP groups.
  $ldap_groups = $server
    ->search($basedn, SimpleLdapRole::filter(), $scope, array(
    $attribute_name,
  ));

  // Get a list of Drupal roles.
  $drupal_roles = user_roles(TRUE);

  // Make sure each of the LDAP groups is also a Drupal role.
  for ($i = 0; $i < $ldap_groups['count']; $i++) {
    $name = $ldap_groups[$i][$attribute_name][0];
    if (!in_array($name, $drupal_roles)) {
      $role = new stdClass();
      $role->name = $name;
      user_role_save($role);
    }
  }
}

/**
 * Implements hook_sync_user_to_ldap().
 *
 * Synchronize Drupal roles to LDAP groups.
 */
function simple_ldap_role_sync_user_to_ldap($drupal_user) {

  // Get module configuration.
  $basedn = simple_ldap_role_variable_get('simple_ldap_role_basedn');
  $scope = simple_ldap_role_variable_get('simple_ldap_role_scope');
  $objectclass = simple_ldap_role_variable_get('simple_ldap_role_objectclass');
  $attribute_name = simple_ldap_role_variable_get('simple_ldap_role_attribute_name');
  $attribute_member = simple_ldap_role_variable_get('simple_ldap_role_attribute_member');
  $attribute_member_format = simple_ldap_role_variable_get('simple_ldap_role_attribute_member_format');
  $attribute_member_default = simple_ldap_role_variable_get('simple_ldap_role_attribute_member_default');

  // Get an LDAP server object.
  $server = SimpleLdapServer::singleton();

  // Determine the search string to use depending on the module configuration.
  if ($attribute_member_format == 'dn') {
    $ldap_user = SimpleLdapUser::singleton($drupal_user->name);
    $search = $ldap_user->dn;
  }
  else {
    $search = $drupal_user->name;
  }

  // Generate the LDAP search filter.
  $safe_search = preg_replace(array(
    '/\\(/',
    '/\\)/',
  ), array(
    '\\\\(',
    '\\\\)',
  ), $search);
  $filter = '(&(' . $attribute_member . '=' . $safe_search . ')' . SimpleLdapRole::filter() . ')';

  // Get a list of LDAP groups of which this user is a member.
  $ldap_groups = $server
    ->search($basedn, $filter, $scope, array(
    $attribute_name,
    $attribute_member,
  ));

  // Get a list of Drupal roles for this user.
  $drupal_roles = array();
  foreach (array_keys($drupal_user->roles) as $rid) {

    // Skip "special" roles.
    $exclude = array(
      DRUPAL_AUTHENTICATED_RID,
      DRUPAL_ANONYMOUS_RID,
    );

    // Allow altering excluded roles.
    drupal_alter('simple_ldap_role_exclude', $exclude);
    if (in_array($rid, $exclude)) {
      continue;
    }
    $role = user_role_load($rid);
    $drupal_roles[$rid] = $role->name;
  }
  foreach ($drupal_roles as $rid => $name) {

    // Check if the user is a member of the ldap group.
    $found = FALSE;
    for ($i = 0; $i < $ldap_groups['count']; $i++) {
      if (isset($ldap_groups[$i][$attribute_name][0]) && $ldap_groups[$i][$attribute_name][0] == $name) {
        $found = TRUE;
      }
    }

    // Add or modify the LDAP group to make sure the user is a member.
    if (!$found) {
      $ldap_group = SimpleLdapRole::singleton($name);
      $ldap_group
        ->addUser($drupal_user->name);
      $ldap_group
        ->save();
    }
  }

  // Check if the member attribute is required.
  $required = FALSE;
  foreach ($objectclass as $o) {
    $must = $server->schema
      ->must($o, TRUE);
    $required = $required || in_array($attribute_member, $must);
  }

  // Remove user from LDAP groups.
  for ($i = 0; $i < $ldap_groups['count']; $i++) {
    $name = $ldap_groups[$i][$attribute_name][0];
    $dn = $ldap_groups[$i]['dn'];
    if (!in_array($name, $drupal_roles)) {
      $ldap_group = SimpleLdapRole::singleton($name);
      $ldap_group
        ->deleteUser($drupal_user->name);
      $ldap_group
        ->save();
    }
  }
}

/**
 * Synchronize LDAP groups to Drupal roles.
 */
function simple_ldap_role_sync_user_to_drupal($drupal_user) {

  // Get module configuration.
  $basedn = simple_ldap_role_variable_get('simple_ldap_role_basedn');
  $scope = simple_ldap_role_variable_get('simple_ldap_role_scope');
  $attribute_name = simple_ldap_role_variable_get('simple_ldap_role_attribute_name');
  $attribute_member = simple_ldap_role_variable_get('simple_ldap_role_attribute_member');
  $attribute_member_format = simple_ldap_role_variable_get('simple_ldap_role_attribute_member_format');

  // Get an LDAP server object.
  $server = SimpleLdapServer::singleton();

  // Determine the search string to use.
  if ($attribute_member_format == 'dn') {
    $ldap_user = SimpleLdapUser::singleton($drupal_user->name);
    $search = $ldap_user->dn;
  }
  else {
    $search = $drupal_user->name;
  }

  // Generate the LDAP search filter.
  $filter = '(&(' . $attribute_member . '=' . $search . ')' . SimpleLdapRole::filter() . ')';

  // Get a list of LDAP groups for this user.
  $ldap_groups = $server
    ->search($basedn, $filter, $scope);

  // Initialize the $edit array.
  $edit['roles'] = array();

  // Check that the groups match between Drupal and LDAP.
  $dirty = FALSE;
  for ($i = 0; $i < $ldap_groups['count']; $i++) {
    $name = $ldap_groups[$i][$attribute_name][0];

    // Try to load the role.
    $drupal_role = user_role_load_by_name($name);

    // The role does not exist, create it.
    if ($drupal_role === FALSE) {
      $role = new stdClass();
      $role->name = $name;
      user_role_save($role);
      $drupal_role = user_role_load_by_name($name);
    }

    // The role is not currently present in the user. Flag a user_save().
    if (!in_array($name, $drupal_user->roles)) {
      $dirty = TRUE;
    }
    $edit['roles'][$drupal_role->rid] = $drupal_role->name;
  }

  // Remove Drupal roles that are not set in LDAP.
  $diff = array_diff($drupal_user->roles, $edit['roles']);
  foreach ($diff as $rid => $name) {

    // Account for special groups.
    $exclude = array(
      DRUPAL_AUTHENTICATED_RID,
      DRUPAL_ANONYMOUS_RID,
    );

    // Allow altering excluded roles.
    drupal_alter('simple_ldap_role_exclude', $exclude);
    if (in_array($rid, $exclude)) {
      $edit['roles'][$rid] = $drupal_user->roles[$rid];
      continue;
    }
    $dirty = TRUE;
  }

  // Save any changes.
  if ($dirty) {
    if (!isset($drupal_user->original)) {

      // This avoids an infinite load/save loop.
      $drupal_user->original = clone $drupal_user;
    }
    $drupal_user = user_save($drupal_user, $edit);
  }

  // Synchronized user.
  return $drupal_user;
}

/**
 * Returns the value for the specified variable.
 *
 * This function takes into account the configured LDAP server type, and
 * attempts to determine a reasonable default value to try to use in the event
 * that the module has not yet been configured.
 */
function simple_ldap_role_variable_get($name, $default = NULL, $force_default = FALSE) {

  // Allow variable name shorthand by prepending 'simple_ldap_role_' to $name if
  // it is not already there.
  if (strpos($name, 'simple_ldap_role_') !== 0) {
    $name = 'simple_ldap_role_' . $name;
  }

  // Get an LDAP server object.
  $server = SimpleLdapServer::singleton();

  // Handle special variables.
  switch ($name) {
    case 'simple_ldap_role_source':

      // If the LDAP server is set to read-only, force LDAP->Drupal sync.
      if ($server->readonly) {
        return 'ldap';
      }
      break;
  }

  // Define defaults that differ based on LDAP server type.
  switch ($server->type) {
    case 'Active Directory':
      $defaults = array(
        'simple_ldap_role_objectclass' => array(
          'group',
        ),
        'simple_ldap_role_attribute_name' => 'cn',
        'simple_ldap_role_attribute_member' => 'member',
        'simple_ldap_role_attribute_member_format' => 'dn',
      );
      break;
    default:
      $defaults = array(
        'simple_ldap_role_objectclass' => array(
          'groupofnames',
        ),
        'simple_ldap_role_attribute_name' => 'cn',
        'simple_ldap_role_attribute_member' => 'member',
        'simple_ldap_role_attribute_member_format' => 'dn',
      );
  }

  // Define defaults that do not depend on LDAP server type.
  $defaults['simple_ldap_role_basedn'] = $server->basedn;
  $defaults['simple_ldap_role_scope'] = 'sub';
  $defaults['simple_ldap_role_source'] = 'ldap';
  $defaults['simple_ldap_role_sync'] = 'hook_user_load';

  // Determine the default value for the given variable.
  $default = isset($defaults[$name]) ? $defaults[$name] : $default;
  if ($force_default) {
    return $default;
  }
  return variable_get($name, $default);
}