diff --git a/dictionaries/perun.definition.json b/dictionaries/perun.definition.json index 48738f7be5562fa6fd9c9a6dc4a26b514355cddd..95c03762a4318817920e5a542bd105760f360e43 100644 --- a/dictionaries/perun.definition.json +++ b/dictionaries/perun.definition.json @@ -178,5 +178,17 @@ "403_is_eligible_default_contact": { "en": "If you think you have used an account which meets the criteria, and you are still prevented from logging in to the service, please contact us at", "cs": "Pokud si myslĂte, Ĺľe pouĹľĂváte správnĂ˝ účet a pĹ™Ăstup je Vám odmĂtnut neprávem, prosĂme kontakujte nás na" + }, + "create_member_exception_text": { + "en": "Error occured when activating account. Please try again later.", + "cs": "PĹ™i aktivovánà účtu se objevila chyba. Zkuste to prosĂm za chvĂli." + }, + "create_member_success_text": { + "en": "Your account was successfully activated. Changes should be noticeable within 5-10 minutes.", + "cs": "Váš účet byl ĂşspěšnÄ› aktivován. ZmÄ›ny by se mÄ›ly projevit do 5-10 minut." + }, + "create_member_button": { + "en": "Continue", + "cs": "PokraÄŤovat" } } diff --git a/lib/AdapterRpc.php b/lib/AdapterRpc.php index 95a2291b685f2e11899e0edaff04d30abe0f2c12..fb07474584b05c27edca0e6670a6f36808269a67 100644 --- a/lib/AdapterRpc.php +++ b/lib/AdapterRpc.php @@ -844,6 +844,24 @@ class AdapterRpc extends Adapter return $facilitiesWithAttributes; } + public function getExtSourceByName(string $extSourceName) + { + return $this->connector->get( + 'extSourcesManager', + 'getExtSourceByName', + ['name' => $extSourceName] + ); + } + + public function createMember(int $voId, int $extSourceId, string $extLogin) + { + $this->connector->post( + 'membersManager', + 'createMember', + ['vo' => $voId, 'extSource' => $extSourceId, "login" => $extLogin] + ); + } + private function getAttributes($perunAttrs, $attrNamesMap) { $attributes = []; diff --git a/lib/Auth/Process/PerunCreateMember.php b/lib/Auth/Process/PerunCreateMember.php new file mode 100644 index 0000000000000000000000000000000000000000..e911ce4cd004be7dac9e725816f76895d14bf2d8 --- /dev/null +++ b/lib/Auth/Process/PerunCreateMember.php @@ -0,0 +1,125 @@ +<?php + +namespace SimpleSAML\Module\perun\Auth\Process; + +use SimpleSAML\Auth\State; +use SimpleSAML\Configuration; +use SimpleSAML\Auth\ProcessingFilter; +use SimpleSAML\Error\Exception; +use SimpleSAML\Module; +use SimpleSAML\Module\perun\AdapterRpc; +use SimpleSAML\Module\perun\Exception as PerunException; +use SimpleSAML\Module\perun\PerunConstants; +use SimpleSAML\Utils\HTTP; + +class PerunCreateMember extends ProcessingFilter +{ + public const TEMPLATE_URL = 'perun:perun-create-member-tpl.php'; + + public const REDIRECT_URL = 'perun/perun_create_member.php'; + + public const CALLBACK_URL = 'perun/perun_create_member_callback.php'; + + public const STAGE = 'perun:PerunCreateMember'; + + public const PARAM_WAS_EXCEPTION = 'was_exception'; + + public const PARAM_STATE_ID = PerunConstants::STATE_ID; + + public const PARAM_CALLBACK = 'callback'; + + public const DEBUG_PREFIX = self::STAGE . ' - '; + + public const UID_ATTR = 'uid_attr'; + + public const IDP_ENTITY_ID = 'idp_entity_id'; + + public const VO_SHORT_NAME = 'vo_short_name'; + + private $config; + + private $userIdAttr; + + private $adapter; + + private $idpEntityId; + + private $voShortName; + + public function __construct($config = null, $reserved = null) + { + if ($config) { + parent::__construct($config, $reserved); + } + $this->config = Configuration::loadFromArray($config); + $this->userIdAttr = $this->config->getString(self::UID_ATTR, null); + $this->voShortName = $this->config->getString(self::VO_SHORT_NAME, null); + $this->idpEntityId = $this->config->getString(self::IDP_ENTITY_ID, null); + + $this->adapter = new AdapterRpc(); + + if (empty($this->userIdAttr)) { + throw new Exception( + self::DEBUG_PREFIX . + 'Invalid configuration: no attribute configured for extracting UID. Use option \'' . self::UID_ATTR . + '\' to configure list of attributes, that should be considered as IDs for a user' + ); + } + + if (empty($this->voShortName)) { + throw new Exception( + self::DEBUG_PREFIX . + 'Invalid configuration: no vo_short_name configured. Use option \'' . self::VO_SHORT_NAME . + '\' to configure VO in which member should be created.' + ); + } + + if (empty($this->idpEntityId)) { + throw new Exception( + self::DEBUG_PREFIX . + 'Invalid configuration: no idp_entity_id configured. Use option \'' . self::IDP_ENTITY_ID . + '\' to configure idp for which this filter will be performed.' + ); + } + } + + public function process(&$request) + { + + if (isset($request[PerunConstants::ATTRIBUTES][$this->userIdAttr[0]])) { + $uid = $request[PerunConstants::ATTRIBUTES][$this->userIdAttr[0]]; + } else { + throw new Exception( + self::DEBUG_PREFIX . 'missing user id attribute in request.' + ); + } + + $alreadyMember = false; + $wasException = false; + try { + $extSource = $this->adapter->getExtSourceByName($this->idpEntityId); + $vo = $this->adapter->getVoByShortName($this->voShortName); + $this->adapter->createMember($vo->getId(), $extSource["id"], $uid); + } catch (PerunException $e) { + if ($e->getName() === 'AlreadyMemberException') { + $alreadyMember = true; + } else { + $wasException = true; + } + } + if ($alreadyMember) { + return; + } + + $stateId = State::saveState($request, self::STAGE); + $url = Module::getModuleURL(self::REDIRECT_URL); + + $params = []; + $params[self::PARAM_WAS_EXCEPTION] = $wasException; + $params[self::PARAM_CALLBACK] = Module::getModuleURL(self::CALLBACK_URL, [ + self::PARAM_STATE_ID => $stateId, + ]); + + HTTP::redirectTrustedURL($url, $params); + } +} diff --git a/templates/perun-create-member-tpl.php b/templates/perun-create-member-tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..958b3cda8affda15c690ae92f2653b897ee3c4f8 --- /dev/null +++ b/templates/perun-create-member-tpl.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +use SimpleSAML\Module\perun\Auth\Process\PerunCreateMember; + +$this->includeAtTemplateBase('includes/header.php'); +?> + + <div class="row"> + <div> + <?php if ($this->data[PerunCreateMember::PARAM_WAS_EXCEPTION]) { ?> + <p><?php echo $this->t('{perun:perun:create_member_exception_text}'); ?></p> + <?php } else { ?> + <p><?php echo $this->t('{perun:perun:create_member_success_text}'); ?></p> + <a class="btn btn-lg btn-block btn-primary" + href="<?php echo $this->data[PerunCreateMember::PARAM_CALLBACK]; ?>"> + <?php echo $this->t('{perun:perun:create_member_button}'); ?> + </a> + <?php } ?> + + </div> + </div> + +<?php +$this->includeAtTemplateBase('includes/footer.php'); +?> \ No newline at end of file diff --git a/www/perun_create_member.php b/www/perun_create_member.php new file mode 100644 index 0000000000000000000000000000000000000000..1efc1736d1101c20f24f30450cba6b8a6e50f596 --- /dev/null +++ b/www/perun_create_member.php @@ -0,0 +1,14 @@ +<?php + +declare(strict_types=1); + +use SimpleSAML\Configuration; +use SimpleSAML\Module\perun\Auth\Process\PerunCreateMember; +use SimpleSAML\XHTML\Template; + +$config = Configuration::getInstance(); +$t = new Template($config, PerunCreateMember::TEMPLATE_URL); +$t->data[PerunCreateMember::PARAM_CALLBACK] = $_REQUEST[PerunCreateMember::PARAM_CALLBACK]; +$t->data[PerunCreateMember::PARAM_WAS_EXCEPTION] = $_REQUEST[PerunCreateMember::PARAM_WAS_EXCEPTION]; + +$t->show(); diff --git a/www/perun_create_member_callback.php b/www/perun_create_member_callback.php new file mode 100644 index 0000000000000000000000000000000000000000..4ba5e340ef26c44c6e897fdb0e4df43b0b28e07f --- /dev/null +++ b/www/perun_create_member_callback.php @@ -0,0 +1,14 @@ +<?php + +use SimpleSAML\Auth\ProcessingChain; +use SimpleSAML\Auth\State; +use SimpleSAML\Error\BadRequest; +use SimpleSAML\Module\perun\Auth\Process\PerunCreateMember; + +if (empty($_REQUEST[PerunCreateMember::PARAM_STATE_ID])) { + throw new BadRequest('Missing required \'' . PerunCreateMember::PARAM_STATE_ID . '\' query parameter.'); +} + +$state = State::loadState($_REQUEST[PerunCreateMember::PARAM_STATE_ID], PerunCreateMember::STAGE); + +ProcessingChain::resumeProcessing($state);