19declare(strict_types=1);
59 'hide_own_online_status',
68 'interests_help_offered',
69 'interests_help_looking',
70 'bs_allow_to_contact_me',
71 'chat_osc_accept_msg',
72 'chat_broadcast_typing',
96 $this->
ctrl = $DIC->ctrl();
97 $this->tpl =
$DIC->ui()->mainTemplate();
98 $this->
lng = $DIC->language();
99 $this->
rbac = $DIC->rbac();
100 $this->error_handler =
$DIC[
'ilErr'];
101 $this->
tabs = $DIC->tabs();
102 $this->
toolbar = $DIC[
'ilToolbar'];
103 $this->
help = $DIC[
'ilHelp'];
104 $this->http_state =
$DIC->http();
106 $this->ui_factory =
$DIC->ui()->factory();
107 $this->ui_renderer =
$DIC->ui()->renderer();
108 $this->
profile = $DIC[
'user']->getProfile();
110 $this->
lng->loadLanguageModule(
'auth');
115 if (!$this->
rbac->system()->checkAccess($operation, $this->ref_id)) {
116 $this->error_handler->raiseError($this->
lng->txt(
'msg_no_perm_read'), $this->error_handler->WARNING);
150 if ($this->http_state->wrapper()->query()->has(self::REQUEST_PARAM_SAML_IDP_ID)) {
151 $idpId = $this->http_state->wrapper()->query()->retrieve(
152 self::REQUEST_PARAM_SAML_IDP_ID,
155 } elseif ($this->http_state->wrapper()->post()->has(self::REQUEST_PARAM_SAML_IDP_ID)) {
156 $idpId = $this->http_state->wrapper()->post()->retrieve(
157 self::REQUEST_PARAM_SAML_IDP_ID,
162 if ($this->
getTableAction() && $this->http_state->wrapper()->query()->has(
'saml_idps_idp_id')) {
163 $idpIds = $this->http_state->wrapper()->query()->retrieve(
165 $this->
refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
167 if (count($idpIds) === 1) {
168 $idpId = current($idpIds);
172 if ($this->http_state->wrapper()->post()->has(self::REQUEST_PARAM_SAML_IDP_IDS)) {
173 $idpIds = $this->http_state->wrapper()->post()->retrieve(
174 self::REQUEST_PARAM_SAML_IDP_IDS,
175 $this->
refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
177 if (count($idpIds) === 1) {
178 $idpId = current($idpIds);
189 }
catch (Exception) {
190 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_FAILURE, $this->
lng->txt(
'auth_saml_unknow_idp'),
true);
191 $this->
ctrl->setParameter($this, self::REQUEST_PARAM_SAML_IDP_ID,
null);
192 $this->
ctrl->redirect($this, self::DEFAULT_CMD);
202 $this->saml_auth = $factory->auth();
203 }
catch (Throwable
$e) {
204 if (
$e->getMessage() ===
'Database error: could not find driver') {
205 $this->tpl->setOnScreenMessage(
206 self::MESSAGE_TYPE_FAILURE,
207 $this->
lng->txt(
'auth_saml_err_sqlite_driver')
210 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_FAILURE,
$e->getMessage());
214 $this->
help->setScreenIdComponent(
'auth');
216 $cmd = $this->
ctrl->getCmd();
217 if ($cmd ===
null || $cmd ===
'' || !method_exists($this, $cmd .
'Command')) {
220 $verified_command = $cmd .
'Command';
225 $this->
ctrl->setParameter($this, self::REQUEST_PARAM_SAML_IDP_ID, $idp_id);
228 if (!in_array(strtolower($cmd), array_map(
'strtolower', self::GLOBAL_COMMANDS),
true)) {
230 $this->
ctrl->redirect($this, self::DEFAULT_CMD);
243 $this->$verified_command();
248 $is_global_command = in_array(strtolower($cmd), array_map(
'strtolower', self::GLOBAL_COMMANDS),
true);
249 $is_global_entity_command = in_array(
251 array_map(
'strtolower', self::GLOBAL_ENTITY_COMMANDS),
255 $is_global_table_action = in_array(
257 array_map(
'strtolower', self::GLOBAL_ENTITY_TABLE_ACTIONS),
261 return $is_global_command || $is_global_entity_command || $is_global_table_action;
266 if ($this->saml_auth && $this->
rbac->system()->checkAccess(self::PERMISSION_WRITE, $this->ref_id)) {
268 $this->ui_factory->button()->standard(
269 $this->lng->txt(
'auth_saml_add_idp_btn'),
270 $this->ctrl->getLinkTarget($this, self::CMD_SHOW_NEW_IDP_FORM)
275 $federation_md_url = rtrim(
278 ) .
'/metadata.php?client_id=' .
CLIENT_ID;
279 $info = $this->ui_factory->messageBox()->info(
281 $this->
lng->txt(
'auth_saml_idps_info'),
282 'auth/saml/config/config.php',
283 'auth/saml/config/authsources.php',
284 $this->ui_renderer->render(
285 $this->ui_factory->link()->standard(
286 'https://simplesamlphp.org/docs/stable/simplesamlphp-sp',
287 'https://simplesamlphp.org/docs/stable/simplesamlphp-sp'
290 $this->ui_renderer->render($this->ui_factory->link()->standard($federation_md_url, $federation_md_url))
300 $this->http_state->request(),
302 self::CMD_TABLE_ACTIONS,
303 $this->
rbac->system()->checkAccess(self::PERMISSION_WRITE, $this->ref_id)
305 $this->tpl->setContent($this->ui_renderer->render([
$info, $table->get()]));
310 return $this->http_state->wrapper()->query()->retrieve(
311 'saml_idps_table_action',
313 $this->refinery->kindlyTo()->string(),
314 $this->refinery->always(
null)
322 self::TABLE_ACTION_SHOW_IDP_SETTINGS => $this->
ctrl->redirect($this, self::CMD_SHOW_IDP_SETTINGS),
323 self::TABLE_ACTION_ACTIVATE_IDP => $this->
activateIdp(),
326 default => $this->
ctrl->redirect($this, self::DEFAULT_CMD),
334 $this->idp->setActive(
false);
335 $this->idp->persist();
337 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_SUCCESS, $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY),
true);
338 $this->
ctrl->redirect($this, self::DEFAULT_CMD);
345 $this->idp->setActive(
true);
346 $this->idp->persist();
348 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_SUCCESS, $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY),
true);
349 $this->
ctrl->redirect($this, self::DEFAULT_CMD);
354 switch ($a_view_mode) {
356 $this->
tabs->addSubTabTarget(
358 $this->
ctrl->getLinkTarget($this, self::DEFAULT_CMD),
360 self::GLOBAL_ENTITY_COMMANDS,
361 [self::DEFAULT_CMD, self::CMD_SHOW_NEW_IDP_FORM, self::CMD_SAVE_NEW_IDP]
365 ($this->
getTableAction() === self::TABLE_ACTION_CONFIRM_DELETE_IDP)
368 $this->
tabs->addSubTabTarget(
370 $this->
ctrl->getLinkTarget($this, self::CMD_SHOW_SETTINGS),
371 [self::CMD_SHOW_SETTINGS, self::CMD_SAVE_SETTINGS],
377 $this->
tabs->clearTargets();
378 $this->
tabs->setBackTarget(
379 $this->
lng->txt(
'back'),
380 $this->ctrl->getLinkTarget($this, self::DEFAULT_CMD)
383 $this->
tabs->addSubTabTarget(
384 'auth_saml_idp_settings',
385 $this->
ctrl->getLinkTarget($this, self::CMD_SHOW_IDP_SETTINGS),
386 [self::CMD_SHOW_IDP_SETTINGS, self::CMD_SAVE_IDP_SETTINGS],
390 $this->
tabs->addSubTabTarget(
391 self::LNG_AUTH_SAML_USER_MAPPING,
392 $this->
ctrl->getLinkTarget($this, self::CMD_SHOW_USER_ATTRIBUTE_MAPPING_FORM),
393 [self::CMD_SHOW_USER_ATTRIBUTE_MAPPING_FORM, self::CMD_SAVE_USER_ATTRIBUTE_MAPPING],
408 $form->setFormAction($this->
ctrl->getFormAction($this, self::CMD_SAVE_USER_ATTRIBUTE_MAPPING));
409 $form->setTitle($this->
lng->txt(self::LNG_AUTH_SAML_USER_MAPPING));
411 foreach ($this->
profile->getFields() as $field) {
412 if (in_array($field->getIdentifier(), self::IGNORED_USER_FIELDS,
true)) {
416 $id = $field->getIdentifier();
417 if ($field->isCustom()) {
424 if ($this->
rbac->system()->checkAccess(self::PERMISSION_WRITE, $this->ref_id)) {
425 $form->addCommandButton(self::CMD_SAVE_USER_ATTRIBUTE_MAPPING, $this->
lng->txt(self::LNG_SAVE));
427 foreach ($form->getItems() as $item) {
428 $item->setDisabled(
true);
443 $update_automatically =
new ilCheckboxInputGUI(
'', $field_name . self::PROP_UPDATE_SUFFIX);
444 $update_automatically->setOptionTitle($this->
lng->txt(
'auth_saml_update_field_info'));
445 $update_automatically->setValue(
'1');
446 $form->
addItem($update_automatically);
451 $this->ensureWriteAccess();
453 $form = $this->getUserAttributeMappingForm();
455 $this->mapping->delete();
457 foreach ($this->
profile->getFields() as $field) {
458 if (in_array($field->getIdentifier(), self::IGNORED_USER_FIELDS,
true)) {
462 $id = $field->getIdentifier();
463 if ($field->isCustom()) {
467 $rule = $this->mapping->getEmptyRule();
468 $rule->setAttribute(
$id);
469 $rule->setExternalAttribute((
string) $form->
getInput($rule->getAttribute()));
470 $rule->updateAutomatically((
bool) $form->
getInput($rule->getAttribute() . self::PROP_UPDATE_SUFFIX));
471 $this->mapping[$rule->getAttribute()] = $rule;
474 $this->mapping->save();
476 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_SUCCESS, $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY));
481 $this->showUserAttributeMappingFormCommand($form);
486 $this->
tabs->setSubTabActive(self::LNG_AUTH_SAML_USER_MAPPING);
489 $form = $this->getUserAttributeMappingForm();
491 foreach ($this->mapping as $rule) {
492 $data[$rule->getAttribute()] = $rule->getExternalAttribute();
493 $data[$rule->getAttribute() . self::PROP_UPDATE_SUFFIX] = $rule->isAutomaticallyUpdated();
498 $this->tpl->setContent($form->
getHTML());
506 $access = $this->
rbac->system()->checkAccess(self::PERMISSION_WRITE, $this->ref_id);
507 $form = $this->ui_factory->input()->container()->form()->standard(
508 $this->
ctrl->getFormAction($this, $access ? self::CMD_SAVE_SETTINGS : self::CMD_SHOW_SETTINGS),
510 self::LNG_LOGIN_FORM => $this->ui_factory
514 $this->lng->txt(
'auth_saml_login_form'),
515 $this->lng->txt(
'auth_saml_login_form_info')
517 ->withValue((
bool) ($values[self::LNG_LOGIN_FORM] ??
true))
518 ->withDisabled(!$access),
523 $form = $form->withSubmitLabel($this->
lng->txt(
'refresh'));
535 $global_roles = array_map(
538 $this->
rbac->review()->getGlobalRoles(),
545 $select[0] = $this->
lng->txt(
'links_select_one');
546 foreach ($global_roles as $role_id) {
555 $this->ensureWriteAccess();
557 $form = $this->getSettingsForm()->withRequest($this->http_state->request());
558 if (!$form->getError()) {
559 $data = $form->getData();
561 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_SUCCESS, $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY));
564 $this->showSettingsCommand($form);
570 $form = $this->getSettingsForm([
575 $title = $this->ui_factory->item()->standard($this->
lng->txt(
'auth_saml_configure'));
576 $this->tpl->setContent($this->ui_renderer->render([
583 ?
string &$medadata_entity_id =
null
584 ): \
ILIAS\Refinery\Constraint {
585 $xml_parser_error = null;
587 return $this->
refinery->custom()->constraint(
588 function (
string $value) use (&$xml_parser_error, &$medadata_entity_id):
bool {
595 $result = $parser->parse($value);
596 if ($result->isError()) {
597 $xml_parser_error = $result->error();
601 $medadata_entity_id = $result->value();
604 }
catch (Throwable) {
605 $xml_parser_error = $this->
lng->txt(
'auth_saml_add_idp_md_error');
609 implode(
' ', [$this->
lng->txt(
'auth_saml_add_idp_md_error'), $xml_parser_error])
613 private function getIdpSettingsForm(array $values = []): StandardForm
615 $ui_field = $this->ui_factory->input()->field();
616 $metadata_entity_id = $values[self::METADATA_ENTITY_ID] ??
null;
621 $this->
lng->txt(
'auth_saml_idp')
622 )->withValue($values[self::METADATA_ENTITY_ID] ??
'')->withDisabled(
true),
623 self::METADATA_STORAGE_KEY => $ui_field
625 $this->
lng->txt(
'auth_saml_add_idp_md_label'),
626 $this->lng->txt(
'auth_saml_add_idp_md_info')
628 ->withValue($values[self::METADATA_STORAGE_KEY] ??
'')
631 ->withDedicatedName(self::METADATA_STORAGE_KEY)
632 ->withAdditionalTransformation($this->metadataValidationConstraint($metadata_entity_id)),
633 'allow_local_auth' => $ui_field->checkbox(
634 $this->
lng->txt(
'auth_allow_local'),
635 $this->lng->txt(
'auth_allow_local_info')
636 )->withValue((
bool) ($values[
'allow_local_auth'] ??
true)),
637 'uid_claim' => $ui_field->text(
638 $this->
lng->txt(
'auth_saml_uid_claim'),
639 $this->lng->txt(
'auth_saml_uid_claim_info')
640 )->withValue($values[
'uid_claim'] ??
'')->withRequired(
true),
641 'sync_status' => $ui_field->optionalGroup(
643 'login_claim' => $ui_field->text(
644 $this->lng->txt(
'auth_saml_username_claim'),
645 $this->lng->txt(
'auth_saml_username_claim_info')
646 )->withRequired(
true),
647 'default_role_id' => $ui_field->select(
648 $this->lng->txt(
'auth_saml_role_select'),
649 $this->prepareRoleSelection()
650 )->withRequired(
true),
651 'account_migr_status' => $ui_field->checkbox(
652 $this->lng->txt(
'auth_saml_migration'),
653 $this->lng->txt(
'auth_saml_migration_info')
656 $this->lng->txt(
'auth_saml_sync'),
657 $this->lng->txt(
'auth_saml_sync_info')
659 (isset($values[
'sync_status']) && $values[
'sync_status'])
661 'login_claim' => $values[
'login_claim'] ??
'',
662 'default_role_id' => $values[
'default_role_id'] ?? array_key_first($this->prepareRoleSelection()),
663 'account_migr_status' => (
bool) ($values[
'account_migr_status'] ??
true)
669 $write_access = $this->
rbac->system()->checkAccess(self::PERMISSION_WRITE, $this->ref_id);
670 $inputs = array_map(
static function (
FormInput $input) use ($write_access) {
671 if (!$write_access) {
678 $this->
ctrl->setParameter($this, self::REQUEST_PARAM_SAML_IDP_ID, $this->idp->getIdpId());
680 return $this->ui_factory->input()->container()->form()->standard(
681 $this->
ctrl->getFormAction($this, self::CMD_SAVE_IDP_SETTINGS),
688 $this->
tabs->setSubTabActive(
'auth_saml_idp_settings');
691 $data = $this->idp->toArray();
692 $this->populateWithMetadata($this->idp,
$data);
693 $form = $this->getIdpSettingsForm(
$data);
696 $this->
help->setSubScreenId(
'edit_idp');
698 $title = $this->ui_factory->item()->standard(
699 sprintf($this->
lng->txt(
'auth_saml_configure_idp'), $this->idp->getEntityId())
702 $this->tpl->setContent($this->ui_renderer->render([
710 $this->ensureWriteAccess();
712 $form = $this->getIdpSettingsForm()->withRequest($this->http_state->request());
714 if (!$form->getError()) {
715 $this->idp->bindForm($form);
716 $this->idp->persist();
718 $this->storeMetadata($this->idp, $form->getData()[self::METADATA_STORAGE_KEY] ??
'');
719 $this->tpl->setOnScreenMessage(
720 self::MESSAGE_TYPE_SUCCESS,
721 $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY),
726 $this->
ctrl->redirect($this, self::CMD_SHOW_IDP_SETTINGS);
731 $medadata_entity_id =
'';
733 return $this->ui_factory->input()->container()->form()->standard(
734 $this->
ctrl->getFormAction($this, self::CMD_SAVE_NEW_IDP),
736 self::METADATA_STORAGE_KEY => $this->ui_factory
740 $this->lng->txt(
'auth_saml_add_idp_md_label'),
741 $this->lng->txt(
'auth_saml_add_idp_md_info')
743 ->withValue($values[self::METADATA_STORAGE_KEY] ??
'')
746 ->withDedicatedName(self::METADATA_STORAGE_KEY)
747 ->withAdditionalTransformation($this->metadataValidationConstraint($medadata_entity_id)),
748 self::METADATA_ENTITY_ID => $this->ui_factory
752 ->withAdditionalTransformation(
753 $this->refinery->custom()->transformation(
754 static function (
string $value) use (&$medadata_entity_id):
string {
756 if ($sanitized_value !== $medadata_entity_id) {
760 return trim($sanitized_value);
770 $this->ensureWriteAccess();
772 $form = $this->getIdpForm()->withRequest($this->http_state->request());
773 if (!$form->getError()) {
777 $this->storeMetadata($idp, $form->getData()[self::METADATA_STORAGE_KEY] ??
'');
779 $this->tpl->setOnScreenMessage(
780 self::MESSAGE_TYPE_SUCCESS,
781 $this->
lng->txt(self::LNG_SAVED_SUCCESSFULLY),
784 $this->
ctrl->setParameter($this, self::REQUEST_PARAM_SAML_IDP_ID, $idp->
getIdpId());
785 $this->
ctrl->redirect($this, self::TABLE_ACTION_SHOW_IDP_SETTINGS);
788 $this->showNewIdpFormCommand($form);
793 $this->ensureWriteAccess();
795 if ($form ===
null) {
796 $form = $this->getIdpForm();
798 $form = $form->withRequest($this->http_state->request());
801 $this->
help->setSubScreenId(
'create_idp');
803 $title = $this->ui_factory->item()->standard($this->
lng->txt(
'auth_saml_add_idp_btn'));
804 $this->tpl->setContent($this->ui_renderer->render([
812 $idp_disco = $this->saml_auth->getIdpDiscovery();
814 $data[self::METADATA_STORAGE_KEY] = $idp_disco->fetchIdpMetadata($idp->
getIdpId());
819 $idp_disco = $this->saml_auth->getIdpDiscovery();
820 $idp_disco->storeIdpMetadata($idp->
getIdpId(), $metadata);
825 $this->ensureWriteAccess();
828 $confirmation->setFormAction($this->
ctrl->getFormAction($this, self::CMD_DELETE_IDP));
829 $confirmation->setConfirm($this->
lng->txt(
'confirm'), self::CMD_DELETE_IDP);
830 $confirmation->setCancel($this->
lng->txt(self::LNG_CANCEL), self::DEFAULT_CMD);
831 $confirmation->setHeaderText($this->
lng->txt(
'auth_saml_sure_delete_idp'));
832 $confirmation->addItem(
833 self::REQUEST_PARAM_SAML_IDP_IDS,
834 (
string) $this->idp->getIdpId(),
835 $this->idp->getEntityId()
838 $this->tpl->setContent($confirmation->getHTML());
843 $this->ensureWriteAccess();
845 $idp_disco = $this->saml_auth->getIdpDiscovery();
846 $idp_disco->deleteIdpMetadata($this->idp->getIdpId());
848 $this->idp->delete();
850 $this->tpl->setOnScreenMessage(self::MESSAGE_TYPE_SUCCESS, $this->
lng->txt(
'auth_saml_deleted_idp'),
true);
852 $this->
ctrl->setParameter($this, self::REQUEST_PARAM_SAML_IDP_ID,
null);
853 $this->
ctrl->redirect($this, self::DEFAULT_CMD);
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Provides fluid interface to RBAC services.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Error Handling & global info handling.
static _lookupTitle(int $obj_id)
bindForm(StandardForm $form)
static getInstanceByIdpId(int $a_idp_id)
shouldRenderGlobalCommandSubTabs(string $cmd)
addAttributeRuleFieldToForm(ilPropertyFormGUI $form, string $field_label, string $field_name)
populateWithMetadata(ilSamlIdp $idp, array &$data)
const int VIEW_MODE_SINGLE
setSubTabs(int $a_view_mode)
const string LNG_AUTH_SAML_USER_MAPPING
getUnsafeGetCommands()
This method must return a list of unsafe GET commands.
const array IGNORED_USER_FIELDS
showIdpSettingsCommand(?StandardForm $form=null)
const string MESSAGE_TYPE_SUCCESS
getSettingsForm(array $values=[])
readonly ilToolbarGUI $toolbar
const string MESSAGE_TYPE_FAILURE
const string PERMISSION_WRITE
readonly ilCtrlInterface $ctrl
readonly ILIAS UI Factory $ui_factory
getSafePostCommands()
This method must return a list of safe POST commands.
showNewIdpFormCommand(?StandardForm $form=null)
readonly RBACServices $rbac
initUserAttributeMapping()
const string METADATA_STORAGE_KEY
readonly Profile $profile
readonly ILIAS UI Renderer $ui_renderer
const string LNG_SAVED_SUCCESSFULLY
storeMetadata(ilSamlIdp $idp, string $metadata)
readonly Refinery $refinery
ensureAccess(string $operation)
readonly ilErrorHandling $error_handler
showSettingsCommand(?StandardForm $form=null)
const int VIEW_MODE_GLOBAL
saveUserAttributeMappingCommand()
const string LNG_LOGIN_FORM
const string METADATA_ENTITY_ID
readonly GlobalHttpState $http_state
handleTableActionsCommand()
showUserAttributeMappingFormCommand(?ilPropertyFormGUI $form=null)
metadataValidationConstraint(?string &$medadata_entity_id=null)
__construct(private readonly int $ref_id)
const string REQUEST_PARAM_SAML_IDP_ID
ilExternalAuthUserAttributeMapping $mapping
const string REQUEST_PARAM_SAML_IDP_IDS
readonly ilGlobalTemplateInterface $tpl
getUserAttributeMappingForm()
const string PROP_UPDATE_SUFFIX
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a text property in a property form.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static _sortIds(array $a_ids, string $a_table, string $a_field, string $a_id_name)
Function that sorts ids by a given table field using WHERE IN E.g: __sort(array(6,...
Interface GlobalHttpState.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const string CMD_TABLE_ACTIONS
const string CMD_LIST_IDPS
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.