Projet

Général

Profil

Paste
Télécharger (19,8 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ldap / ldap_authorization / LdapAuthorizationConsumerAbstract.class.php @ bc175c27

1
<?php
2

    
3
/**
4
 * @file
5
 * Abstract class to represent an ldap_authorization consumer behavior
6
 * such as drupal_role, og_group, etc.  each authorization comsumer
7
 * will extend this class with its own class named
8
 * LdapAuthorizationConsumer<consumer type> such as LdapAuthorizationConsumerDrupalRole.
9
 */
10

    
11
/**
12
 *
13
 */
14
class LdapAuthorizationConsumerAbstract {
15

    
16
  /**
17
   * Machine name of consumer.  e.g. og_group, drupal_role, etc.
18
   */
19
  public $consumerType = NULL;
20

    
21
  /**
22
   * The following properties are generally populated from a
23
   * call to hook_ldap_authorization_consumer()
24
   */
25

    
26
  /**
27
   * User interface name of consumer. e.g.  drupal role, og group.
28
   */
29
  public $name;
30

    
31
  /**
32
   * User interface name of consumer. e.g. drupal roles, og groups.
33
   */
34
  public $namePlural;
35
  /**
36
   * User interface short name of consumer. e.g. role, group.
37
   */
38
  public $shortName;
39

    
40
  /**
41
   * User interface short name of consumer plural, e.g. roles, groups.
42
   */
43
  public $shortNamePlural;
44

    
45
  /**
46
   * E.g. roles, groups.
47
   */
48
  public $description;
49
  /**
50
   * Module providing consumer functionality e.g. ldap_authorization_drupal_roles.
51
   */
52
  public $consumerModule;
53

    
54
  /**
55
   * LDAPConsumerConf object class encapuslating admin form.
56
   */
57
  public $consumerConf;
58

    
59
  /**
60
   * Link to test this consumer.
61
   */
62
  public $testLink;
63

    
64
  /**
65
   * Link to configure this consumer.
66
   */
67
  public $editLink;
68

    
69
  public $emptyConsumer = array(
70
    'exists' => TRUE,
71
    'value' => NULL,
72
    'name' => NULL,
73
    'map_to_string' => NULL,
74
  );
75

    
76
  /**
77
   * @property boolean $allowConsumerObjectCreation
78
   *
79
   *  Does this consumer module support creating consumer objects
80
   * (drupal roles,  og groups, etc.)
81
   */
82

    
83
  public $allowConsumerObjectCreation = FALSE;
84

    
85
  /**
86
   * @property boolean $detailedWatchdogLog
87
   *
88
   *  should watchdog log be used for debugging, useful for non programmers
89
   *  who don't have php debugging enabled
90
   */
91
  public $detailedWatchdogLog = FALSE;
92

    
93

    
94
  /**
95
   * @property array $defaultConsumerConfProperties
96
   * default properties for consumer admin UI form
97
   */
98
  public $defaultConsumerConfProperties = array(
99
    'onlyApplyToLdapAuthenticated' => TRUE,
100
    'useMappingsAsFilter' => TRUE,
101
    'synchOnLogon' => TRUE,
102
    'revokeLdapProvisioned' => TRUE,
103
    'regrantLdapProvisioned' => TRUE,
104
    'createConsumers' => TRUE,
105
  );
106

    
107
  /**
108
   * Constructor Method.
109
   *
110
   * @param string $consumer_type
111
   *   e.g. drupal_role, og_group.
112
   * @param array $params
113
   *   as associative array of default properties.
114
   */
115
  public function __construct($consumer_type, $params) {
116
    $this->consumerType = $consumer_type;
117
    $this->name = $params['consumer_name'];
118
    $this->namePlural = $params['consumer_name_plural'];
119
    $this->shortName = $params['consumer_short_name'];
120
    $this->shortNamePlural = $params['consumer_short_name_plural'];
121
    $this->consumerModule = $params['consumer_module'];
122
    $this->mappingDirections = $params['consumer_mapping_directions'];
123
    $this->testLink = l(t('test') . ' ' . $this->name, LDAP_SERVERS_MENU_BASE_PATH . '/authorization/test/' . $this->consumerType);
124
    $this->editLink = l(t('edit') . ' ' . $this->name, LDAP_SERVERS_MENU_BASE_PATH . '/authorization/edit/' . $this->consumerType);
125
    ldap_servers_module_load_include('php', 'ldap_authorization', 'LdapAuthorizationConsumerConfAdmin.class');
126
    $this->consumerConf = new LdapAuthorizationConsumerConf($this);
127
  }
128

    
129
  /**
130
   * Function to normalize mappings
131
   * should be overridden when mappings are not stored as map|authorization_id format
132
   * where authorization_id is the format returned by
133
   *   LdapAuthorizationConsumerAbstract::usersAuthorizations()
134
   *
135
   * For example ldap_authorization_og may store mapping target as:
136
   *   Campus Accounts|group-name=knitters,role-name=administrator member.
137
   *
138
   *   normalized mappings are of form such as for organic groups:
139
   *
140
   *   array(
141
         array(
142
           'from' => 'students',
143
           'normalized' => 'node:21:1',
144
           'simplified' => 'node:students:member',
145
           'user_entered' => 'students'
146
           'valid' => TRUE,
147
           'error_message' => '',
148
           ),
149

150
         ...
151
        )
152

153
   *   or for drupal role where rid 3 is moderator and rid 2 is admin:
154
   *   array(
155
         array(
156
           'from' => 'students',
157
           'normalized' => '2',
158
           'simplified' => 'admin',
159
           'user_entered' => 'admin',
160
           'valid' => TRUE,
161
           'error_message' => '',
162
           ),
163
         ...
164
        )
165

166
        where 'normalized' is in id format and 'simplified' is user shorthand
167
   )
168
   */
169
  public function normalizeMappings($mappings) {
170
    return $mappings;
171
  }
172

    
173
  /**
174
   * Create authorization consumers.
175
   *
176
   * @param string (lowercase) $consumer_id
177
   * @param array $consumer
178
   *   as associative array with the following key/values
179
   *   'value' => NULL | mixed consumer such as drupal role name, og group entity, etc.
180
   *   'name' => name of consumer for UI, logging etc.
181
   *   'map_to_string' => string mapped to in ldap authorization.  mixed case string
182
   *   'exists' => TRUE indicates consumer is known to exist,
183
   *               FALSE indicates consumer is known to not exist,
184
   *               NULL indicate consumer's existance not checked yet.
185
   */
186
  public function createConsumer($consumer_id, $consumer) {
187
    // Method must be overridden.
188
  }
189

    
190
  /**
191
   * Populate consumer side of $consumers array.
192
   *
193
   * @param array $consumers
194
   *   as associative array keyed on $consumer_id with values
195
   *   of $consumer.  $consumer_id and $consumer have structure in LdapAuthorizationConsumerAbstractClass::createConsumer
196
   *   when values are $consumer['exists'] != TRUE need to be populated by consumer object.
197
   * @param bool $create_missing_consumers
198
   *   indicates if consumers (drupal roles, og groups, etc) should be created
199
   *   if values are NULL, object will be created if.
200
   *
201
   * @return $consumers by reference
202
   */
203
  public function populateConsumersFromConsumerIds(&$consumers, $create_missing_consumers = FALSE) {
204
    // Method must be overridden.
205
  }
206

    
207
  /**
208
   *
209
   */
210
  public function authorizationDiff($initial, $current) {
211
    return array_diff($initial, $current);
212
  }
213

    
214
  /**
215
   * Grant authorizations to a user.
216
   *
217
   * @param object $user
218
   *   drupal user object.
219
   * @param array $consumers
220
   *   in form of LdapAuthorizationConsumerAbstractClass::populateConsumersFromConsumerIds.
221
   * @param array $ldap_entry
222
   *   is ldap data from ldap entry which drupal user is mapped to.
223
   * @param bool $user_save
224
   *   should user object be saved by authorizationGrant method.
225
   *
226
   * @return array $results.  Array of form
227
   *   array(
228
   *    <authz consumer id1> => 1,
229
   *    <authz consumer id2> => 0,
230
   *   )
231
   *   where 1s and 0s represent success and failure to grant
232
   *
233
   *
234
   *   method may be desireable to override, if consumer benefits from adding grants as a group rather than one at a time
235
   */
236
  public function authorizationGrant(&$user, &$user_auth_data, $consumers, $ldap_entry = NULL, $user_save = TRUE) {
237
    $this->filterOffPastAuthorizationRecords($user, $user_auth_data);
238
    $this->grantsAndRevokes('grant', $user, $user_auth_data, $consumers, $ldap_entry, $user_save);
239
  }
240

    
241
  /**
242
   * Revoke authorizations to a user.
243
   *
244
   * @param object $user
245
   *   drupal user object.
246
   * @param array $consumers
247
   *   in form of LdapAuthorizationConsumerAbstractClass::populateConsumersFromConsumerIds.
248
   * @param array $ldap_entry
249
   *   is ldap data from ldap entry which drupal user is mapped to.
250
   * @param bool $user_save
251
   *   should user object be saved by authorizationGrant method.
252
   *
253
   * @return array $results.  Array of form
254
   *   array(
255
   *    <authz consumer id1> => 1,
256
   *    <authz consumer id2> => 0,
257
   *   )
258
   *   where 1s and 0s represent success and failure to revoke
259
   *   $user_auth_data is returned by reference
260
   *
261
   *   method may be desireable to override, if consumer benefits from revoking grants as a group rather than one at a time
262
   */
263
  public function authorizationRevoke(&$user, &$user_auth_data, $consumers, $ldap_entry, $user_save = TRUE) {
264
    $this->filterOffPastAuthorizationRecords($user, $user_auth_data);
265
    $this->grantsAndRevokes('revoke', $user, $user_auth_data, $consumers, $ldap_entry, $user_save);
266
  }
267

    
268
  /**
269
   * This is a function to clear off.
270
   */
271
  public function filterOffPastAuthorizationRecords(&$user, &$user_auth_data, $time = NULL) {
272
    if ($time != NULL || variable_get('ldap_help_user_data_clear', 0)) {
273
      $clear_time = ($time) ? $time : variable_get('ldap_help_user_data_clear_set_date', 0);
274
      if ($clear_time > 0 && $clear_time < time()) {
275
        foreach ($user_auth_data as $consumer_id => $entry) {
276
          if ($entry['date_granted'] < $clear_time) {
277
            unset($user_auth_data[$consumer_id]);
278
            if (isset($user->data['ldap_authorizations'][$this->consumerType][$consumer_id])) {
279
              unset($user->data['ldap_authorizations'][$this->consumerType][$consumer_id]);
280
            }
281
          }
282
        }
283
      }
284
    }
285
  }
286

    
287
  /**
288
   * Some authorization schemes such as organic groups, require a certain order.  implement this method
289
   * to sort consumer ids/authorization ids.
290
   *
291
   * @param string $op
292
   *   'grant' or 'revoke' signifying what to do with the $consumer_ids.
293
   * @param $consumers
294
   *   associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
295
   *
296
   *   alters $consumers by reference
297
   */
298
  public function sortConsumerIds($op, &$consumers) {}
299

    
300
  /**
301
   * Attempt to flush related caches.  This will be something like og_invalidate_cache($gids)
302
   *
303
   * @param $consumers
304
   *   associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
305
   */
306
  public function flushRelatedCaches($consumers = NULL) {}
307

    
308
  /**
309
   * @param string $op
310
   *   'grant' or 'revoke' signifying what to do with the $consumer_ids.
311
   * @param drupal user object $object
312
   * @param array $user_auth_data
313
   *   is array specific to this consumer_type.  Stored at $user->data['ldap_authorizations'][<consumer_type>].
314
   * @param $consumers
315
   *   as associative array in form of LdapAuthorizationConsumerAbstract::populateConsumersFromConsumerIds
316
   * @param array $ldap_entry,
317
   *   when available user's ldap entry.
318
   * @param bool $user_save
319
   *   indicates is user data array should be saved or not.  this depends on the implementation calling this function.
320
   */
321
  protected function grantsAndRevokes($op, &$user, &$user_auth_data, $consumers, &$ldap_entry = NULL, $user_save = TRUE) {
322

    
323
    if (!is_array($user_auth_data)) {
324
      $user_auth_data = array();
325
    }
326

    
327
    $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
328
    $this->sortConsumerIds($op, $consumers);
329
    $results = array();
330
    $watchdog_tokens = array();
331
    $watchdog_tokens['%username'] = $user->name;
332
    $watchdog_tokens['%action'] = $op;
333
    $watchdog_tokens['%user_save'] = $user_save;
334
    $consumer_ids_log = array();
335
    $users_authorization_ids = $this->usersAuthorizations($user);
336
    $watchdog_tokens['%users_authorization_ids'] = join(', ', $users_authorization_ids);
337
    if ($detailed_watchdog_log) {
338
      watchdog('ldap_authorization', "on call of grantsAndRevokes: user_auth_data=" . print_r($user_auth_data, TRUE), $watchdog_tokens, WATCHDOG_DEBUG);
339
    }
340

    
341
    foreach ($consumers as $consumer_id => $consumer) {
342
      if ($detailed_watchdog_log) {
343
        watchdog('ldap_authorization', "consumer_id=$consumer_id, user_save=$user_save, op=$op", $watchdog_tokens, WATCHDOG_DEBUG);
344
      }
345
      $log = "consumer_id=$consumer_id, op=$op,";
346
      $user_has_authorization = in_array($consumer_id, $users_authorization_ids);
347
      $user_has_authorization_recorded = isset($user_auth_data[$consumer_id]);
348

    
349
      /** grants **/
350
      if ($op == 'grant') {
351
        if ($user_has_authorization && !$user_has_authorization_recorded) {
352
          // Grant case 1: authorization id already exists for user, but is not ldap provisioned.  mark as ldap provisioned, but don't regrant.
353
          $results[$consumer_id] = TRUE;
354
          $user_auth_data[$consumer_id] = array(
355
            'date_granted' => time(),
356
            'consumer_id_mixed_case' => $consumer_id,
357
          );
358
        }
359
        elseif (!$user_has_authorization && $consumer['exists']) {
360
          // Grant case 2: consumer exists, but user is not member. grant authorization
361
          // allow consuming module to add additional data to $user_auth_data.
362
          $results[$consumer_id] = $this->grantSingleAuthorization($user, $consumer_id, $consumer, $user_auth_data, $user_save);
363
          $existing = empty($user_auth_data[$consumer_id]) ? array() : $user_auth_data[$consumer_id];
364
          $user_auth_data[$consumer_id] = $existing + array(
365
            'date_granted' => time(),
366
            'consumer_id_mixed_case' => $consumer_id,
367
          );
368
        }
369
        elseif ($consumer['exists'] !== TRUE) {
370
          // Grant case 3: something is wrong. consumers should have been created before calling grantsAndRevokes.
371
          $results[$consumer_id] = FALSE;
372
        }
373
        elseif ($consumer['exists'] === TRUE) {
374
          // Grant case 4: consumer exists and user has authorization recorded. do nothing.
375
          $results[$consumer_id] = TRUE;
376
        }
377
        else {
378
          // Grant case 5: $consumer['exists'] has not been properly set before calling function.
379
          $results[$consumer_id] = FALSE;
380
          watchdog('ldap_authorization', "grantsAndRevokes consumer[exists] not properly set. consumer_id=$consumer_id, op=$op, username=%username", $watchdog_tokens, WATCHDOG_ERROR);
381
        }
382
      }
383
      /** revokes **/
384
      elseif ($op == 'revoke') {
385

    
386
        $log .= "revoking existing consumer object, ";
387
        if ($user_has_authorization) {
388
          // Revoke case 1: user has authorization, revoke it.  revokeSingleAuthorization will remove $user_auth_data[$consumer_id]
389
          // defer to default for $user_save param.
390
          $results[$consumer_id] = $this->revokeSingleAuthorization($user, $consumer_id, $consumer, $user_auth_data, $user_save);
391
          $log .= t(',result=') . (boolean) ($results[$consumer_id]);
392
        }
393
        elseif ($user_has_authorization_recorded) {
394
          // Revoke case 2: user does not have authorization, but has record of it. remove record of it.
395
          unset($user_auth_data[$consumer_id]);
396
          $results[$consumer_id] = TRUE;
397
        }
398
        else {
399
          // Revoke case 3: trying to revoke something that isn't there.
400
          $results[$consumer_id] = TRUE;
401
        }
402

    
403
      }
404
      $consumer_ids_log[] = $log;
405
      if ($detailed_watchdog_log) {
406
        watchdog('ldap_authorization', "user_auth_data after consumer $consumer_id" . print_r($user_auth_data, TRUE), $watchdog_tokens, WATCHDOG_DEBUG);
407
      }
408

    
409
    }
410
    $watchdog_tokens['%consumer_ids_log'] = (count($consumer_ids_log)) ? join('<hr/>', $consumer_ids_log) : t('no actions');
411

    
412
    if ($user_save) {
413
      $user = user_load($user->uid, TRUE);
414
      $user_edit = $user->data;
415
      $user_edit['data']['ldap_authorizations'][$this->consumerType] = $user_auth_data;
416
      $user = user_save($user, $user_edit);
417
      // Reload this.
418
      $user_auth_data = $user->data['ldap_authorizations'][$this->consumerType];
419
    }
420
    $this->flushRelatedCaches($consumers);
421

    
422
    if ($detailed_watchdog_log) {
423
      watchdog('ldap_authorization', '%username:
424
        <hr/>LdapAuthorizationConsumerAbstract grantsAndRevokes() method log.  action=%action:<br/> %consumer_ids_log
425
        ',
426
        $watchdog_tokens, WATCHDOG_DEBUG);
427
    }
428

    
429
  }
430

    
431
  /**
432
   * @param drupal user object $user
433
   *   to have $consumer_id revoked.
434
   * @param string lower case $consumer_id
435
   *   $consumer_id such as drupal role name, og group name, etc.
436
   * @param mixed $consumer
437
   *   depends on type of consumer.  Drupal roles are strings, og groups are ??
438
   * @param array $user_auth_data
439
   *   array of $user data specific to this consumer type.
440
   *   stored in $user->data['ldap_authorizations'][<consumer_type>] array.
441
   * @param bool $reset
442
   *   signifying if caches associated with $consumer_id should be invalidated.
443
   *
444
   *   return boolen TRUE on success, FALSE on fail.  If user save is FALSE, the user object will
445
   *   not be saved and reloaded, so a returned TRUE may be misleading.
446
   *   $user_auth_data should have successfully revoked consumer id removed.
447
   */
448
  public function revokeSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data, $user_save = FALSE, $reset = FALSE) {
449
    // Method must be overridden.
450
  }
451

    
452
  /**
453
   * @param object $user
454
   *   as drupal user object to have $consumer_id granted.
455
   * @param string lower case $consumer_id
456
   *   $consumer_id such as drupal role name, og group name, etc.
457
   * @param mixed $consumer
458
   *   depends on type of consumer.  Drupal roles are strings, og groups are ??
459
   * @param array $user_auth_data
460
   *   in form
461
   *   array('my drupal role' =>
462
   *     'date_granted' => 1351814718,
463
   *     'consumer_id_mixed_case' => 'My Drupal Role',
464
   *     )
465
   * @param bool $reset
466
   *   signifying if caches associated with $consumer_id should be invalidated.
467
   * @return boolean FALSE on failure or TRUE on success
468
   */
469
  public function grantSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data, $user_save = FALSE, $reset = FALSE) {
470
    // Method must be overridden.
471
  }
472

    
473
  /**
474
   * Return all user consumer ids
475
   *   regardless of it they were granted by this module.
476
   *
477
   * @param user object $user
478
   *
479
   * @return array of consumer ids such as array('3-2','7-2'), array('admin','user_admin')
480
   */
481
  public function usersAuthorizations(&$user) {
482
    // Method must be overridden.
483
  }
484

    
485
  /**
486
   * Put authorization ids in displayable format.
487
   */
488
  public function convertToFriendlyAuthorizationIds($authorizations) {
489
    return $authorizations;
490
  }
491

    
492
  /**
493
   * @param drupal user object $user
494
   *   to have $consumer_id granted.
495
   * @param string lower case $consumer_id
496
   *   $consumer_id such as drupal role name, og group name, etc.
497
   * @param mixed $consumer
498
   *   depends on type of consumer.  Drupal roles are strings, og groups are ??
499
   *
500
   *   return boolen TRUE on success, FALSE on fail.  If user save is FALSE, the user object will
501
   *   not be saved and reloaded, so a returned TRUE may be misleading.
502
   */
503
  public function createSingleAuthorization(&$user, $consumer_id, $consumer, &$user_auth_data) {
504
    // Method must be overridden.
505
  }
506

    
507
  /**
508
   * @param drupal user object $user
509
   * @param string lowercase $consumer_id
510
   *   such as drupal role name, og group name, etc.
511
   *
512
   * @return boolean if an ldap_authorization_* module granted the authorization id
513
   */
514
  public function hasLdapGrantedAuthorization(&$user, $consumer_id) {
515
    return (!empty($user->data['ldap_authorizations'][$this->consumerType][$consumer_id]));
516
  }
517

    
518
  /**
519
   * NOTE this is in mixed case, since we must rely on whatever module is storing
520
   * the authorization id.
521
   *
522
   * @param drupal user object $user
523
   * @param string lowercase case $consumer_id
524
   *   such as drupal role name, og group name, etc.
525
   *
526
   * @return param boolean is user has authorization id, regardless of what module granted it.
527
   */
528
  public function hasAuthorization(&$user, $consumer_id) {
529
    return @in_array($consumer_id, $this->usersAuthorizations($user));
530
  }
531

    
532
  /**
533
   * Validate authorization mappings on LDAP Authorization OG Admin form.
534
   *
535
   * @param array $mapping
536
   *   single mapping in format generated in normalizeMappings method.
537
   * @param array $form_values
538
   *   from authorization configuration form.
539
   * @param bool $clear_cache
540
   *
541
   * @return array of form array($message_type, $message_text) where message type is status, warning, or error
542
   *   and $message_text is what the user should see.
543
   */
544
  public function validateAuthorizationMappingTarget($mapping, $form_values = NULL, $clear_cache = FALSE) {
545
    $message_type = NULL;
546
    $message_text = NULL;
547
    return array($message_type, $message_text);
548
  }
549

    
550
}