1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Cron relate functions.
|
6
|
*/
|
7
|
|
8
|
/**
|
9
|
* Function to respond to ldap associated drupal accounts which no
|
10
|
* longer have a related LDAP entry.
|
11
|
*
|
12
|
* @param LdapUserConf $ldap_user_conf
|
13
|
*
|
14
|
* @return boolean FALSE on error or incompletion or TRUE otherwise
|
15
|
*/
|
16
|
function _ldap_user_orphans($ldap_user_conf) {
|
17
|
if (!$ldap_user_conf->orphanedDrupalAcctBehavior ||
|
18
|
$ldap_user_conf->orphanedDrupalAcctBehavior == 'ldap_user_orphan_do_not_check') {
|
19
|
return TRUE;
|
20
|
}
|
21
|
|
22
|
/**
|
23
|
* query drupal accounts
|
24
|
* - ldap associated drupal accounts
|
25
|
* - where (ldap_user_current_dn not null)
|
26
|
* - ordered by ldap_user_last_checked
|
27
|
* - order by uid asc (get oldest first)
|
28
|
*/
|
29
|
|
30
|
$last_uid_checked = variable_get('ldap_user_cron_last_uid_checked', 1);
|
31
|
|
32
|
$query = new EntityFieldQuery();
|
33
|
$query->entityCondition('entity_type', 'user')
|
34
|
->fieldCondition('ldap_user_puid_sid', 'value', 'NULL', '!=')
|
35
|
->fieldCondition('ldap_user_puid_property', 'value', 'NULL', '!=')
|
36
|
->fieldCondition('ldap_user_puid', 'value', 'NULL', '!=')
|
37
|
->fieldCondition('ldap_user_current_dn', 'value', 'NULL', '!=')
|
38
|
->propertyCondition('uid', $last_uid_checked, '>')
|
39
|
->propertyCondition('status', 1)
|
40
|
->propertyOrderBy('uid', 'ASC')
|
41
|
->range(0, $ldap_user_conf->orphanedCheckQty)
|
42
|
// Run the query as user 1.
|
43
|
->addMetaData('account', user_load(1));
|
44
|
$result = $query->execute();
|
45
|
|
46
|
$email_list = [];
|
47
|
$ldap_servers = ldap_servers_get_servers(NULL, 'enabled');
|
48
|
$watchdogs_sids_missing_watchdogged = [];
|
49
|
/**
|
50
|
* First produce array of form:
|
51
|
* $drupal_users[$sid][$puid_attr][$puid]['exists'] = bool
|
52
|
* signifying if corresponding LDAP Entry exists.
|
53
|
*/
|
54
|
if (!(isset($result['user']) && count($result['user']) > 0)) {
|
55
|
variable_set('ldap_user_cron_last_uid_checked', 1);
|
56
|
return TRUE;
|
57
|
}
|
58
|
|
59
|
$uids = array_keys($result['user']);
|
60
|
$user_count = count($uids);
|
61
|
|
62
|
// If maxed out reset uid check counter.
|
63
|
if ($user_count < $ldap_user_conf->orphanedCheckQty) {
|
64
|
variable_set('ldap_user_cron_last_uid_checked', 1);
|
65
|
}
|
66
|
else {
|
67
|
variable_set('ldap_user_cron_last_uid_checked', $uids[count($uids) - 1]);
|
68
|
}
|
69
|
|
70
|
$batches = floor($user_count / LDAP_SERVERS_MAXFILTER_ORS) + 1;
|
71
|
// e.g. 175 users and 50 max ldap query ors will yield 4 batches.
|
72
|
for ($batch = 1; $batch <= $batches; $batch++) {
|
73
|
$email_list = _ldap_user_orphan_process_batch($ldap_user_conf, $batch, $user_count, $uids, $ldap_servers, $watchdogs_sids_missing_watchdogged, $query, $email_list);
|
74
|
}
|
75
|
|
76
|
if (count($email_list) > 0) {
|
77
|
$site_email = variable_get('site_mail', FALSE);
|
78
|
$params = ['accounts' => $email_list];
|
79
|
if ($site_email) {
|
80
|
drupal_mail(
|
81
|
'ldap_user',
|
82
|
'orphaned_accounts',
|
83
|
$site_email,
|
84
|
language_default(),
|
85
|
$params
|
86
|
);
|
87
|
}
|
88
|
}
|
89
|
|
90
|
return TRUE;
|
91
|
}
|
92
|
|
93
|
/**
|
94
|
* @param $ldap_user_conf
|
95
|
* @param $batch
|
96
|
* @param $user_count
|
97
|
* @param $uids
|
98
|
* @param $ldap_servers
|
99
|
* @param $watchdogs_sids_missing_watchdogged
|
100
|
* @param $query
|
101
|
* @param $email_list
|
102
|
*
|
103
|
* @return array
|
104
|
* @throws \Exception
|
105
|
*/
|
106
|
function _ldap_user_orphan_process_batch($ldap_user_conf, $batch, $user_count, $uids, $ldap_servers, $watchdogs_sids_missing_watchdogged, $query, $email_list) {
|
107
|
$filters = [];
|
108
|
$drupal_users = [];
|
109
|
/**
|
110
|
* 1. populate $drupal_users[$sid][$puid_attr][$puid]['exists'] = TRUE
|
111
|
*
|
112
|
* e.g. first batch $i=0; $i<50; $i++
|
113
|
* 2nd batch $i=50; $i<100; $i++
|
114
|
* 4th batch $i=150; $i<175; $i++
|
115
|
*/
|
116
|
// e.g 0, 50, 100.
|
117
|
$start = ($batch - 1) * LDAP_SERVERS_MAXFILTER_ORS;
|
118
|
// e.g. 50, 100, 150.
|
119
|
$end_plus_1 = min(($batch) * LDAP_SERVERS_MAXFILTER_ORS, $user_count);
|
120
|
// e.g. 50, 50; 100, 50.
|
121
|
$batch_uids = array_slice($uids, $start, ($end_plus_1 - $start));
|
122
|
$accounts = entity_load('user', $batch_uids);
|
123
|
|
124
|
foreach ($accounts as $uid => $user) {
|
125
|
$sid = @$user->ldap_user_puid_sid[LANGUAGE_NONE][0]['value'];
|
126
|
$puid = @$user->ldap_user_puid[LANGUAGE_NONE][0]['value'];
|
127
|
$puid_attr = @$user->ldap_user_puid_property[LANGUAGE_NONE][0]['value'];
|
128
|
if ($sid && $puid && $puid_attr) {
|
129
|
if ($ldap_servers[$sid]->unique_persistent_attr_binary) {
|
130
|
$filters[$sid][$puid_attr][] = "($puid_attr=" . ldap_servers_binary_filter($puid) . ")";
|
131
|
}
|
132
|
else {
|
133
|
$filters[$sid][$puid_attr][] = "($puid_attr=$puid)";
|
134
|
}
|
135
|
$drupal_users[$sid][$puid_attr][$puid]['uid'] = $uid;
|
136
|
$drupal_users[$sid][$puid_attr][$puid]['exists'] = FALSE;
|
137
|
}
|
138
|
else {
|
139
|
// User with missing ldap data fields
|
140
|
// perhaps should be watchdogged?
|
141
|
}
|
142
|
}
|
143
|
|
144
|
// 2. set $drupal_users[$sid][$puid_attr][$puid]['exists'] to FALSE
|
145
|
// if entry doesn't exist.
|
146
|
foreach ($filters as $sid => $puid_attrs) {
|
147
|
if (!isset($ldap_servers[$sid])) {
|
148
|
if (!isset($watchdogs_sids_missing_watchdogged[$sid])) {
|
149
|
watchdog(
|
150
|
'ldap_user',
|
151
|
'Server %sid not enabled, but needed to remove orphaned ldap users',
|
152
|
['%sid' => $sid],
|
153
|
WATCHDOG_ERROR
|
154
|
);
|
155
|
$watchdogs_sids_missing_watchdogged[$sid] = TRUE;
|
156
|
}
|
157
|
continue;
|
158
|
}
|
159
|
foreach ($puid_attrs as $puid_attr => $ors) {
|
160
|
// Query should look like (|(guid=3243243)(guid=3243243)(guid=3243243))
|
161
|
$ldap_filter = '(|' . join("", $ors) . ')';
|
162
|
$ldap_entries = $ldap_servers[$sid]->searchAllBaseDns($ldap_filter, [$puid_attr]);
|
163
|
if ($ldap_entries === FALSE) {
|
164
|
// If query has error, don't remove ldap entries!
|
165
|
unset($drupal_users[$sid]);
|
166
|
watchdog(
|
167
|
'ldap_user',
|
168
|
'ldap server %sid had error while querying to
|
169
|
deal with orphaned ldap user entries. Please check that the ldap
|
170
|
server is configured correctly. Query; %query',
|
171
|
['%sid' => $sid, '%query' => serialize($query)],
|
172
|
WATCHDOG_ERROR);
|
173
|
continue;
|
174
|
}
|
175
|
|
176
|
unset($ldap_entries['count']);
|
177
|
|
178
|
foreach ($ldap_entries as $i => $ldap_entry) {
|
179
|
$puid = $ldap_servers[$sid]->userPuidFromLdapEntry($ldap_entry);
|
180
|
$drupal_users[$sid][$puid_attr][$puid]['exists'] = TRUE;
|
181
|
}
|
182
|
}
|
183
|
}
|
184
|
// 3. we now have $drupal_users[$sid][$puid_attr][$puid]['exists'] = bool.
|
185
|
global $base_url;
|
186
|
foreach ($drupal_users as $sid => $puid_x_puid_attrs) {
|
187
|
foreach ($puid_x_puid_attrs as $puid_attr => $puids) {
|
188
|
foreach ($puids as $puid => $user_data) {
|
189
|
|
190
|
if ($account = $accounts[$user_data['uid']]) {
|
191
|
$user_edit = [];
|
192
|
$user_edit['ldap_user_last_checked'][LANGUAGE_NONE][0]['value'] = time();
|
193
|
$account = user_save($account, $user_edit, 'ldap_user');
|
194
|
if (!$user_data['exists']) {
|
195
|
/**
|
196
|
* $ldap_user_conf->orphanedDrupalAcctBehavior will either be
|
197
|
* 'ldap_user_orphan_email' or one of the user module options:
|
198
|
* user_cancel_block, user_cancel_block_unpublish,
|
199
|
* user_cancel_reassign, user_cancel_delete
|
200
|
*/
|
201
|
if ($ldap_user_conf->orphanedDrupalAcctBehavior == 'ldap_user_orphan_email') {
|
202
|
$email_list[] = $account->name . "," . $account->mail . "," . $base_url . "/user/" . $account->uid . "/edit";
|
203
|
}
|
204
|
else {
|
205
|
_user_cancel([], $account, $ldap_user_conf->orphanedDrupalAcctBehavior);
|
206
|
}
|
207
|
}
|
208
|
}
|
209
|
}
|
210
|
}
|
211
|
}
|
212
|
return $email_list;
|
213
|
}
|