ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilLDAPRoleAssignmentRule.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
26{
27 public const TYPE_GROUP = 1;
28 public const TYPE_ATTRIBUTE = 2;
29 public const TYPE_PLUGIN = 3;
30
31 private static array $instances = [];
32
37
38 private int $rule_id;
39
40 private int $server_id = 0;
41 private bool $add_on_update = false;
42 private bool $remove_on_update = false;
43 private int $plugin_id = 0;
44 private string $attribute_value = '';
45 private string $attribute_name = '';
46 private bool $member_is_dn = false;
47 private string $member_attribute = '';
48 private string $dn = '';
49 private int $type = 0;
50 private int $role_id = 0;
51
52 private function __construct(int $a_rule_id = 0)
53 {
54 global $DIC;
55 $this->db = $DIC->database();
56 $this->logger = $DIC->logger()->auth();
57 $this->ilErr = $DIC['ilErr'];
58 $this->lng = $DIC->language();
59
60 $this->rule_id = $a_rule_id;
61 $this->read();
62 }
63
64 public static function _getInstanceByRuleId(int $a_rule_id): ilLDAPRoleAssignmentRule
65 {
66 return self::$instances[$a_rule_id] ?? (self::$instances[$a_rule_id] = new ilLDAPRoleAssignmentRule($a_rule_id));
67 }
68
72 public static function hasRulesForUpdate(): bool
73 {
74 global $DIC;
75
76 $ilDB = $DIC['ilDB'];
77
78 $query = 'SELECT COUNT(*) num FROM ldap_role_assignments ' .
79 'WHERE add_on_update = 1 ' .
80 'OR remove_on_update = 1 ';
81 $res = $ilDB->query($query);
82 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
83
84 return $row->num > 0;
85 }
86
90 public function matches(array $a_user_data): bool
91 {
92 switch ($this->getType()) {
94 return ilLDAPRoleAssignmentRules::callPlugin($this->getPluginId(), $a_user_data);
95
97
98 $attn = strtolower($this->getAttributeName());
99
100 if (!isset($a_user_data[$attn])) {
101 return false;
102 }
103
104 if (!is_array($a_user_data[$attn])) {
105 $attribute_val = array(0 => $a_user_data[$attn]);
106 } else {
107 $attribute_val = $a_user_data[$attn];
108 }
109
110 foreach ($attribute_val as $value) {
111 if ($this->wildcardCompare(trim($this->getAttributeValue()), trim($value))) {
112 $this->logger->debug(': Found role mapping: ' . ilObject::_lookupTitle($this->getRoleId()));
113 return true;
114 }
115 }
116 return false;
117
118 case self::TYPE_GROUP:
119 return $this->isGroupMember($a_user_data);
120 }
121
122 return false;
123 }
124
125 protected function wildcardCompare(string $a_str1, string $a_str2): bool
126 {
127 $pattern = str_replace('*', '.*?', $a_str1);
128
129 $exception = [];
130 foreach (ilAuthUtils::REGEX_DELIMITERS as $delimiter) {
131 $this->logger->debug('Trying pattern to match attribute value:' . $pattern . ' => ' . $a_str2);
132
133 set_error_handler(static function (int $severity, string $message, string $file, int $line): never {
134 throw new ErrorException($message, $severity, $severity, $file, $line);
135 });
136
137 $regex = $delimiter . "^" . $pattern . '$' . $delimiter . 'i';
138 try {
139 return preg_match($regex, $a_str2) === 1;
140 } catch (Exception $e) {
141 $exception[] = 'RegEx: ' . $regex . ' -> Message: ' . $e->getMessage();
142 } finally {
143 restore_error_handler();
144 }
145 }
146
147 if ($exception !== []) {
148 $this->logger->warning('Trying the RegEx delimiter chain results in the following problems: ' . implode(', ', $exception));
149 }
150
151 return false;
152 }
153
154
161 private function isGroupMember(array $a_user_data): bool
162 {
164
165 if ($this->isMemberAttributeDN()) {
166 if ($server->enabledEscapeDN()) {
167 $user_cmp = ldap_escape($a_user_data['dn'], "", LDAP_ESCAPE_FILTER);
168 } else {
169 $user_cmp = $a_user_data['dn'];
170 }
171 } else {
172 $user_cmp = $a_user_data['ilExternalAccount'];
173 }
174
175 try {
176 $query = new ilLDAPQuery($server);
177 $query->bind();
178 $res = $query->query(
179 $this->getDN(),
180 sprintf(
181 '(%s=%s)',
182 $this->getMemberAttribute(),
183 $user_cmp
184 ),
186 array('dn')
187 );
188 return (bool) $res->numRows();
189 } catch (ilLDAPQueryException $e) {
190 $this->logger->warning(': Caught Exception: ' . $e->getMessage());
191 return false;
192 }
193 }
194
195
196
202 public static function _getRules($a_server_id): array
203 {
204 global $DIC;
205 $ilDB = $DIC->database();
206
207 $rules = [];
208
209 $query = "SELECT rule_id FROM ldap_role_assignments " .
210 "WHERE server_id = " . $ilDB->quote($a_server_id, 'integer');
211 $res = $ilDB->query($query);
212 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
213 $rules[] = self::_getInstanceByRuleId((int) $row->rule_id);
214 }
215
216 return $rules;
217 }
218
224 public function setRoleId(int $a_role_id): void
225 {
226 $this->role_id = $a_role_id;
227 }
228
232 public function getRoleId(): int
233 {
234 return $this->role_id;
235 }
236
240 public function getRuleId(): int
241 {
242 return $this->rule_id;
243 }
244
248 public function setServerId(int $a_id): void
249 {
250 $this->server_id = $a_id;
251 }
252
256 public function getServerId(): int
257 {
258 return $this->server_id;
259 }
260
264 public function setType(int $a_type): void
265 {
266 $this->type = $a_type;
267 }
268
272 public function getType(): int
273 {
274 return $this->type;
275 }
276
280 public function setDN(string $a_dn): void
281 {
282 $this->dn = $a_dn;
283 }
284
288 public function getDN(): string
289 {
290 return $this->dn;
291 }
292
293 public function setMemberAttribute(string $a_attribute): void
294 {
295 $this->member_attribute = $a_attribute;
296 }
297
301 public function getMemberAttribute(): string
302 {
304 }
305
309 public function setMemberIsDN(bool $a_status): void
310 {
311 $this->member_is_dn = $a_status;
312 }
313
317 public function isMemberAttributeDN(): bool
318 {
319 return $this->member_is_dn;
320 }
321
325 public function setAttributeName(string $a_name): void
326 {
327 $this->attribute_name = $a_name;
328 }
329
333 public function getAttributeName(): string
334 {
336 }
337
341 public function setAttributeValue(string $a_value): void
342 {
343 $this->attribute_value = $a_value;
344 }
345
349 public function getAttributeValue(): string
350 {
352 }
353
354 public function enableAddOnUpdate(bool $a_status): void
355 {
356 $this->add_on_update = $a_status;
357 }
358
359 public function isAddOnUpdateEnabled(): bool
360 {
362 }
363
364 public function enableRemoveOnUpdate(bool $a_status): void
365 {
366 $this->remove_on_update = $a_status;
367 }
368
369 public function isRemoveOnUpdateEnabled(): bool
370 {
372 }
373
374 public function setPluginId(int $a_id): void
375 {
376 $this->plugin_id = $a_id;
377 }
378
379 public function getPluginId(): int
380 {
381 return $this->plugin_id;
382 }
383
384 public function isPluginActive(): bool
385 {
386 return $this->getType() === self::TYPE_PLUGIN;
387 }
388
389 public function conditionToString(): string
390 {
391 switch ($this->getType()) {
393 return $this->lng->txt('ldap_plugin_id') . ': ' . $this->getPluginId();
394
395 case self::TYPE_GROUP:
396 $dn_arr = explode(',', $this->getDN());
397 return $dn_arr[0];
398
400 return $this->getAttributeName() . '=' . $this->getAttributeValue();
401
402 default:
403 throw new RuntimeException(sprintf('Unknown type: %s', var_export($this->getType(), true)));
404 }
405 }
406
407 public function create(): bool
408 {
409 $next_id = $this->db->nextId('ldap_role_assignments');
410
411 $query = "INSERT INTO ldap_role_assignments (server_id,rule_id,type,dn,attribute,isdn,att_name,att_value,role_id, " .
412 "add_on_update, remove_on_update, plugin_id ) " .
413 "VALUES( " .
414 $this->db->quote($this->getServerId(), 'integer') . ", " .
415 $this->db->quote($next_id, 'integer') . ", " .
416 $this->db->quote($this->getType(), 'integer') . ", " .
417 $this->db->quote($this->getDN(), 'text') . ", " .
418 $this->db->quote($this->getMemberAttribute(), 'text') . ", " .
419 $this->db->quote($this->isMemberAttributeDN(), 'integer') . ", " .
420 $this->db->quote($this->getAttributeName(), 'text') . ", " .
421 $this->db->quote($this->getAttributeValue(), 'text') . ", " .
422 $this->db->quote($this->getRoleId(), 'integer') . ", " .
423 $this->db->quote($this->isAddOnUpdateEnabled(), 'integer') . ', ' .
424 $this->db->quote($this->isRemoveOnUpdateEnabled(), 'integer') . ', ' .
425 $this->db->quote($this->getPluginId(), 'integer') . ' ' .
426 ")";
427 $this->db->manipulate($query);
428 $this->rule_id = $next_id;
429
430 return true;
431 }
432
433 public function update(): bool
434 {
435 $query = "UPDATE ldap_role_assignments " .
436 "SET server_id = " . $this->db->quote($this->getServerId(), 'integer') . ", " .
437 "type = " . $this->db->quote($this->getType(), 'integer') . ", " .
438 "dn = " . $this->db->quote($this->getDN(), 'text') . ", " .
439 "attribute = " . $this->db->quote($this->getMemberAttribute(), 'text') . ", " .
440 "isdn = " . $this->db->quote($this->isMemberAttributeDN(), 'integer') . ", " .
441 "att_name = " . $this->db->quote($this->getAttributeName(), 'text') . ", " .
442 "att_value = " . $this->db->quote($this->getAttributeValue(), 'text') . ", " .
443 "role_id = " . $this->db->quote($this->getRoleId(), 'integer') . ", " .
444 "add_on_update = " . $this->db->quote($this->isAddOnUpdateEnabled(), 'integer') . ', ' .
445 'remove_on_update = ' . $this->db->quote($this->isRemoveOnUpdateEnabled(), 'integer') . ', ' .
446 'plugin_id = ' . $this->db->quote($this->getPluginId(), 'integer') . ' ' .
447 "WHERE rule_id = " . $this->db->quote($this->getRuleId(), 'integer') . " ";
448 $this->db->manipulate($query);
449
450 return true;
451 }
452
453 public function validate(): bool
454 {
455 $this->ilErr->setMessage('');
456
457 if (!$this->getRoleId()) {
458 $this->ilErr->setMessage('fill_out_all_required_fields');
459 return false;
460 }
461 switch ($this->getType()) {
462 case self::TYPE_GROUP:
463 if ($this->getDN() === '' || $this->getMemberAttribute() === '') {
464 $this->ilErr->setMessage('fill_out_all_required_fields');
465 return false;
466 }
467 break;
469 if ($this->getAttributeName() === '' || $this->getAttributeValue() === '') {
470 $this->ilErr->setMessage('fill_out_all_required_fields');
471 return false;
472 }
473 break;
474
476 if (!$this->getPluginId()) {
477 $this->ilErr->setMessage('ldap_err_missing_plugin_id');
478 return false;
479 }
480 break;
481
482 default:
483 $this->ilErr->setMessage('ldap_no_type_given');
484 return false;
485 }
486
487 return true;
488 }
489
490 public function delete(): bool
491 {
492 $query = "DELETE FROM ldap_role_assignments " .
493 "WHERE rule_id = " . $this->db->quote($this->getRuleId(), 'integer') . " ";
494 $this->db->manipulate($query);
495
496 return true;
497 }
498
499 private function read(): void
500 {
501 $query = "SELECT * FROM ldap_role_assignments " .
502 "WHERE rule_id = " . $this->db->quote($this->getRuleId(), 'integer') . " ";
503
504 $res = $this->db->query($query);
505 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
506 $this->setServerId((int) $row->server_id);
507 $this->setType((int) $row->type);
508 if (!is_null($row->dn)) {
509 $this->setDN($row->dn);
510 }
511 if (!is_null($row->attribute)) {
512 $this->setMemberAttribute($row->attribute);
513 }
514 $this->setMemberIsDN((bool) $row->isdn);
515 if (!is_null($row->att_name)) {
516 $this->setAttributeName($row->att_name);
517 }
518 if (!is_null($row->att_value)) {
519 $this->setAttributeValue($row->att_value);
520 }
521 $this->setRoleId((int) $row->role_id);
522 if (!is_null($row->add_on_update)) {
523 $this->enableAddOnUpdate((bool) $row->add_on_update);
524 }
525 if (!is_null($row->remove_on_update)) {
526 $this->enableRemoveOnUpdate((bool) $row->remove_on_update);
527 }
528 if (!is_null($row->plugin_id)) {
529 $this->setPluginId((int) $row->plugin_id);
530 }
531 }
532 }
533}
const array REGEX_DELIMITERS
Error Handling & global info handling.
static _getRules($a_server_id)
Get all rules.
isGroupMember(array $a_user_data)
Check if user is member of specific group.
setAttributeName(string $a_name)
set attribute name
isMemberAttributeDN()
is member attribute dn
static hasRulesForUpdate()
Check if there any rule for updates.
wildcardCompare(string $a_str1, string $a_str2)
setMemberIsDN(bool $a_status)
set member attribute is dn
setAttributeValue(string $a_value)
set attribute value
setRoleId(int $a_role_id)
set role id
matches(array $a_user_data)
Check if a rule matches.
static _getInstanceByRuleId(int $a_rule_id)
static callPlugin(int $a_plugin_id, array $a_user_data)
Call plugin check if the condition matches.
static getInstanceByServerId(int $a_server_id)
Get instance by server id.
language handling
Component logger with individual log levels by component id.
static _lookupTitle(int $obj_id)
Interface ilDBInterface.
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26
$server
Definition: shib_login.php:28
$message
Definition: xapiexit.php:31