ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ilOpenIdConnectUserSync Class Reference
+ Collaboration diagram for ilOpenIdConnectUserSync:

Public Member Functions

 __construct (private readonly ilOpenIdConnectSettings $settings, private readonly stdClass $user_info)
 
 setExternalAccount (string $ext_account)
 
 setInternalAccount (string $int_account)
 
 getUserId ()
 
 needsCreation ()
 
 updateUser ()
 

Data Fields

const AUTH_MODE = 'oidc'
 

Protected Member Functions

 parseRoleAssignments ()
 

Private Member Functions

 transformToXml ()
 
 valueFrom (string $connect_name)
 

Private Attributes

const UDF_STRING = 'udf_'
 
readonly ilLogger $logger
 
readonly Language $lng
 
readonly ilXmlWriter $writer
 
string $ext_account = ''
 
string $int_account = ''
 
int $usr_id = 0
 
array $user_defined_fields
 

Detailed Description

Definition at line 24 of file class.ilOpenIdConnectUserSync.php.

Constructor & Destructor Documentation

◆ __construct()

ilOpenIdConnectUserSync::__construct ( private readonly ilOpenIdConnectSettings  $settings,
private readonly stdClass  $user_info 
)

Definition at line 40 of file class.ilOpenIdConnectUserSync.php.

43 {
44 global $DIC;
45
46 $this->logger = $DIC->logger()->auth();
47 $this->lng = $DIC->language();
48 $this->writer = new ilXmlWriter();
49 $this->user_defined_fields = $DIC['user']->getProfile()->getAllUserDefinedFields();
50 }
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: shib_login.php:26

References $DIC, ILIAS\Repository\lng(), and ILIAS\Repository\logger().

+ Here is the call graph for this function:

Member Function Documentation

◆ getUserId()

ilOpenIdConnectUserSync::getUserId ( )

Definition at line 63 of file class.ilOpenIdConnectUserSync.php.

63 : int
64 {
65 return $this->usr_id;
66 }

References $usr_id.

Referenced by transformToXml().

+ Here is the caller graph for this function:

◆ needsCreation()

ilOpenIdConnectUserSync::needsCreation ( )

Definition at line 68 of file class.ilOpenIdConnectUserSync.php.

68 : bool
69 {
70 $this->logger->dump($this->int_account, ilLogLevel::DEBUG);
71
72 return $this->int_account === '';
73 }

References ilLogLevel\DEBUG, and ILIAS\Repository\logger().

Referenced by parseRoleAssignments(), transformToXml(), and updateUser().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parseRoleAssignments()

ilOpenIdConnectUserSync::parseRoleAssignments ( )
protected
Returns
array<int, int> Map of role assignments, where the key equals the respetive value

Definition at line 289 of file class.ilOpenIdConnectUserSync.php.

289 : array
290 {
291 $this->logger->debug('Parsing role assignments');
292
293 $found_role = false;
294
295 $roles_assignable[$this->settings->getRole()] = $this->settings->getRole();
296
297 $this->logger->dump($this->settings->getRoleMappings(), ilLogLevel::DEBUG);
298
299 foreach ($this->settings->getRoleMappings() as $role_id => $role_info) {
300 $this->logger->dump($role_id, ilLogLevel::DEBUG);
301 $this->logger->dump($role_info, ilLogLevel::DEBUG);
302
303 if ($role_info['value'] === '') {
304 $this->logger->debug('No role mapping for role: ' . $role_id);
305 continue;
306 }
307
308 [$role_attribute, $role_value] = array_map(trim(...), explode('::', $role_info['value']));
309
310 if (!$role_attribute || !$role_value) {
311 $this->logger->debug('No valid role mapping configuration for: ' . $role_id);
312 continue;
313 }
314
315 if (!isset($this->user_info->{$role_attribute})) {
316 $this->logger->debug('No user info passed');
317 continue;
318 }
319
320 if (!$role_info['update'] && !$this->needsCreation()) {
321 $this->logger->debug('No user role update for role: ' . $role_id);
322 continue;
323 }
324
325 if (is_array($this->user_info->{$role_attribute})) {
326 $roles_claim = array_map(
327 static function (mixed $value): string {
328 return match (true) {
329 is_string($value) => trim($value),
330 $value instanceof stdClass && property_exists($value, 'id') => trim((string) $value->id),
331 $value instanceof stdClass && property_exists($value, 'value') => trim((string) $value->value),
332 default => throw new DomainException(sprintf(
333 'Unexpected role value type, please check your provider configuration: %s',
334 print_r($value, true)
335 )),
336 };
337 },
338 $this->user_info->{$role_attribute}
339 );
340 if (!in_array($role_value, $roles_claim, true)) {
341 $this->logger->debug('User account has no ' . $role_value);
342 continue;
343 }
344 } elseif (strcmp(trim((string) $this->user_info->{$role_attribute}), $role_value) !== 0) {
345 $this->logger->debug('User account has no ' . $role_value);
346 continue;
347 }
348
349 $this->logger->debug('Matching role mapping for role_id: ' . $role_id);
350
351 $found_role = true;
352 $roles_assignable[(int) $role_id] = (int) $role_id;
353 $long_role_id = ('il_' . IL_INST_ID . '_role_' . $role_id);
354
355 $this->writer->xmlElement(
356 'Role',
357 [
358 'Id' => $long_role_id,
359 'Type' => 'Global',
360 'Action' => 'Assign'
361 ],
362 null
363 );
364 }
365
366 if (!$found_role && $this->needsCreation()) {
367 $long_role_id = ('il_' . IL_INST_ID . '_role_' . $this->settings->getRole());
368
369 $this->writer->xmlElement(
370 'Role',
371 [
372 'Id' => $long_role_id,
373 'Type' => 'Global',
374 'Action' => 'Assign'
375 ],
376 null
377 );
378 }
379
380 return $roles_assignable;
381 }
const IL_INST_ID
Definition: constants.php:40

References ilLogLevel\DEBUG, ILIAS\Repository\logger(), needsCreation(), and ILIAS\Repository\settings().

Referenced by transformToXml(), and updateUser().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setExternalAccount()

ilOpenIdConnectUserSync::setExternalAccount ( string  $ext_account)

Definition at line 52 of file class.ilOpenIdConnectUserSync.php.

52 : void
53 {
54 $this->ext_account = $ext_account;
55 }

References $ext_account.

◆ setInternalAccount()

ilOpenIdConnectUserSync::setInternalAccount ( string  $int_account)

Definition at line 57 of file class.ilOpenIdConnectUserSync.php.

57 : void
58 {
59 $this->int_account = $int_account;
60 $this->usr_id = (int) ilObjUser::_lookupId($this->int_account);
61 }
static _lookupId(string|array $a_user_str)

References $int_account, ilObjUser\_lookupId(), and ILIAS\Repository\int().

Referenced by updateUser().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformToXml()

ilOpenIdConnectUserSync::transformToXml ( )
private

Definition at line 103 of file class.ilOpenIdConnectUserSync.php.

103 : void
104 {
105 $this->writer->xmlStartTag('Users');
106
107 if ($this->needsCreation()) {
108 $this->writer->xmlStartTag('User', ['Action' => 'Insert']);
109 $this->writer->xmlElement('Login', [], ilAuthUtils::_generateLogin($this->ext_account));
110 } else {
111 $this->writer->xmlStartTag(
112 'User',
113 [
114 'Id' => $this->getUserId(),
115 'Action' => 'Update'
116 ]
117 );
118 $this->writer->xmlElement('Login', [], $this->int_account);
119 }
120
121 $this->writer->xmlElement('ExternalAccount', [], $this->ext_account);
122 $this->writer->xmlElement('AuthMode', ['type' => self::AUTH_MODE], null);
123
124 $this->parseRoleAssignments();
125
126 if ($this->needsCreation()) {
127 $this->writer->xmlElement('Active', [], 'true');
128 $this->writer->xmlElement('TimeLimitOwner', [], 7);
129 $this->writer->xmlElement('TimeLimitUnlimited', [], 1);
130 $this->writer->xmlElement('TimeLimitFrom', [], time());
131 $this->writer->xmlElement('TimeLimitUntil', [], time());
132 }
133
134 $profile_fields = $this->settings->getProfileMappingFields();
135
136 $udf_fields = [];
137 foreach ($this->user_defined_fields as $field) {
138 $field = self::UDF_STRING . $field->getIdentifier();
139 $udf_fields[$field] = $field;
140 }
141
142 $profile_and_udf_fields = $profile_fields + $udf_fields;
143 foreach ($profile_and_udf_fields as $field => $lng_key) {
144 $connect_name = $this->settings->getProfileMappingFieldValue($field);
145 if (!$connect_name) {
146 $this->logger->debug('Ignoring unconfigured field: ' . $field);
147 continue;
148 }
149 if (!$this->needsCreation() && !$this->settings->getProfileMappingFieldUpdate($field)) {
150 $this->logger->debug('Ignoring ' . $field . ' for update.');
151 continue;
152 }
153
154 $value = $this->valueFrom($connect_name);
155 if ($value === '') {
156 $this->logger->debug('Cannot find user data in ' . $connect_name);
157 continue;
158 }
159
160 switch ($field) {
161 case 'gender':
162 switch (strtolower($value)) {
163 case 'm':
164 case 'male':
165 $this->writer->xmlElement('Gender', [], 'm');
166 break;
167
168 case 'f':
169 case 'female':
170 $this->writer->xmlElement('Gender', [], 'f');
171 break;
172
173 default:
174 // use the default for anything that is not clearly m or f
175 $this->writer->xmlElement('Gender', [], 'n');
176 break;
177 }
178 break;
179
180 case 'firstname':
181 $this->writer->xmlElement('Firstname', [], $value);
182 break;
183
184 case 'lastname':
185 $this->writer->xmlElement('Lastname', [], $value);
186 break;
187
188 case 'hobby':
189 $this->writer->xmlElement('Hobby', [], $value);
190 break;
191
192 case 'title':
193 $this->writer->xmlElement('Title', [], $value);
194 break;
195
196 case 'institution':
197 $this->writer->xmlElement('Institution', [], $value);
198 break;
199
200 case 'department':
201 $this->writer->xmlElement('Department', [], $value);
202 break;
203
204 case 'street':
205 $this->writer->xmlElement('Street', [], $value);
206 break;
207
208 case 'city':
209 $this->writer->xmlElement('City', [], $value);
210 break;
211
212 case 'zipcode':
213 $this->writer->xmlElement('PostalCode', [], $value);
214 break;
215
216 case 'country':
217 $this->writer->xmlElement('Country', [], $value);
218 break;
219
220 case 'phone_office':
221 $this->writer->xmlElement('PhoneOffice', [], $value);
222 break;
223
224 case 'phone_home':
225 $this->writer->xmlElement('PhoneHome', [], $value);
226 break;
227
228 case 'phone_mobile':
229 $this->writer->xmlElement('PhoneMobile', [], $value);
230 break;
231
232 case 'fax':
233 $this->writer->xmlElement('Fax', [], $value);
234 break;
235
236 case 'email':
237 $this->writer->xmlElement('Email', [], $value);
238 break;
239
240 case 'second_email':
241 $this->writer->xmlElement('SecondEmail', [], $value);
242 break;
243
244 case 'matriculation':
245 $this->writer->xmlElement('Matriculation', [], $value);
246 break;
247
248 default:
249 if (!str_starts_with($field, 'udf_')) {
250 continue 2;
251 }
252
253 $id_data = explode('_', $field);
254 if (!isset($id_data[1])) {
255 continue 2;
256 }
257
258 $field = $this->user_defined_fields[$id_data[1]] ?? null;
259 if ($definition === null) {
260 $this->logger->warning(
261 sprintf(
262 'Invalid/Orphaned UD field mapping detected: %s',
263 $field
264 )
265 );
266 break;
267 }
268
269 $this->writer->xmlElement(
270 'UserDefinedField',
271 [
272 'Id' => $field->getIdentifier(),
273 'Name' => $field->getLabel($this->lng)
274 ],
275 $value
276 );
277 break;
278 }
279 }
280 $this->writer->xmlEndTag('User');
281 $this->writer->xmlEndTag('Users');
282
283 $this->logger->debug($this->writer->xmlDumpMem());
284 }
static _generateLogin(string $a_login)
generate free login by starting with a default string and adding postfix numbers

References ilAuthUtils\_generateLogin(), getUserId(), ILIAS\Repository\logger(), needsCreation(), parseRoleAssignments(), ILIAS\Repository\settings(), and valueFrom().

Referenced by updateUser().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ updateUser()

ilOpenIdConnectUserSync::updateUser ( )

Definition at line 75 of file class.ilOpenIdConnectUserSync.php.

75 : bool
76 {
77 if ($this->needsCreation() && !$this->settings->isSyncAllowed()) {
78 throw new ilOpenIdConnectSyncForbiddenException('No internal account given.');
79 }
80
81 $this->transformToXml();
82
83 $importParser = new ilUserImportParser();
84 $importParser->setXMLContent($this->writer->xmlDumpMem(false));
85
86 $roles = $this->parseRoleAssignments();
87 $importParser->setRoleAssignment($roles);
88
89 $importParser->setFolderId(USER_FOLDER_ID);
90 $importParser->startParsing();
91 $debug = $importParser->getProtocol();
92 $this->logger->debug(json_encode($debug, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT));
93
95 self::AUTH_MODE,
96 $this->ext_account
97 );
99
100 return true;
101 }
static _checkExternalAuthAccount(string $a_auth, string $a_account, bool $tryFallback=true)
check whether external account and authentication method matches with a user
const USER_FOLDER_ID
Definition: constants.php:33

References $int_account, ilObjUser\_checkExternalAuthAccount(), ILIAS\Repository\logger(), needsCreation(), parseRoleAssignments(), setInternalAccount(), ILIAS\Repository\settings(), transformToXml(), and USER_FOLDER_ID.

+ Here is the call graph for this function:

◆ valueFrom()

ilOpenIdConnectUserSync::valueFrom ( string  $connect_name)
private

Definition at line 383 of file class.ilOpenIdConnectUserSync.php.

383 : string
384 {
385 if (!$connect_name) {
386 return '';
387 }
388
389 if (!property_exists($this->user_info, $connect_name)) {
390 $this->logger->debug('Cannot find property ' . $connect_name . ' in user info ');
391 return '';
392 }
393
394 return (string) $this->user_info->{$connect_name};
395 }

References ILIAS\Repository\logger().

Referenced by transformToXml().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $ext_account

string ilOpenIdConnectUserSync::$ext_account = ''
private

Definition at line 32 of file class.ilOpenIdConnectUserSync.php.

Referenced by setExternalAccount().

◆ $int_account

string ilOpenIdConnectUserSync::$int_account = ''
private

Definition at line 33 of file class.ilOpenIdConnectUserSync.php.

Referenced by setInternalAccount(), and updateUser().

◆ $lng

readonly Language ilOpenIdConnectUserSync::$lng
private

Definition at line 30 of file class.ilOpenIdConnectUserSync.php.

◆ $logger

readonly ilLogger ilOpenIdConnectUserSync::$logger
private

Definition at line 29 of file class.ilOpenIdConnectUserSync.php.

◆ $user_defined_fields

array ilOpenIdConnectUserSync::$user_defined_fields
private

Definition at line 38 of file class.ilOpenIdConnectUserSync.php.

◆ $usr_id

int ilOpenIdConnectUserSync::$usr_id = 0
private

Definition at line 34 of file class.ilOpenIdConnectUserSync.php.

Referenced by getUserId().

◆ $writer

readonly ilXmlWriter ilOpenIdConnectUserSync::$writer
private

Definition at line 31 of file class.ilOpenIdConnectUserSync.php.

◆ AUTH_MODE

const ilOpenIdConnectUserSync::AUTH_MODE = 'oidc'

Definition at line 26 of file class.ilOpenIdConnectUserSync.php.

◆ UDF_STRING

const ilOpenIdConnectUserSync::UDF_STRING = 'udf_'
private

Definition at line 27 of file class.ilOpenIdConnectUserSync.php.


The documentation for this class was generated from the following file: