ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilSamlSettingsGUI.php
Go to the documentation of this file.
1<?php declare(strict_types=1);
2/* Copyright (c) 1998-2016 ILIAS open source, Extended GPL, see docs/LICENSE */
3
9{
12
13 const DEFAULT_CMD = 'listIdps';
14
18 protected static $globalCommands = [
20 'showAddIdpForm',
21 'showSettings',
22 'saveSettings',
23 'showNewIdpForm',
24 'saveNewIdp',
25 ];
26
30 protected static $globalEntityCommands = [
31 'deactivateIdp',
32 'activateIdp',
33 'confirmDeleteIdp',
34 'deleteIdp',
35 ];
36
40 protected static $ignoredUserFields = [
41 'mail_incoming_mail',
42 'preferences',
43 'hide_own_online_status',
44 'show_users_online',
45 'hits_per_page',
46 'roles',
47 'upload',
48 'password',
49 'username',
50 'language',
51 'skin_style',
52 'interests_general',
53 'interests_help_offered',
54 'interests_help_looking',
55 'bs_allow_to_contact_me',
56 'chat_osc_accept_msg',
57 ];
58
60 protected $ref_id;
62 protected $ctrl;
64 protected $lng;
66 protected $tpl;
68 protected $access;
70 protected $rbac;
72 protected $error_handler;
74 protected $tabs;
76 protected $toolbar;
78 protected $help;
80 protected $mapping;
82 protected $idp;
84 protected $samlAuth;
85
90 public function __construct($ref_id)
91 {
92 global $DIC;
93
94 $this->ctrl = $DIC->ctrl();
95 $this->tpl = $DIC->ui()->mainTemplate();
96 $this->lng = $DIC->language();
97 $this->access = $DIC->access();
98 $this->rbac = $DIC->rbac();
99 $this->error_handler = $DIC['ilErr'];
100 $this->tabs = $DIC->tabs();
101 $this->toolbar = $DIC['ilToolbar'];
102 $this->help = $DIC['ilHelp'];
103
104 $this->lng->loadLanguageModule('auth');
105 $this->ref_id = $ref_id;
106 }
107
111 protected function ensureAccess(string $operation) : void
112 {
113 if (!$this->rbac->system()->checkAccess($operation, $this->getRefId())) {
114 $this->error_handler->raiseError($this->lng->txt('msg_no_perm_read'), $this->error_handler->WARNING);
115 }
116 }
117
118 protected function ensureWriteAccess() : void
119 {
120 $this->ensureAccess('write');
121 }
122
123 protected function ensureReadAccess() : void
124 {
125 $this->ensureAccess('read');
126 }
127
131 public function getRefId() : int
132 {
133 return (int) $this->ref_id;
134 }
135
139 public function setRefId($ref_id) : void
140 {
141 $this->ref_id = (int) $ref_id;
142 }
143
144 protected function initIdp() : void
145 {
146 try {
147 $this->idp = ilSamlIdp::getInstanceByIdpId((int) $_REQUEST['saml_idp_id']);
148 } catch (Exception $e) {
149 ilUtil::sendFailure($this->lng->txt('auth_saml_unknow_idp'), true);
150 $this->ctrl->setParameter($this, 'saml_idp_id', null);
151 $this->ctrl->redirect($this, self::DEFAULT_CMD);
152 }
153 }
154
155 public function executeCommand() : void
156 {
157 $this->ensureReadAccess();
158
159 try {
161 $this->samlAuth = $factory->auth();
162 } catch (Throwable $e) {
163 if ('Database error: could not find driver' === $e->getMessage()) {
164 ilUtil::sendFailure($this->lng->txt('auth_saml_err_sqlite_driver'));
165 } else {
166 ilUtil::sendFailure($e->getMessage());
167 }
168 }
169
170 $this->help->setScreenIdComponent('auth');
171
172 switch ($this->ctrl->getNextClass()) {
173 default:
174 $cmd = $this->ctrl->getCmd();
175 if (!strlen($cmd) || !method_exists($this, $cmd)) {
176 $cmd = self::DEFAULT_CMD;
177 }
178
179 if (isset($_REQUEST['saml_idp_id'])) {
180 $this->ctrl->saveParameter($this, 'saml_idp_id');
181 }
182
183 if (!in_array(strtolower($cmd), array_map('strtolower', self::$globalCommands))) {
184 if (!isset($_REQUEST['saml_idp_id'])) {
185 $this->ctrl->redirect($this, self::DEFAULT_CMD);
186 }
187
188 $this->initIdp();
190 }
191
192 if (
193 in_array(strtolower($cmd), array_map('strtolower', self::$globalCommands)) ||
194 in_array(strtolower($cmd), array_map('strtolower', self::$globalEntityCommands))
195 ) {
196 $this->setSubTabs(self::VIEW_MODE_GLOBAL);
197 } else {
198 $this->setSubTabs(self::VIEW_MODE_SINGLE);
199 }
200
201 $this->$cmd();
202 break;
203 }
204 }
205
209 protected function listIdps() : void
210 {
211 if ($this->samlAuth && $this->rbac->system()->checkAccess('visible,read', $this->ref_id)) {
212 $addIdpButton = ilLinkButton::getInstance();
213 $addIdpButton->setCaption('auth_saml_add_idp_btn');
214 $addIdpButton->setUrl($this->ctrl->getLinkTarget($this, 'showNewIdpForm'));
215 $this->toolbar->addStickyItem($addIdpButton);
216 }
217
218 $table = new ilSamlIdpTableGUI($this, self::DEFAULT_CMD, $this->samlAuth);
219 $this->tpl->setContent($table->getHTML());
220 }
221
222 protected function deactivateIdp() : void
223 {
224 $this->ensureWriteAccess();
225
226 $this->idp->setActive(false);
227 $this->idp->persist();
228
229 ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
230 $this->listIdps();
231 }
232
233 protected function activateIdp() : void
234 {
235 $this->ensureWriteAccess();
236
237 $this->idp->setActive(true);
238 $this->idp->persist();
239
240 ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
241 $this->listIdps();
242 }
243
247 protected function setSubTabs(int $a_view_mode) : void
248 {
249 switch ($a_view_mode) {
251 $this->tabs->addSubTabTarget(
252 'auth_saml_idps',
253 $this->ctrl->getLinkTarget($this, self::DEFAULT_CMD),
254 array_merge(self::$globalEntityCommands, [self::DEFAULT_CMD, 'showNewIdpForm', 'saveNewIdp']),
255 get_class($this)
256 );
257
258 $this->tabs->addSubTabTarget(
259 'settings',
260 $this->ctrl->getLinkTarget($this, 'showSettings'),
261 array('showSettings', 'saveSettings'),
262 get_class($this)
263 );
264 break;
265
267 $this->tabs->clearTargets();
268 $this->tabs->setBackTarget(
269 $this->lng->txt('back'),
270 $this->ctrl->getLinkTarget($this, self::DEFAULT_CMD)
271 );
272
273 $this->tabs->addSubTabTarget(
274 'auth_saml_idp_settings',
275 $this->ctrl->getLinkTarget($this, 'showIdpSettings'),
276 ['showIdpSettings', 'saveIdpSettings'],
277 get_class($this)
278 );
279
280 $this->tabs->addSubTabTarget(
281 'auth_saml_user_mapping',
282 $this->ctrl->getLinkTarget($this, 'showUserAttributeMappingForm'),
283 ['showUserAttributeMappingForm', 'saveUserAttributeMapping'],
284 get_class($this)
285 );
286 break;
287 }
288 }
289
290 private function initUserAttributeMapping() : void
291 {
292 $this->mapping = new ilExternalAuthUserAttributeMapping('saml', $this->idp->getIdpId());
293 }
294
299 {
300 $form = new ilPropertyFormGUI();
301 $form->setFormAction($this->ctrl->getFormAction($this, 'saveUserAttributeMapping'));
302 $form->setTitle($this->lng->txt('auth_saml_user_mapping'));
303
304 $usr_profile = new ilUserProfile();
305 foreach ($usr_profile->getStandardFields() as $id => $definition) {
306 if (in_array($id, self::$ignoredUserFields)) {
307 continue;
308 }
309
310 $this->addAttributeRuleFieldToForm($form, $this->lng->txt($id), $id);
311 }
312
313 foreach (ilUserDefinedFields::_getInstance()->getDefinitions() as $definition) {
314 $this->addAttributeRuleFieldToForm($form, $definition['field_name'], 'udf_' . $definition['field_id']);
315 }
316
317 if (!$this->access->checkAccess('write', '', $this->getRefId())) {
318 foreach ($form->getItems() as $item) {
319 $item->setDisabled(true);
320 }
321 } else {
322 $form->addCommandButton('saveUserAttributeMapping', $this->lng->txt('save'));
323 }
324
325 return $form;
326 }
327
333 protected function addAttributeRuleFieldToForm(
334 ilPropertyFormGUI $form,
335 string $field_label,
336 string $field_name
337 ) : void {
338 $field = new ilTextInputGUI($field_label, $field_name);
339 $form->addItem($field);
340
341 $update_automatically = new ilCheckboxInputGUI('', $field_name . '_update');
342 $update_automatically->setOptionTitle($this->lng->txt('auth_saml_update_field_info'));
343 $update_automatically->setValue(1);
344 $form->addItem($update_automatically);
345 }
346
347 protected function saveUserAttributeMapping() : void
348 {
349 $this->ensureWriteAccess();
350
351 $form = $this->getUserAttributeMappingForm();
352 if ($form->checkInput()) {
353 $this->mapping->delete();
354
355 $usr_profile = new ilUserProfile();
356 foreach ($usr_profile->getStandardFields() as $id => $definition) {
357 if (in_array($id, self::$ignoredUserFields)) {
358 continue;
359 }
360
361 $rule = $this->mapping->getEmptyRule();
362 $rule->setAttribute($id);
363 $rule->setExternalAttribute($form->getInput($rule->getAttribute()));
364 $rule->updateAutomatically((bool) $form->getInput($rule->getAttribute() . '_update'));
365 $this->mapping[$rule->getAttribute()] = $rule;
366 }
367
368 foreach (ilUserDefinedFields::_getInstance()->getDefinitions() as $definition) {
369 $rule = $this->mapping->getEmptyRule();
370 $rule->setAttribute('udf_' . $definition['field_id']);
371 $rule->setExternalAttribute($form->getInput($rule->getAttribute()));
372 $rule->updateAutomatically((bool) $form->getInput($rule->getAttribute() . '_update'));
373 $this->mapping[$rule->getAttribute()] = $rule;
374 }
375
376 $this->mapping->save();
377
378 ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
379 }
380
381 $form->setValuesByPost();
382
383 $this->showUserAttributeMappingForm($form);
384 }
385
389 protected function showUserAttributeMappingForm(ilPropertyFormGUI $form = null) : void
390 {
391 $this->tabs->setSubTabActive('auth_saml_user_mapping');
392
393 if (!($form instanceof ilPropertyFormGUI)) {
394 $form = $this->getUserAttributeMappingForm();
395 $data = array();
396 foreach ($this->mapping as $rule) {
397 $data[$rule->getAttribute()] = $rule->getExternalAttribute();
398 $data[$rule->getAttribute() . '_update'] = (bool) $rule->isAutomaticallyUpdated();
399 }
400 $form->setValuesByArray($data);
401 }
402
403 $this->tpl->setContent($form->getHTML());
404 }
405
409 protected function getSettingsForm() : ilPropertyFormGUI
410 {
411 $form = new ilPropertyFormGUI();
412 $form->setFormAction($this->ctrl->getFormAction($this, 'saveSettings'));
413 $form->setTitle($this->lng->txt('auth_saml_configure'));
414
415 $show_login_form = new ilCheckboxInputGUI($this->lng->txt('auth_saml_login_form'), 'login_form');
416 $show_login_form->setInfo($this->lng->txt('auth_saml_login_form_info'));
417 $show_login_form->setValue(1);
418 $form->addItem($show_login_form);
419
420 if (!$this->access->checkAccess('write', '', $this->getRefId())) {
421 foreach ($form->getItems() as $item) {
422 $item->setDisabled(true);
423 }
424 } else {
425 $form->addCommandButton('saveSettings', $this->lng->txt('save'));
426 }
427
428 return $form;
429 }
430
431 private function prepareRoleSelection() : array
432 {
433 $global_roles = ilUtil::_sortIds(
434 $this->rbac->review()->getGlobalRoles(),
435 'object_data',
436 'title',
437 'obj_id'
438 );
439
440 $select[0] = $this->lng->txt('links_select_one');
441 foreach ($global_roles as $role_id) {
442 $select[$role_id] = ilObject::_lookupTitle($role_id);
443 }
444
445 return $select;
446 }
447
448 protected function saveSettings() : void
449 {
450 $this->ensureWriteAccess();
451
452 $form = $this->getSettingsForm();
453 if ($form->checkInput()) {
454 ilSamlSettings::getInstance()->setLoginFormStatus((bool) $form->getInput('login_form'));
455 ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
456 }
457
458 $form->setValuesByPost();
459
460 $this->showSettings($form);
461 }
462
466 protected function showSettings(ilPropertyFormGUI $form = null) : void
467 {
468 if (!($form instanceof ilPropertyFormGUI)) {
469 $form = $this->getSettingsForm();
470 $form->setValuesByArray([
471 'login_form' => ilSamlSettings::getInstance()->isDisplayedOnLoginPage(),
472 ]);
473 }
474
475 $this->tpl->setContent($form->getHTML());
476 }
477
482 {
483 $form = new ilPropertyFormGUI();
484 $form->setFormAction($this->ctrl->getFormAction($this, 'saveIdpSettings'));
485 $form->setTitle(sprintf($this->lng->txt('auth_saml_configure_idp'), $this->idp->getEntityId()));
486
487 $idp = new ilTextInputGUI($this->lng->txt('auth_saml_idp'), 'entity_id');
488 $idp->setDisabled(true);
489 $form->addItem($idp);
490
491 $this->addMetadataElement($form);
492
493 $local = new ilCheckboxInputGUI($this->lng->txt('auth_allow_local'), 'allow_local_auth');
494 $local->setValue(1);
495 $local->setInfo($this->lng->txt('auth_allow_local_info'));
496 $form->addItem($local);
497
498 $uid_claim = new ilTextInputGUI($this->lng->txt('auth_saml_uid_claim'), 'uid_claim');
499 $uid_claim->setInfo($this->lng->txt('auth_saml_uid_claim_info'));
500 $uid_claim->setRequired(true);
501 $form->addItem($uid_claim);
502
503 $sync = new ilCheckboxInputGUI($this->lng->txt('auth_saml_sync'), 'sync_status');
504 $sync->setInfo($this->lng->txt('auth_saml_sync_info'));
505 $sync->setValue(1);
506
507 $username_claim = new ilTextInputGUI($this->lng->txt('auth_saml_username_claim'), 'login_claim');
508 $username_claim->setInfo($this->lng->txt('auth_saml_username_claim_info'));
509 $username_claim->setRequired(true);
510 $sync->addSubItem($username_claim);
511
512 $role = new ilSelectInputGUI($this->lng->txt('auth_saml_role_select'), 'default_role_id');
513 $role->setOptions($this->prepareRoleSelection());
514 $role->setRequired(true);
515 $sync->addSubItem($role);
516
517 $migr = new ilCheckboxInputGUI($this->lng->txt('auth_saml_migration'), 'account_migr_status');
518 $migr->setInfo($this->lng->txt('auth_saml_migration_info'));
519 $migr->setValue(1);
520 $sync->addSubItem($migr);
521 $form->addItem($sync);
522
523 if (!$this->access->checkAccess('write', '', $this->getRefId())) {
524 foreach ($form->getItems() as $item) {
525 $item->setDisabled(true);
526 }
527 } else {
528 $form->addCommandButton('saveIdpSettings', $this->lng->txt('save'));
529 }
530 $form->addCommandButton(self::DEFAULT_CMD, $this->lng->txt('cancel'));
531
532 return $form;
533 }
534
538 protected function showIdpSettings(ilPropertyFormGUI $form = null) : void
539 {
540 $this->tabs->setSubTabActive('auth_saml_idp_settings');
541
542 if (null === $form) {
543 $form = $this->getIdpSettingsForm();
544 $data = $this->idp->toArray();
545 $this->populateWithMetadata($this->idp, $data);
546 $form->setValuesByArray($data);
547 } else {
548 $form->setValuesByPost();
549 }
550
551 $this->help->setSubScreenId('edit_idp');
552
553 $this->tpl->setContent($form->getHTML());
554 }
555
556 protected function saveIdpSettings() : void
557 {
558 $this->ensureWriteAccess();
559
560 $form = $this->getIdpSettingsForm();
561 if ($form->checkInput()) {
562 $this->idp->bindForm($form);
563 $this->idp->persist();
564 ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
565
566 $this->storeMetadata($this->idp, $form->getInput('metadata'));
567 }
568
569 $this->showIdpSettings($form);
570 }
571
575 protected function getIdpForm() : ilPropertyFormGUI
576 {
577 $form = new ilPropertyFormGUI();
578 $form->setFormAction($this->ctrl->getFormAction($this, 'saveNewIdp'));
579 $form->setTitle($this->lng->txt('auth_saml_add_idp_btn'));
580
581 $this->addMetadataElement($form);
582
583 $form->addCommandButton('saveNewIdp', $this->lng->txt('save'));
584 $form->addCommandButton('listIdps', $this->lng->txt('cancel'));
585
586 return $form;
587 }
588
589 protected function saveNewIdp() : void
590 {
591 $this->ensureWriteAccess();
592
593 $form = $this->getIdpForm();
594 if ($form->checkInput()) {
595 $idp = new ilSamlIdp();
596 $idp->bindForm($form);
597 $idp->persist();
598
599 $this->storeMetadata($idp, $form->getInput('metadata'));
600
601 ilUtil::sendSuccess($this->lng->txt('saved_successfully'), true);
602 $this->ctrl->setParameter($this, 'saml_idp_id', $idp->getIdpId());
603 $this->ctrl->redirect($this, 'showIdpSettings');
604 }
605
606 $this->showNewIdpForm($form);
607 }
608
612 protected function showNewIdpForm(ilPropertyFormGUI $form = null) : void
613 {
614 $this->ensureWriteAccess();
615
616 if (null === $form) {
617 $form = $this->getIdpForm();
618 } else {
619 $form->setValuesByPost();
620 }
621
622 $this->help->setSubScreenId('create_idp');
623
624 $this->tpl->setContent($form->getHTML());
625 }
626
630 protected function addMetadataElement(ilPropertyFormGUI $form) : void
631 {
632 $metadata = new ilSamlIdpMetadataInputGUI(
633 $this->lng->txt('auth_saml_add_idp_md_label'),
634 'metadata',
636 );
637 $metadata->setInfo($this->lng->txt('auth_saml_add_idp_md_info'));
638 $metadata->setRows(20);
639 $metadata->setRequired(true);
640
641 $purifier = new ilHtmlPurifierComposite();
642 $purifier->addPurifier(new ilSamlIdpMetadataPurifier());
643
644 $metadata->setPurifier($purifier);
645 $metadata->usePurifier(true);
646 $form->addItem($metadata);
647 }
648
649 protected function populateWithMetadata(ilSamlIdp $idp, array &$data) : void
650 {
651 $idpDisco = $this->samlAuth->getIdpDiscovery();
652
653 $data['metadata'] = $idpDisco->fetchIdpMetadata($idp->getIdpId());
654 }
655
660 protected function storeMetadata(ilSamlIdp $idp, string $metadata) : void
661 {
662 $idpDisco = $this->samlAuth->getIdpDiscovery();
663 $idpDisco->storeIdpMetadata($idp->getIdpId(), $metadata);
664 }
665
666 protected function confirmDeleteIdp() : void
667 {
668 $this->ensureWriteAccess();
669
670 $confirmation = new ilConfirmationGUI();
671 $confirmation->setFormAction($this->ctrl->getFormAction($this, 'deleteIdp'));
672 $confirmation->setConfirm($this->lng->txt('confirm'), 'deleteIdp');
673 $confirmation->setCancel($this->lng->txt('cancel'), self::DEFAULT_CMD);
674 $confirmation->setHeaderText($this->lng->txt('auth_saml_sure_delete_idp'));
675 $confirmation->addItem('saml_idp_ids', $this->idp->getIdpId(), $this->idp->getEntityId());
676
677 $this->tpl->setContent($confirmation->getHTML());
678 }
679
680 protected function deleteIdp() : void
681 {
682 $this->ensureWriteAccess();
683
684 $idpDisco = $this->samlAuth->getIdpDiscovery();
685 $idpDisco->deleteIdpMetadata($this->idp->getIdpId());
686
687 $this->idp->delete();
688
689 ilUtil::sendSuccess($this->lng->txt('auth_saml_deleted_idp'), true);
690
691 $this->ctrl->setParameter($this, 'saml_idp_id', null);
692 $this->ctrl->redirect($this, self::DEFAULT_CMD);
693 }
694}
An exception for terminatinating execution or to throw for unit testing.
This class represents a checkbox property in a property form.
Confirmation screen class.
setFormAction($a_formaction)
Set FormAction.
Composite for nesting multiple purifiers.
static getInstance()
Factory.
static _lookupTitle($a_id)
lookup object title
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
addCommandButton($a_cmd, $a_text, $a_id="")
Add Command button.
setValuesByArray($a_values, $a_restrict_to_value_keys=false)
Set form values from an array.
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
checkInput()
Check Post Input.
setValuesByPost()
Set form values from POST values.
setTitle($a_title)
Set Title.
Class ilSamlAuthFactory.
Class ilSamlIdpMetadataInputGUI.
Class ilSamlIdpMetadataPurifier.
Class ilSamlIdpTableGUI.
Class ilSamlIdpXmlMetadataParser.
Class ilSamlIdp.
static getInstanceByIdpId(int $a_idp_id)
Class ilSamlSettingsGUI.
addAttributeRuleFieldToForm(ilPropertyFormGUI $form, string $field_label, string $field_name)
populateWithMetadata(ilSamlIdp $idp, array &$data)
setSubTabs(int $a_view_mode)
showNewIdpForm(ilPropertyFormGUI $form=null)
storeMetadata(ilSamlIdp $idp, string $metadata)
ensureAccess(string $operation)
showUserAttributeMappingForm(ilPropertyFormGUI $form=null)
showSettings(ilPropertyFormGUI $form=null)
showIdpSettings(ilPropertyFormGUI $form=null)
__construct($ref_id)
ilSamlSettingsGUI constructor.
addMetadataElement(ilPropertyFormGUI $form)
This class represents a selection list property in a property form.
This class represents a text property in a property form.
static _getInstance()
Get instance.
Class ilUserProfile.
static _sortIds($a_ids, $a_table, $a_field, $a_id_name)
Function that sorts ids by a given table field using WHERE IN E.g: __sort(array(6,...
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
help()
Definition: help.php:2
$factory
Definition: metadata.php:58
$data
Definition: storeScorm.php:23
$DIC
Definition: xapitoken.php:46