ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilLDAPRoleGroupMapping.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
25{
26 private static ?ilLDAPRoleGroupMapping $instance = null;
27 private ilLogger $log;
30
31 private array $servers;
32 private array $mappings;
33 private array $mapping_members;
34 private array $mapping_info;
35 private array $mapping_info_strict;
36 private array $query;
37 private array $users;
38 private ?array $user_dns;
39 private bool $active_servers = false;
40
44 private function __construct()
45 {
46 global $DIC;
47
48 $this->log = $DIC->logger()->auth();
49 $this->rbacreview = $DIC->rbac()->review();
50 $this->ilObjDataCache = $DIC['ilObjDataCache'];
51
52 $this->initServers();
53 }
54
58 public static function _getInstance(): ?ilLDAPRoleGroupMapping
59 {
60 if (is_object(self::$instance)) {
61 return self::$instance;
62 }
63 return self::$instance = new ilLDAPRoleGroupMapping();
64 }
65
74 public function getInfoStrings(int $a_obj_id, bool $a_check_type = false): array
75 {
76 if (!$this->active_servers) {
77 return [];
78 }
79
80 if ($a_check_type) {
81 if (isset($this->mapping_info_strict[$a_obj_id]) && is_array($this->mapping_info_strict[$a_obj_id])) {
82 return $this->mapping_info_strict[$a_obj_id];
83 }
84 } elseif (isset($this->mapping_info[$a_obj_id]) && is_array($this->mapping_info[$a_obj_id])) {
85 return $this->mapping_info[$a_obj_id];
86 }
87
88 return [];
89 }
90
91
97 public function assign($a_role_id, $a_usr_id): bool
98 {
99 // return if there nothing to do
100 if (!$this->active_servers) {
101 return false;
102 }
103
104 if (!$this->isHandledRole($a_role_id)) {
105 return false;
106 }
107 if (!$this->isHandledUser($a_usr_id)) {
108 $this->log->write('LDAP assign: User ID: ' . $a_usr_id . ' has no LDAP account');
109 return false;
110 }
111 $this->log->write('LDAP assign: User ID: ' . $a_usr_id . ' Role Id: ' . $a_role_id);
112 $this->assignToGroup($a_role_id, $a_usr_id);
113
114 return true;
115 }
116
125 public function deleteRole(int $a_role_id): bool
126 {
127 // return if there nothing to do
128 if (!$this->active_servers) {
129 return false;
130 }
131
132 if (!$this->isHandledRole($a_role_id)) {
133 return false;
134 }
135
136 foreach ($this->rbacreview->assignedUsers($a_role_id) as $usr_id) {
137 $this->deassign($a_role_id, $usr_id);
138 }
139 return true;
140 }
141
142
148 public function deassign($a_role_id, $a_usr_id): bool
149 {
150 // return if there notzing to do
151 if (!$this->active_servers) {
152 return false;
153 }
154 if (!$this->isHandledRole($a_role_id)) {
155 return false;
156 }
157 if (!$this->isHandledUser($a_usr_id)) {
158 return false;
159 }
160 $this->log->write('LDAP deassign: User ID: ' . $a_usr_id . ' Role Id: ' . $a_role_id);
161 $this->deassignFromGroup($a_role_id, $a_usr_id);
162
163 return true;
164 }
165
171 public function deleteUser($a_usr_id): bool
172 {
173 if (!$this->active_servers) {
174 return false;
175 }
176
177 foreach ($this->mappings as $role_id) {
178 $this->deassign($role_id, $a_usr_id);
179 }
180 return true;
181 }
182
183
187 private function initServers(): void
188 {
190
191 if (!count($server_ids)) {
192 return;
193 }
194
195 // Init servers
196 $this->active_servers = true;
197 $this->servers = [];
198 $this->mappings = [];
199 foreach ($server_ids as $server_id) {
200 $this->servers[$server_id] = new ilLDAPServer($server_id);
201 $this->mappings = ilLDAPRoleGroupMappingSettings::_getAllActiveMappings();
202 }
203 $this->mapping_info = [];
204 $this->mapping_info_strict = [];
205 foreach ($this->mappings as $mapping) {
206 foreach ($mapping as $data) {
207 if ($data['info'] !== '' && $data['object_id']) {
208 $this->mapping_info[$data['object_id']][] = $data['info'];
209 }
210 if ($data['info'] !== '' && ($data['info_type'] === ilLDAPRoleGroupMappingSettings::MAPPING_INFO_ALL)) {
211 $this->mapping_info_strict[$data['object_id']][] = $data['info'];
212 }
213 }
214 }
215 $this->users = ilObjUser::_getExternalAccountsByAuthMode('ldap', true);
216 }
217
221 private function isHandledRole($a_role_id): bool
222 {
223 if (!is_string($a_role_id) || !is_int($a_role_id)) {
224 return false;
225 }
226
227 return array_key_exists($a_role_id, $this->mappings);
228 }
229
233 private function isHandledUser($a_usr_id): bool
234 {
235 return array_key_exists($a_usr_id, $this->users);
236 }
237
238
245 private function assignToGroup($a_role_id, $a_usr_id): void
246 {
247 foreach ($this->mappings[$a_role_id] as $data) {
248 try {
249 if ($data['isdn']) {
250 $external_account = $this->readDN($a_usr_id, $data['server_id']);
251 } else {
252 $external_account = $this->users[$a_usr_id];
253 }
254
255 // Forcing modAdd since Active directory is too slow and i cannot check if a user is member or not.
256 #if($this->isMember($external_account,$data))
257 #{
258 # $this->log->write("LDAP assign: User already assigned to group '".$data['dn']."'");
259 #}
260 #else
261 {
262 // Add user
263 $query_obj = $this->getLDAPQueryInstance($data['server_id'], $data['url']);
264 $query_obj->modAdd($data['dn'], array($data['member'] => $external_account));
265 $this->log->write('LDAP assign: Assigned ' . $external_account . ' to group ' . $data['dn']);
266 }
267 } catch (ilLDAPQueryException $exc) {
268 $this->log->write($exc->getMessage());
269 // try next mapping
270 continue;
271 }
272 }
273 }
274
282 private function deassignFromGroup($a_role_id, $a_usr_id): void
283 {
284 foreach ($this->mappings[$a_role_id] as $data) {
285 try {
286 if ($data['isdn']) {
287 $external_account = $this->readDN($a_usr_id, $data['server_id']);
288 } else {
289 $external_account = $this->users[$a_usr_id];
290 }
291
292 // Check for other role membership
293 if ($role_id = $this->checkOtherMembership($a_usr_id, $a_role_id, $data)) {
294 $this->log->write('LDAP deassign: User is still assigned to role "' . $role_id . '".');
295 continue;
296 }
297 /*
298 if(!$this->isMember($external_account,$data))
299 {
300 $this->log->write("LDAP deassign: User not assigned to group '".$data['dn']."'");
301 continue;
302 }
303 */
304 // Deassign user
305 $query_obj = $this->getLDAPQueryInstance($data['server_id'], $data['url']);
306 $query_obj->modDelete($data['dn'], array($data['member'] => $external_account));
307 $this->log->write('LDAP deassign: Deassigned ' . $external_account . ' from group ' . $data['dn']);
308
309 // Delete from cache
310 if (is_array($this->mapping_members[$data['mapping_id']])) {
311 $key = array_search($external_account, $this->mapping_members[$data['mapping_id']], true);
312 if ($key || $key === 0) {
313 unset($this->mapping_members[$data['mapping_id']]);
314 }
315 }
316 } catch (ilLDAPQueryException $exc) {
317 $this->log->write($exc->getMessage());
318 // try next mapping
319 continue;
320 }
321 }
322 }
323
330 private function checkOtherMembership(int $a_usr_id, int $a_role_id, array $a_data)
331 {
332 foreach ($this->mappings as $role_id => $tmp_data) {
333 foreach ($tmp_data as $data) {
334 if ($role_id === $a_role_id) {
335 continue;
336 }
337 if ($data['server_id'] !== $a_data['server_id']) {
338 continue;
339 }
340 if ($data['dn'] !== $a_data['dn']) {
341 continue;
342 }
343 if ($this->rbacreview->isAssigned($a_usr_id, $role_id)) {
344 return $this->ilObjDataCache->lookupTitle((int) $role_id);
345 }
346 }
347 }
348 return false;
349 }
350
358 private function readDN(int $a_usr_id, int $a_server_id)
359 {
360 if ($this->user_dns === null) {
361 $this->user_dns = [];
362 }
363 if (isset($this->user_dns[$a_usr_id])) {
364 return $this->user_dns[$a_usr_id];
365 }
366
367 $external_account = $this->users[$a_usr_id];
368
369 $server = $this->servers[$a_server_id];
370 $query_obj = $this->getLDAPQueryInstance($a_server_id, $server->getUrl());
371
372 if ($search_base = $server->getSearchBase()) {
373 $search_base .= ',';
374 }
375 $search_base .= $server->getBaseDN();
376
377 // try optional group user filter first
378 if ($server->isMembershipOptional() && $server->getGroupUserFilter()) {
379 $userFilter = $server->getGroupUserFilter();
380 } else {
381 $userFilter = $server->getFilter();
382 }
383
384 $filter = sprintf(
385 '(&(%s=%s)%s)',
386 $server->getUserAttribute(),
387 $external_account,
388 $userFilter
389 );
390
391 $res = $query_obj->query($search_base, $filter, $server->getUserScope(), array('dn'));
392
393 if (!$res->numRows()) {
394 throw new ilLDAPQueryException(__METHOD__ . ' cannot find dn for user ' . $external_account);
395 }
396 if ($res->numRows() > 1) {
397 throw new ilLDAPQueryException(__METHOD__ . ' found multiple distinguished name for: ' . $external_account);
398 }
399
400 $data = $res->get();
401 $this->user_dns[$a_usr_id] = $data['dn'];
402 return $this->user_dns[$a_usr_id];
403 }
404
410 private function getLDAPQueryInstance($a_server_id, $a_url)
411 {
412 if (array_key_exists($a_server_id, $this->query) &&
413 array_key_exists($a_url, $this->query[$a_server_id]) &&
414 is_object($this->query[$a_server_id][$a_url])) {
415 return $this->query[$a_server_id][$a_url];
416 }
417 $tmp_query = new ilLDAPQuery($this->servers[$a_server_id], $a_url);
418 $tmp_query->bind(ilLDAPQuery::LDAP_BIND_ADMIN);
419
420 return $this->query[$a_server_id][$a_url] = $tmp_query;
421 }
422}
checkOtherMembership(int $a_usr_id, int $a_role_id, array $a_data)
Check other membership.
readDN(int $a_usr_id, int $a_server_id)
Read DN of user.
initServers()
Check if there is any active server with.
getLDAPQueryInstance($a_server_id, $a_url)
Get LDAPQueryInstance.
assignToGroup($a_role_id, $a_usr_id)
Assign user to group.
deleteUser($a_usr_id)
Delete user => deassign from all ldap groups.
deassign($a_role_id, $a_usr_id)
This method is typically called from class RbacAdmin::deassignUser() It checks if there is a role map...
deleteRole(int $a_role_id)
Delete role.
static ilLDAPRoleGroupMapping $instance
assign($a_role_id, $a_usr_id)
This method is typically called from class RbacAdmin::assignUser() It checks if there is a role mappi...
isHandledUser($a_usr_id)
Check if user is ldap user.
static _getInstance()
Get singleton instance of this class.
__construct()
Singleton contructor.
getInfoStrings(int $a_obj_id, bool $a_check_type=false)
Get info string for object If check info type is enabled this function will check if the info string ...
deassignFromGroup($a_role_id, $a_usr_id)
Deassign user from group.
static _getRoleSyncServerIds()
Check whether there if there is an active server with option role_sync_active.
Component logger with individual log levels by component id.
static _getExternalAccountsByAuthMode(string $a_auth_mode, bool $a_read_auth_default=false)
Get list of external account by authentication method Note: If login == ext_account for two user with...
class ilObjectDataCache
class ilRbacReview Contains Review functions of core Rbac.
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26
$server
Definition: shib_login.php:28