LdapAuthorizationConsumerAbstract.class.php in Lightweight Directory Access Protocol (LDAP) 7.2
Same filename and directory in other branches
Abstract class to represent an ldap_authorization consumer behavior such as drupal_role, og_group, etc. each authorization comsumer will extend this class with its own class named LdapAuthorizationConsumer<consumer type> such as LdapAuthorizationConsumerDrupalRole.
File
ldap_authorization/LdapAuthorizationConsumerAbstract.class.phpView source
<?php
/**
* @file
* Abstract class to represent an ldap_authorization consumer behavior
* such as drupal_role, og_group, etc. each authorization comsumer
* will extend this class with its own class named
* LdapAuthorizationConsumer<consumer type> such as LdapAuthorizationConsumerDrupalRole.
*/
/**
*
*/
class LdapAuthorizationConsumerAbstract {
/**
* Machine name of consumer. e.g. og_group, drupal_role, etc.
*/
public $consumerType = NULL;
/**
* The following properties are generally populated from a
* call to hook_ldap_authorization_consumer()
*/
/**
* User interface name of consumer. e.g. drupal role, og group.
*/
public $name;
/**
* User interface name of consumer. e.g. drupal roles, og groups.
*/
public $namePlural;
/**
* User interface short name of consumer. e.g. role, group.
*/
public $shortName;
/**
* User interface short name of consumer plural, e.g. roles, groups.
*/
public $shortNamePlural;
/**
* E.g. roles, groups.
*/
public $description;
/**
* Module providing consumer functionality e.g. ldap_authorization_drupal_roles.
*/
public $consumerModule;
/**
* LDAPConsumerConf object class encapuslating admin form.
*/
public $consumerConf;
/**
* Link to test this consumer.
*/
public $testLink;
/**
* Link to configure this consumer.
*/
public $editLink;
public $emptyConsumer = [
'exists' => TRUE,
'value' => NULL,
'name' => NULL,
'map_to_string' => NULL,
];
/**
* @property boolean $allowConsumerObjectCreation
*
* Does this consumer module support creating consumer objects
* (drupal roles, og groups, etc.)
*/
public $allowConsumerObjectCreation = FALSE;
/**
* @property boolean $detailedWatchdogLog
*
* should watchdog log be used for debugging, useful for non programmers
* who don't have php debugging enabled
*/
public $detailedWatchdogLog = FALSE;
/**
* @property array $defaultConsumerConfProperties
* default properties for consumer admin UI form
*/
public $defaultConsumerConfProperties = [
'onlyApplyToLdapAuthenticated' => TRUE,
'useMappingsAsFilter' => TRUE,
'synchOnLogon' => TRUE,
'revokeLdapProvisioned' => TRUE,
'regrantLdapProvisioned' => TRUE,
'createConsumers' => TRUE,
];
/**
* Constructor Method.
*
* @param string $consumer_type
* e.g. drupal_role, og_group.
* @param array $params
* as associative array of default properties.
*/
public function __construct($consumer_type, $params) {
$this->consumerType = $consumer_type;
$this->name = $params['consumer_name'];
$this->namePlural = $params['consumer_name_plural'];
$this->shortName = $params['consumer_short_name'];
$this->shortNamePlural = $params['consumer_short_name_plural'];
$this->consumerModule = $params['consumer_module'];
$this->mappingDirections = $params['consumer_mapping_directions'];
$this->testLink = l(t('test') . ' ' . $this->name, LDAP_SERVERS_MENU_BASE_PATH . '/authorization/test/' . $this->consumerType);
$this->editLink = l(t('edit') . ' ' . $this->name, LDAP_SERVERS_MENU_BASE_PATH . '/authorization/edit/' . $this->consumerType);
ldap_servers_module_load_include('php', 'ldap_authorization', 'LdapAuthorizationConsumerConfAdmin.class');
$this->consumerConf = new LdapAuthorizationConsumerConf($this);
}
/**
* Function to normalize mappings.
*
* Should be overridden when mappings are not stored as map|authorization_id format
* where authorization_id is the format returned by
* LdapAuthorizationConsumerAbstract::usersAuthorizations()
*
* For example ldap_authorization_og may store mapping target as:
* Campus Accounts|group-name=knitters,role-name=administrator member
* normalized mappings are of form such as for organic groups:
* [
* [
* 'from' => 'students',
* 'normalized' => 'node:21:1',
* 'simplified' => 'node:students:member',
* 'user_entered' => 'students'
* 'valid' => TRUE,
* 'error_message' => '',
* ],
* ...
* ]
*
* Or for Drupal role where rid 3 is moderator and rid 2 is admin:
* [
* [
* 'from' => 'students',
* 'normalized' => '2',
* 'simplified' => 'admin',
* 'user_entered' => 'admin',
* 'valid' => TRUE,
* 'error_message' => '',
* ],
* ...
* ]
*
* Where 'normalized' is in id format and 'simplified' is user shorthand.
*/
public function normalizeMappings($mappings) {
return $mappings;
}
/**
* Create authorization consumers.
*
* @param string (lowercase) $consumer_id
* @param array $consumer
* as associative array with the following key/values
* 'value' => NULL | mixed consumer such as drupal role name, og group entity, etc.
* 'name' => name of consumer for UI, logging etc.
* 'map_to_string' => string mapped to in ldap authorization. mixed case string
* 'exists' => TRUE indicates consumer is known to exist,
* FALSE indicates consumer is known to not exist,
* NULL indicate consumer's existance not checked yet.
*/
public function createConsumer($consumer_id, $consumer) {
// Method must be overridden.
}
/**
* Populate consumer side of $consumers array.
*
* @param array $consumers
* as associative array keyed on $consumer_id with values
* of $consumer. $consumer_id and $consumer have structure in LdapAuthorizationConsumerAbstractClass::createConsumer
* when values are $consumer['exists'] != TRUE need to be populated by consumer object.
* @param bool $create_missing_consumers
* indicates if consumers (drupal roles, og groups, etc) should be created
* if values are NULL, object will be created if.
*
* @return $consumers by reference
*/
public function populateConsumersFromConsumerIds(&$consumers, $create_missing_consumers = FALSE) {
// Method must be overridden.
}
/**
*
*/
public function authorizationDiff($initial, $current) {
return array_diff($initial, $current);
}
/**
* Grant authorizations to a user.
*
* @param object $user
* drupal user object.
* @param array $consumers
* in form of LdapAuthorizationConsumerAbstractClass::populateConsumersFromConsumerIds.
* @param array $ldap_entry
* is ldap data from ldap entry which drupal user is mapped to.
* @param bool $user_save
* should user object be saved by authorizationGrant method.
*
* @return array $results. Array of form
* array(
* <authz consumer id1> => 1,
* <authz consumer id2> => 0,
* )
* where 1s and 0s represent success and failure to grant
*
*
* method may be desireable to override, if consumer benefits from adding grants as a group rather than one at a time
*/
public function authorizationGrant(&$user, &$user_auth_data, $consumers, $ldap_entry = NULL, $user_save = TRUE) {
$this
->filterOffPastAuthorizationRecords($user, $user_auth_data);
$this
->grantsAndRevokes('grant', $user, $user_auth_data, $consumers, $ldap_entry, $user_save);
}
/**
* Revoke authorizations to a user.
*
* @param object $user
* drupal user object.
* @param array $consumers
* in form of LdapAuthorizationConsumerAbstractClass::populateConsumersFromConsumerIds.
* @param array $ldap_entry
* is ldap data from ldap entry which drupal user is mapped to.
* @param bool $user_save
* should user object be saved by authorizationGrant method.
*
* @return array $results. Array of form
* array(
* <authz consumer id1> => 1,
* <authz consumer id2> => 0,
* )
* where 1s and 0s represent success and failure to revoke
* $user_auth_data is returned by reference
*
* method may be desireable to override, if consumer benefits from revoking grants as a group rather than one at a time
*/
public function authorizationRevoke(&$user, &$user_auth_data, $consumers, $ldap_entry, $user_save = TRUE) {
$this
->filterOffPastAuthorizationRecords($user, $user_auth_data);
$this
->grantsAndRevokes('revoke', $user, $user_auth_data, $consumers, $ldap_entry, $user_save);
}
/**
* This is a function to clear off.
*/
public function filterOffPastAuthorizationRecords(&$user, &$user_auth_data, $time = NULL) {
if ($time != NULL || variable_get('ldap_help_user_data_clear', 0)) {
$clear_time = $time ? $time : variable_get('ldap_help_user_data_clear_set_date', 0);
if ($clear_time > 0 && $clear_time < time()) {
foreach ($user_auth_data as $consumer_id => $entry) {
if ($entry['date_granted'] < $clear_time) {
unset($user_auth_data[$consumer_id]);
if (isset($user->data['ldap_authorizations'][$this->consumerType][$consumer_id])) {
unset($user->data['ldap_authorizations'][$this->consumerType][$consumer_id]);
}
}
}
}
}
}
/**
* Some authorization schemes such as organic groups, require a certain order. implement this method
* to sort consumer ids/authorization ids.
*
* @param string $op
* 'grant' or 'revoke' signifying what to do with the $consumer_ids.
* @param $consumers
* associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
*
* alters $consumers by reference
*/
public function sortConsumerIds($op, &$consumers) {
}
/**
* Attempt to flush related caches. This will be something like og_invalidate_cache($gids)
*
* @param $consumers
* associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
*/
public function flushRelatedCaches($consumers = NULL) {
}
/**
* @param string $op
* 'grant' or 'revoke' signifying what to do with the $consumer_ids.
* @param drupal user object $object
* @param array $user_auth_data
* is array specific to this consumer_type. Stored at $user->data['ldap_authorizations'][<consumer_type>].
* @param $consumers
* as associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
* @param array $ldap_entry,
* when available user's ldap entry.
* @param bool $user_save
* indicates is user data array should be saved or not. this depends on the implementation calling this function.
*/
protected function grantsAndRevokes($op, &$user, &$user_auth_data, $consumers, &$ldap_entry = NULL, $user_save = TRUE) {
if (!is_array($user_auth_data)) {
$user_auth_data = [];
}
$detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
$this
->sortConsumerIds($op, $consumers);
$results = [];
$watchdog_tokens = [];
$watchdog_tokens['%username'] = $user->name;
$watchdog_tokens['%action'] = $op;
$watchdog_tokens['%user_save'] = $user_save;
$consumer_ids_log = [];
$users_authorization_ids = $this
->usersAuthorizations($user);
$watchdog_tokens['%users_authorization_ids'] = join(', ', $users_authorization_ids);
if ($detailed_watchdog_log) {
watchdog('ldap_authorization', "on call of grantsAndRevokes: user_auth_data=" . print_r($user_auth_data, TRUE), $watchdog_tokens, WATCHDOG_DEBUG);
}
foreach ($consumers as $consumer_id => $consumer) {
if ($detailed_watchdog_log) {
watchdog('ldap_authorization', "consumer_id={$consumer_id}, user_save={$user_save}, op={$op}", $watchdog_tokens, WATCHDOG_DEBUG);
}
$log = "consumer_id={$consumer_id}, op={$op},";
$user_has_authorization = in_array($consumer_id, $users_authorization_ids);
$user_has_authorization_recorded = isset($user_auth_data[$consumer_id]);
/** grants **/
if ($op == 'grant') {
if ($user_has_authorization && !$user_has_authorization_recorded) {
// Grant case 1: authorization id already exists for user, but is not ldap provisioned. mark as ldap provisioned, but don't regrant.
$results[$consumer_id] = TRUE;
$user_auth_data[$consumer_id] = [
'date_granted' => time(),
'consumer_id_mixed_case' => $consumer_id,
];
}
elseif (!$user_has_authorization && $consumer['exists']) {
// Grant case 2: consumer exists, but user is not member. grant authorization
// allow consuming module to add additional data to $user_auth_data.
$results[$consumer_id] = $this
->grantSingleAuthorization($user, $consumer_id, $consumer, $user_auth_data, $user_save);
$existing = empty($user_auth_data[$consumer_id]) ? [] : $user_auth_data[$consumer_id];
$user_auth_data[$consumer_id] = $existing + [
'date_granted' => time(),
'consumer_id_mixed_case' => $consumer_id,
];
}
elseif ($consumer['exists'] !== TRUE) {
// Grant case 3: something is wrong. consumers should have been created before calling grantsAndRevokes.
$results[$consumer_id] = FALSE;
}
elseif ($consumer['exists'] === TRUE) {
// Grant case 4: consumer exists and user has authorization recorded. do nothing.
$results[$consumer_id] = TRUE;
}
else {
// Grant case 5: $consumer['exists'] has not been properly set before calling function.
$results[$consumer_id] = FALSE;
watchdog('ldap_authorization', "grantsAndRevokes consumer[exists] not properly set. consumer_id={$consumer_id}, op={$op}, username=%username", $watchdog_tokens, WATCHDOG_ERROR);
}
}
elseif ($op == 'revoke') {
$log .= "revoking existing consumer object, ";
if ($user_has_authorization) {
// Revoke case 1: user has authorization, revoke it. revokeSingleAuthorization will remove $user_auth_data[$consumer_id]
// defer to default for $user_save param.
$results[$consumer_id] = $this
->revokeSingleAuthorization($user, $consumer_id, $consumer, $user_auth_data, $user_save);
$log .= t(',result=') . (bool) $results[$consumer_id];
}
elseif ($user_has_authorization_recorded) {
// Revoke case 2: user does not have authorization, but has record of it. remove record of it.
unset($user_auth_data[$consumer_id]);
$results[$consumer_id] = TRUE;
}
else {
// Revoke case 3: trying to revoke something that isn't there.
$results[$consumer_id] = TRUE;
}
}
$consumer_ids_log[] = $log;
if ($detailed_watchdog_log) {
watchdog('ldap_authorization', "user_auth_data after consumer {$consumer_id}" . print_r($user_auth_data, TRUE), $watchdog_tokens, WATCHDOG_DEBUG);
}
}
$watchdog_tokens['%consumer_ids_log'] = count($consumer_ids_log) ? join('<hr/>', $consumer_ids_log) : t('no actions');
if ($user_save) {
$user = user_load($user->uid, TRUE);
$user_edit = $user->data;
$user_edit['data']['ldap_authorizations'][$this->consumerType] = $user_auth_data;
$user = user_save($user, $user_edit);
// Reload this.
$user_auth_data = $user->data['ldap_authorizations'][$this->consumerType];
}
$this
->flushRelatedCaches($consumers);
if ($detailed_watchdog_log) {
watchdog('ldap_authorization', '%username:
<hr/>LdapAuthorizationConsumerAbstract grantsAndRevokes() method log. action=%action:<br/> %consumer_ids_log
', $watchdog_tokens, WATCHDOG_DEBUG);
}
}
/**
* @param drupal user object $user
* to have $consumer_id revoked.
* @param string lower case $consumer_id
* $consumer_id such as drupal role name, og group name, etc.
* @param mixed $consumer
* depends on type of consumer. Drupal roles are strings, og groups are ??
* @param array $user_auth_data
* array of $user data specific to this consumer type.
* stored in $user->data['ldap_authorizations'][<consumer_type>] array.
* @param bool $reset
* signifying if caches associated with $consumer_id should be invalidated.
*
* return boolen TRUE on success, FALSE on fail. If user save is FALSE, the user object will
* not be saved and reloaded, so a returned TRUE may be misleading.
* $user_auth_data should have successfully revoked consumer id removed.
*/
public function revokeSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data, $user_save = FALSE, $reset = FALSE) {
// Method must be overridden.
}
/**
* @param object $user
* as drupal user object to have $consumer_id granted.
* @param string lower case $consumer_id
* $consumer_id such as drupal role name, og group name, etc.
* @param mixed $consumer
* depends on type of consumer. Drupal roles are strings, og groups are ??
* @param array $user_auth_data
* in form
* array('my drupal role' =>
* 'date_granted' => 1351814718,
* 'consumer_id_mixed_case' => 'My Drupal Role',
* )
* @param bool $reset
* signifying if caches associated with $consumer_id should be invalidated.
* @return boolean FALSE on failure or TRUE on success
*/
public function grantSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data, $user_save = FALSE, $reset = FALSE) {
// Method must be overridden.
}
/**
* Return all user consumer ids
* regardless of it they were granted by this module.
*
* @param user object $user
*
* @return array of consumer ids such as array('3-2','7-2'), array('admin','user_admin')
*/
public function usersAuthorizations(&$user) {
// Method must be overridden.
}
/**
* Put authorization ids in displayable format.
*/
public function convertToFriendlyAuthorizationIds($authorizations) {
return $authorizations;
}
/**
* @param drupal user object $user
* to have $consumer_id granted.
* @param string lower case $consumer_id
* $consumer_id such as drupal role name, og group name, etc.
* @param mixed $consumer
* depends on type of consumer. Drupal roles are strings, og groups are ??
*
* return boolen TRUE on success, FALSE on fail. If user save is FALSE, the user object will
* not be saved and reloaded, so a returned TRUE may be misleading.
*/
public function createSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data) {
// Method must be overridden.
}
/**
* @param drupal user object $user
* @param string lowercase $consumer_id
* such as drupal role name, og group name, etc.
*
* @return boolean if an ldap_authorization_* module granted the authorization id
*/
public function hasLdapGrantedAuthorization(&$user, $consumer_id) {
return !empty($user->data['ldap_authorizations'][$this->consumerType][$consumer_id]);
}
/**
* NOTE this is in mixed case, since we must rely on whatever module is storing
* the authorization id.
*
* @param drupal user object $user
* @param string lowercase case $consumer_id
* such as drupal role name, og group name, etc.
*
* @return param boolean is user has authorization id, regardless of what module granted it.
*/
public function hasAuthorization(&$user, $consumer_id) {
return @in_array($consumer_id, $this
->usersAuthorizations($user));
}
/**
* Validate authorization mappings on LDAP Authorization OG Admin form.
*
* @param array $mapping
* single mapping in format generated in normalizeMappings method.
* @param array $form_values
* from authorization configuration form.
* @param bool $clear_cache
*
* @return array of form array($message_type, $message_text) where message type is status, warning, or error
* and $message_text is what the user should see.
*/
public function validateAuthorizationMappingTarget($mapping, $form_values = NULL, $clear_cache = FALSE) {
$message_type = NULL;
$message_text = NULL;
return [
$message_type,
$message_text,
];
}
}
Classes
Name | Description |
---|---|
LdapAuthorizationConsumerAbstract |