From 83b7be5fbfde6104beee41c06dfd046b24b9ee5f Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Thu, 18 Nov 2021 15:17:57 +0200 Subject: [PATCH 1/3] Refactor COmanage OrgIdentity Handling throw against Error/Error for all classes when a database error occurs --- CHANGELOG.md | 7 + lib/Attributes/SshPublicKey.php | 4 +- lib/Auth/Process/COmanageDbClient.php | 194 +++++-------------- lib/Enrollment/PetitionHandler.php | 4 +- lib/User/AuthenticationEventHandler.php | 4 +- lib/User/OrgIdentity.php | 238 ++++++++++++++++++++++++ 6 files changed, 298 insertions(+), 153 deletions(-) create mode 100644 lib/User/OrgIdentity.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e736f5..e44f0e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [unreleased] + +### Fixed + +- Do not construct the `organization` attribute for a Removed OrgIdentity +- Fixed error handling on database related error + ## [v2.3.0] - 2021-11-15 ### Added diff --git a/lib/Attributes/SshPublicKey.php b/lib/Attributes/SshPublicKey.php index f51f7a4..7752a06 100644 --- a/lib/Attributes/SshPublicKey.php +++ b/lib/Attributes/SshPublicKey.php @@ -64,7 +64,9 @@ public function getSshPublicKeys($personId) . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; diff --git a/lib/Auth/Process/COmanageDbClient.php b/lib/Auth/Process/COmanageDbClient.php index 0cceaf9..44d1aa4 100644 --- a/lib/Auth/Process/COmanageDbClient.php +++ b/lib/Auth/Process/COmanageDbClient.php @@ -141,6 +141,7 @@ class COmanageDbClient extends \SimpleSAML\Auth\ProcessingFilter . ' and not ident.deleted' . ' and ident.identifier_id is null'; + // If the OrgIdentity is of status Removed we will not construct the organization attribute private $profileQuery = "SELECT string_agg(DISTINCT name.given, ',') AS given," . " string_agg(DISTINCT name.family, ',') AS family," . " string_agg(DISTINCT mail.id::text || ':' || mail.mail || ':' || mail.verified::text, ',') AS mail," @@ -150,6 +151,7 @@ class COmanageDbClient extends \SimpleSAML\Auth\ProcessingFilter . " inner join cm_co_org_identity_links ccoil on coi.id = ccoil.org_identity_id and" . " not coi.deleted and not ccoil.deleted and" . " coi.o is not null and coi.o != '' and" + . " coi.status != '" . OrgIdentityStatusEnum::Removed . "' and" . " coi.affiliation is not null and coi.affiliation != ''" . " where ccoil.co_person_id = :coPersonId)," . " (select string_agg(coi.o, ',') as organization" @@ -178,26 +180,6 @@ class COmanageDbClient extends \SimpleSAML\Auth\ProcessingFilter . " AND name.primary_name = true" . " GROUP BY person.id;"; - private $orgIdIdentQuery = "select ident.type," - . " ident.identifier," - . " ident.login," - . " ident.org_identity_id," - . " coi.valid_from as org_valid_from," - . " coi.valid_through as org_valid_through" - . " from cm_identifiers as ident" - . " inner join cm_org_identities coi on ident.org_identity_id = coi.id" - . " and not ident.deleted" - . " and ident.identifier_id is null" - . " and not coi.deleted and coi.org_identity_id is null" - . " inner join cm_co_org_identity_links ccoil on coi.id = ccoil.org_identity_id" - . " and not ccoil.deleted" - . " and ccoil.co_org_identity_link_id is null" - . " inner join cm_co_people ccp on ccoil.co_person_id = ccp.id" - . " and not ccp.deleted" - . " and ccp.co_person_id is null" - . " where ident.type in (:coOrgIdType)" - . ":isLogin" // XXX This is a placeholder for the entire line" - . " and ccp.id = :coPersonId"; private $certQuery = 'SELECT' . ' DISTINCT(cert.subject)' @@ -417,8 +399,12 @@ public function process(&$state) $auth_event->recordAuthenticationEvent($state['Attributes'][$this->userIdAttribute][0]); // Get all the data from the COPerson and import them in the state $this->retrieveCOPersonData($state); - } catch (Error\Exception $e) { - $e->show(); + } catch (Error\Error $e) { + if(method_exists($e, 'show')) { + $e->show(); + } else { + $this->showError($e); + } } } @@ -459,7 +445,9 @@ private function getBasicInfo($orgId) return $result; } } else { - throw new Error\Exception('Failed to communicate with COmanage Registry: '.var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return null; @@ -491,128 +479,14 @@ private function getCoPersonIdentifier($personId, $identifier_type) return $result['identifier']; } } else { - throw new Error\Exception('Failed to communicate with COmanage Registry: '.var_export($db->getLastError(), true)); - } - - return null; - } - - /** - * Fetch all the Identifiers linked to OrgIdentities. Define whether these identifiers are authenticators or not - * - * @param string $personId The CO Person ID - * @param array $orgIdentTypeList - * @param bool $isLogin , true, false or null are allowed - * - * @return array|null Return an array of identifiers, column headers [ident.type, ident.identifier, ident.login, ident.org_identity_id] - * @throws Exception - */ - private function getOrgIdentifiers($personId, $orgIdentTypeList, $isLogin=null) - { - Logger::debug('[attrauthcomanage] getOrgIdentifiers: personId=' . var_export($personId, true)); - - $db = Database::getInstance(); - $this->orgIdIdentQuery = str_replace(':coOrgIdType', - "'" . implode("','", $orgIdentTypeList) . "'", - $this->orgIdIdentQuery); - if(is_null($isLogin)) { - $isLoginConditionStr = ''; - } else { - $isLoginCondition = ($isLogin) ? 'true' : 'false'; - $isLoginConditionStr = ' and ident.login=' . $isLoginCondition; + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } - $this->orgIdIdentQuery = str_replace(':isLogin', - $isLoginConditionStr, - $this->orgIdIdentQuery); - $queryParams = [ - 'coPersonId' => [$personId, PDO::PARAM_INT], - ]; - $stmt = $db->read($this->orgIdIdentQuery, $queryParams); - - if ($stmt->execute()) { - if ($result = $stmt->fetchall(PDO::FETCH_GROUP|PDO::FETCH_ASSOC)) { - Logger::debug("[attrauthcomanage] getOrgIdentifiers: result=" - . var_export($result, true)); - return $result; - } - } else { - throw new Exception('Failed to communicate with COmanage Registry: '.var_export($db->getLastError(), true)); - } return null; } - /** - * Check whether the identifier fetched from the IdP is available in the list of my Identifiers - * and marked as a login identifier - * - * @param string $idpIdent Identifier provided by the Identity Provider - * @param array $identsList List of OrgIdentity Identifiers - * - * @return bool - */ - private function isIdpIdentLogin($idpIdent, $identsList) - { - if( empty($identsList) || empty($idpIdent)) { - return false; - } - foreach ($identsList as $identifierTypes) { - foreach($identifierTypes as $ident) { - if( $ident['identifier'] === $idpIdent - && $ident['login']) { - return true; - } - } - } - return false; - } - - /** - * Check whether the identifier fetched from the IdP has expired - * If valid from and valid through fields are empty we assume that the Identifier will never expire - * - * @param string $idpIdent Identifier provided by the Identity Provider - * @param array $identsList List of OrgIdentity Identifiers - * - * @return bool|null true(is expired), false(is not expired), null if either of the parameters are empty - * @throws Exception - * @todo make timezone configuration - */ - private function isIdpIdentExpired($idpIdent, $identsList) - { - if( empty($identsList) || empty($idpIdent)) { - return null; - } - foreach ($identsList as $identifierTypes) { - foreach($identifierTypes as $ident) { - if( $ident['identifier'] === $idpIdent) { - Logger::debug("[attrauthcomanage] isIdpIdentExpired: org_valid_through = " . var_export($ident['org_valid_through'], true)); - Logger::debug("[attrauthcomanage] isIdpIdentExpired: org_valid_from = " . var_export($ident['org_valid_from'], true)); - $current_date = new \DateTime('now', new \DateTimeZone('Etc/UTC')); - if (empty($ident['org_valid_from']) && empty($ident['org_valid_through'])) { - return false; - } elseif (empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { - $valid_through = new \DateTime($ident['org_valid_through'], new \DateTimeZone('Etc/UTC')); - return !($valid_through >= $current_date); - } elseif (!empty($ident['org_valid_from']) && empty($ident['org_valid_through'])) { - $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); - return !($current_date >= $valid_from); - } elseif (!empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { - $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); - $valid_through = new \DateTime($ident['org_valid_through'], new \DateTimeZone('Etc/UTC')); - if ($valid_through >= $current_date - && $current_date > $valid_from) { - return false; - } else { - return true; - } - } - } - } - } - return false; - } - /** * Execute the profileQuery and construct the result set @@ -648,7 +522,9 @@ private function getProfile($personId) . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return null; @@ -763,7 +639,9 @@ private function getCerts($personId) . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; @@ -832,7 +710,9 @@ private function getMemberships($co_id, $co_person_id) . var_export($result, true) ); } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; @@ -1173,24 +1053,34 @@ private function retrieveCOPersonData(&$state) // XXX Scenario: The user ID module creates an Identifier. We must check that this identifier is enlisted // XXX in the list of available OrgIdentities of the CO Person and is a valid authenticator. // XXX Upon success we return the Identifier of the COPerson - $orgIdentifiers = $this->getOrgIdentifiers($basicInfo['id'], $this->coOrgIdType, true); + $org_identity = new User\OrgIdentity($orgId); + $orgIdentifiers = $org_identity->getLoginOrgIdentifiers($basicInfo['id'], $this->coOrgIdType); + Logger::debug('[attrauthcomanage] process: orgIdentifiers=' . var_export($orgIdentifiers, true)); if (!empty($orgIdentifiers)) { $state['orgIndentifiersList'] = $orgIdentifiers; } // XXX Check if the identifier is an authenticator - if (!$this->isIdpIdentLogin($orgId, $orgIdentifiers)) { + if (!$org_identity->isIdpIdentLogin()) { // Normally, this should not happen $err_msg = 'The identifier - ' . $orgId . ' -
is not present in your account or is not a valid authenticator.
Please contact support for further assistance.'; - throw new Exception($err_msg); + $this->showError($err_msg); } // XXX Check if the identifier is valid or has expired - if ($this->isIdpIdentExpired($orgId, $orgIdentifiers)) { + if ($org_identity->isIdpIdentExpired()) { // Normally, this should not happen $err_msg = "The identifier - " . $orgId . " - is not a valid authenticator."; $err_msg .= "
The subscription from " . end($state['saml:AuthenticatingAuthority']) . " expired."; $err_msg .= "
Please contact support for further assistance."; - throw new Exception($err_msg); + $this->showError($err_msg); + } + + if ($org_identity->isIdpRemoved()) { + // Normally, this should not happen + $err_msg = "The identifier - " . $orgId . " - is not a valid authenticator."; + $err_msg .= "
The subscription from " . end($state['saml:AuthenticatingAuthority']) . " has been Removed."; + $err_msg .= "
Please contact support for further assistance."; + $this->showError($err_msg); } $loginId = $this->getCoPersonIdentifier($basicInfo['id'], $this->coUserIdType); @@ -1634,7 +1524,9 @@ private function getTermsAgreementValid($personId) . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; @@ -1675,7 +1567,9 @@ private function getTermsAgreementRevisioned($personId) . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; diff --git a/lib/Enrollment/PetitionHandler.php b/lib/Enrollment/PetitionHandler.php index 0a31bad..e68285a 100644 --- a/lib/Enrollment/PetitionHandler.php +++ b/lib/Enrollment/PetitionHandler.php @@ -130,7 +130,9 @@ protected function runQueryPetitionFromPersonIdPetStatus($petition_status, $co_i . var_export($result, true)); return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return $result; diff --git a/lib/User/AuthenticationEventHandler.php b/lib/User/AuthenticationEventHandler.php index 4ee55ca..7019691 100644 --- a/lib/User/AuthenticationEventHandler.php +++ b/lib/User/AuthenticationEventHandler.php @@ -185,7 +185,9 @@ public function getLastAuthenticationEvent($identifier): array return $result; } else { - throw new Exception('Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)); + throw new Error\Error( + ['UNHANDLEDEXCEPTION', 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true)] + ); } return []; diff --git a/lib/User/OrgIdentity.php b/lib/User/OrgIdentity.php new file mode 100644 index 0000000..e67e4d0 --- /dev/null +++ b/lib/User/OrgIdentity.php @@ -0,0 +1,238 @@ +org_identity_identifier = $org_identity_identifier; + } + + /** + * Fetch all the Login enabled Identifiers linked to OrgIdentities. Define whether these identifiers are authenticators or not + * + * @param string $personId The CO Person ID + * @param array $orgIdentTypeList + * + * @return array|null Return an array of identifiers, column headers [ident.type, ident.identifier, ident.login, ident.org_identity_id] + * @throws Exception + */ + public function getLoginOrgIdentifiers($personId, $orgIdentTypeList) + { + $this->org_ident_list = $this->getOrgIdentifiers($personId, $orgIdentTypeList, true); + + return $this->org_ident_list; + } + + /** + * Fetch all the NON Login Identifiers linked to OrgIdentities. Define whether these identifiers are authenticators or not + * + * @param string $personId The CO Person ID + * @param array $orgIdentTypeList + * + * @return array|null Return an array of identifiers, column headers [ident.type, ident.identifier, ident.login, ident.org_identity_id] + * @throws Exception + */ + public function getNonLoginOrgIdentifiers($personId, $orgIdentTypeList) + { + $this->org_ident_list = $this->getOrgIdentifiers($personId, $orgIdentTypeList, false); + + return $this->org_ident_list; + } + + /** + * Fetch all the Identifiers linked to OrgIdentities. Define whether these identifiers are authenticators or not + * + * @param string $personId The CO Person ID + * @param array $orgIdentTypeList + * @param bool $isLogin , true, false or null are allowed + * + * @return array|null Return an array of identifiers, column headers [ident.type, ident.identifier, ident.login, ident.org_identity_id] + * @throws Exception + */ + private function getOrgIdentifiers($personId, $orgIdentTypeList, $isLogin = null) + { + Logger::debug('[attrauthcomanage] getOrgIdentifiers: personId=' . var_export($personId, true)); + + $db = Database::getInstance(); + $this->orgIdIdentQuery = str_replace( + ':coOrgIdType', + "'" . implode("','", $orgIdentTypeList) . "'", + $this->orgIdIdentQuery + ); + if (is_null($isLogin)) { + $isLoginConditionStr = ''; + } else { + $isLoginCondition = ($isLogin) ? 'true' : 'false'; + $isLoginConditionStr = ' and ident.login=' . $isLoginCondition; + } + + $this->orgIdIdentQuery = str_replace( + ':isLogin', + $isLoginConditionStr, + $this->orgIdIdentQuery + ); + $queryParams = [ + 'coPersonId' => [$personId, PDO::PARAM_INT], + ]; + $stmt = $db->read($this->orgIdIdentQuery, $queryParams); + + if ($stmt->execute()) { + if ($result = $stmt->fetchall(PDO::FETCH_GROUP | PDO::FETCH_ASSOC)) { + Logger::debug( + "[attrauthcomanage] getOrgIdentifiers: result=" + . var_export($result, true) + ); + + return $result; + } + } else { + throw new Error\Error( + [ + 'UNHANDLEDEXCEPTION', + 'Failed to communicate with COmanage Registry: ' . var_export($db->getLastError(), true) + ] + ); + } + + return null; + } + + /** + * Check whether the identifier fetched from the IdP is available in the list of my Identifiers + * and marked as a login identifier + * + * @return bool + */ + public function isIdpIdentLogin(): bool + { + if (empty($this->org_ident_list) || empty($this->org_identity_identifier)) { + return false; + } + foreach ($this->org_ident_list as $identifierTypes) { + foreach ($identifierTypes as $ident) { + if ($ident['identifier'] === $this->org_identity_identifier + && $ident['login']) { + return true; + } + } + } + + return false; + } + + /** + * Check whether the identifier fetched from the IdP is available in the list of my Identifiers + * and marked as Removed + * + * @return bool + */ + public function isIdpRemoved(): bool + { + if (empty($this->org_ident_list) || empty($this->org_identity_identifier)) { + return false; + } + foreach ($this->org_ident_list as $identifierTypes) { + foreach ($identifierTypes as $ident) { + if ($ident['identifier'] === $this->org_identity_identifier + && $ident['org_status'] == OrgIdentityStatusEnum::Removed) { + return true; + } + } + } + + return false; + } + + /** + * Check whether the identifier fetched from the IdP has expired + * If valid from and valid through fields are empty we assume that the Identifier will never expire + * + * @return bool|null true(is expired), false(is not expired), null if either of the parameters are empty + * @throws Exception + * @todo make timezone configuration + */ + public function isIdpIdentExpired() + { + if (empty($this->org_ident_list) || empty($this->org_identity_identifier)) { + return null; + } + foreach ($this->org_ident_list as $identifierTypes) { + foreach ($identifierTypes as $ident) { + if ($ident['identifier'] === $this->org_identity_identifier) { + $current_date = new \DateTime('now', new \DateTimeZone('Etc/UTC')); + if (empty($ident['org_valid_from']) && empty($ident['org_valid_through'])) { + return false; + } elseif (empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { + $valid_through = new \DateTime($ident['org_valid_through'], new \DateTimeZone('Etc/UTC')); + + return !($valid_through >= $current_date); + } elseif (!empty($ident['org_valid_from']) && empty($ident['org_valid_through'])) { + $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); + + return !($current_date >= $valid_from); + } elseif (!empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { + $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); + $valid_through = new \DateTime($ident['org_valid_through'], new \DateTimeZone('Etc/UTC')); + if ($valid_through >= $current_date + && $current_date > $valid_from) { + return false; + } else { + return true; + } + } + } + } + } + + return false; + } +} \ No newline at end of file From fd4a78a93d0b089b2c03cb73166a8bd0eab806d2 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Mon, 22 Nov 2021 12:09:08 +0200 Subject: [PATCH 2/3] Refactor OrgIdentity error states to use showNoty --- dictionaries/noty.definition.json | 50 ++++++++++++++++++--------- lib/Auth/Process/COmanageDbClient.php | 44 +++++++++++++---------- lib/User/OrgIdentity.php | 42 ++++++++++++++++++++-- templates/noty.tpl.php | 7 ++-- 4 files changed, 104 insertions(+), 39 deletions(-) diff --git a/dictionaries/noty.definition.json b/dictionaries/noty.definition.json index 47912ac..100c293 100644 --- a/dictionaries/noty.definition.json +++ b/dictionaries/noty.definition.json @@ -1,30 +1,42 @@ { - "yes": { - "en": "Resend Verfication Email" + "account_pending_confirmation": { + "en": "Account in Pending Email Confirmation Status" }, - "no": { - "en": "Abort Login" + "default_status": { + "en": "Action Required" }, - "title": { - "en": "Please verify your email address by clicking the link in the email we sent you" + "invitation_restored": { + "en": "Invitation has been restored." }, "msg_title": { "en": "This is your current status:" }, - "default_status": { - "en": "Action Required" + "no": { + "en": "Abort Login" }, - "account_pending_confirmation": { - "en": "Account in Pending Email Confirmation Status" + "org_identity_expired_banner": { + "en": "Organization Identity Expired" }, - "invitation_restored": { - "en": "Invitation has been restored." + "org_identity_expired_description": { + "en": "The identifier - %ORGID% - is not a valid authenticator. The subscription from %AUTHNAUTHORITY% has Expired.
Please contact our support and make sure to include the error message above." + }, + "org_identity_nologin_banner": { + "en": "Organization Identity is not login enabled" + }, + "org_identity_nologin_description": { + "en": "The identifier - %ORGID% - is not a valid authenticator. Please contact our support and make sure to include the error message above." + }, + "org_identity_removed_banner": { + "en": "Organization Identity Removed" + }, + "org_identity_removed_description": { + "en": "The identifier - %ORGID% - is not a valid authenticator. The subscription from %AUTHNAUTHORITY% has been Removed.
Please contact our support and make sure to include the error message above." }, "petition_info": { "en": "The identifier %ORGIDENT% is in Email Pending Confirmation Status. Please check your Mail %MAIL% Inbox or Spam for further information. " }, - "petition_user_notify": { - "en": "

We have sent an email with a confirmation link to your email address %MAIL%. In order to complete the sign-up process, please click the confirmation link. If you do not find the email in your Inbox, please check your Spam or Junk folder for an email from \"RCIAM Notifications\". If you do find the email in these folders, mark the email as \"safe\" or \"not spam\" to ensure that you receive any future notifications about your RCIAM ID.

You can also click the \"Resend Verfication Email\" button below to have another email sent to you." + "petition_invalidate_msg": { + "en": "

This action will invalidate any previous confirmation links.

" }, "petition_token_expired": { "en": "
Email confirmation token EXPIRED  %DATE% ago
" @@ -32,7 +44,13 @@ "petition_token_expires": { "en": "
Email confirmation token EXPIRES in  %DATE%
" }, - "petition_invalidate_msg": { - "en": "

This action will invalidate any previous confirmation links.

" + "petition_user_notify": { + "en": "

We have sent an email with a confirmation link to your email address %MAIL%. In order to complete the sign-up process, please click the confirmation link. If you do not find the email in your Inbox, please check your Spam or Junk folder for an email from \"RCIAM Notifications\". If you do find the email in these folders, mark the email as \"safe\" or \"not spam\" to ensure that you receive any future notifications about your RCIAM ID.

You can also click the \"Resend Verfication Email\" button below to have another email sent to you." + }, + "resend_confirmation_email": { + "en": "Please verify your email address by clicking the link in the email we sent you" + }, + "yes": { + "en": "Resend Verfication Email" } } diff --git a/lib/Auth/Process/COmanageDbClient.php b/lib/Auth/Process/COmanageDbClient.php index 44d1aa4..bc06f69 100644 --- a/lib/Auth/Process/COmanageDbClient.php +++ b/lib/Auth/Process/COmanageDbClient.php @@ -349,6 +349,7 @@ public function process(&$state) $pt_noty = [ 'level' => $petition_handler->getBannerClass(), 'description' => $petition_handler->getUserNotify(), + 'title' => 'resend_confirmation_email', //'status' => 'account_pending_confirmation', // This is a dictionary key 'icon' => 'email.gif', 'yes_btn_show' => true, @@ -400,11 +401,7 @@ public function process(&$state) // Get all the data from the COPerson and import them in the state $this->retrieveCOPersonData($state); } catch (Error\Error $e) { - if(method_exists($e, 'show')) { - $e->show(); - } else { - $this->showError($e); - } + $e->show(); } } @@ -1062,25 +1059,36 @@ private function retrieveCOPersonData(&$state) } // XXX Check if the identifier is an authenticator if (!$org_identity->isIdpIdentLogin()) { - // Normally, this should not happen - $err_msg = 'The identifier - ' . $orgId . ' -
is not present in your account or is not a valid authenticator.
Please contact support for further assistance.'; - $this->showError($err_msg); + // Redirect to User notification + $pt_noty = [ + 'level' => $org_identity->getBannerClass(), + 'description' => $org_identity->getUserNotify($state, 'nologin'), + 'status' => 'org_identity_nologin_banner', // This is a dictionary key + 'yes_btn_show' => false, + ]; + $this->showNoty($pt_noty, $state); } // XXX Check if the identifier is valid or has expired if ($org_identity->isIdpIdentExpired()) { - // Normally, this should not happen - $err_msg = "The identifier - " . $orgId . " - is not a valid authenticator."; - $err_msg .= "
The subscription from " . end($state['saml:AuthenticatingAuthority']) . " expired."; - $err_msg .= "
Please contact support for further assistance."; - $this->showError($err_msg); + // Redirect to User notification + $pt_noty = [ + 'level' => $org_identity->getBannerClass(), + 'description' => $org_identity->getUserNotify($state, 'expired'), + 'status' => 'org_identity_expired_banner', // This is a dictionary key + 'yes_btn_show' => false, + ]; + $this->showNoty($pt_noty, $state); } if ($org_identity->isIdpRemoved()) { - // Normally, this should not happen - $err_msg = "The identifier - " . $orgId . " - is not a valid authenticator."; - $err_msg .= "
The subscription from " . end($state['saml:AuthenticatingAuthority']) . " has been Removed."; - $err_msg .= "
Please contact support for further assistance."; - $this->showError($err_msg); + // Redirect to User notification + $pt_noty = [ + 'level' => $org_identity->getBannerClass(), + 'description' => $org_identity->getUserNotify($state, 'removed'), + 'status' => 'org_identity_removed_banner', // This is a dictionary key + 'yes_btn_show' => false, + ]; + $this->showNoty($pt_noty, $state); } $loginId = $this->getCoPersonIdentifier($basicInfo['id'], $this->coUserIdType); diff --git a/lib/User/OrgIdentity.php b/lib/User/OrgIdentity.php index e67e4d0..afbc5d7 100644 --- a/lib/User/OrgIdentity.php +++ b/lib/User/OrgIdentity.php @@ -12,6 +12,11 @@ class OrgIdentity { + /** + * @var string + */ + private $banner_class = 'info'; + /** * @var */ @@ -154,6 +159,8 @@ private function getOrgIdentifiers($personId, $orgIdentTypeList, $isLogin = null */ public function isIdpIdentLogin(): bool { + $this->banner_class = 'warning'; + if (empty($this->org_ident_list) || empty($this->org_identity_identifier)) { return false; } @@ -161,6 +168,8 @@ public function isIdpIdentLogin(): bool foreach ($identifierTypes as $ident) { if ($ident['identifier'] === $this->org_identity_identifier && $ident['login']) { + // Reset the status of the banner + $this->banner_class = 'info'; return true; } } @@ -184,6 +193,7 @@ public function isIdpRemoved(): bool foreach ($identifierTypes as $ident) { if ($ident['identifier'] === $this->org_identity_identifier && $ident['org_status'] == OrgIdentityStatusEnum::Removed) { + $this->banner_class = 'error'; return true; } } @@ -213,11 +223,15 @@ public function isIdpIdentExpired() return false; } elseif (empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { $valid_through = new \DateTime($ident['org_valid_through'], new \DateTimeZone('Etc/UTC')); - + if(!($valid_through >= $current_date)) { + $this->banner_class = 'error'; + } return !($valid_through >= $current_date); } elseif (!empty($ident['org_valid_from']) && empty($ident['org_valid_through'])) { $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); - + if(!($current_date >= $valid_from)) { + $this->banner_class = 'error'; + } return !($current_date >= $valid_from); } elseif (!empty($ident['org_valid_from']) && !empty($ident['org_valid_through'])) { $valid_from = new \DateTime($ident['org_valid_from'], new \DateTimeZone('Etc/UTC')); @@ -226,6 +240,7 @@ public function isIdpIdentExpired() && $current_date > $valid_from) { return false; } else { + $this->banner_class = 'error'; return true; } } @@ -235,4 +250,27 @@ public function isIdpIdentExpired() return false; } + + /** + * $params array $state + * + * @return array + */ + public function getUserNotify($state, $status) { + $dictionary_list = []; + $dictionary_list['org_identity_'. $status . '_description'] = [ + '%ORGID%' => $this->org_identity_identifier, + '%AUTHNAUTHORITY%' => end($state['saml:AuthenticatingAuthority']) + ]; + + return $dictionary_list; + } + + /** + * @return string + */ + public function getBannerClass(): string + { + return $this->banner_class; + } } \ No newline at end of file diff --git a/templates/noty.tpl.php b/templates/noty.tpl.php index 0d47202..439b9af 100644 --- a/templates/noty.tpl.php +++ b/templates/noty.tpl.php @@ -69,7 +69,9 @@ data['noty']['icon'])): ?> -

t('{attrauthcomanage:noty:title}') ?>

+ data['noty']['title'])) : ?> +

t('{attrauthcomanage:noty:' . $this->data['noty']['title'] . '}') ?>

+
@@ -87,8 +89,7 @@

-data['yesTarget']) - && $yes_button_show): ?> +data['yesTarget']) && $yes_button_show): ?>
Date: Wed, 24 Nov 2021 19:06:38 +0200 Subject: [PATCH 3/3] Fix user messages.Use showNoty to notify Users for suspended status --- dictionaries/noty.definition.json | 26 ++++++++++++++++---------- lib/Auth/Process/COmanageDbClient.php | 12 ++++++++++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/dictionaries/noty.definition.json b/dictionaries/noty.definition.json index 100c293..4eacd00 100644 --- a/dictionaries/noty.definition.json +++ b/dictionaries/noty.definition.json @@ -15,34 +15,34 @@ "en": "Abort Login" }, "org_identity_expired_banner": { - "en": "Organization Identity Expired" + "en": "Identity Expired" }, "org_identity_expired_description": { - "en": "The identifier - %ORGID% - is not a valid authenticator. The subscription from %AUTHNAUTHORITY% has Expired.
Please contact our support and make sure to include the error message above." + "en": "Your identity (%ORGID%) has expired. Please contact our support and make sure to include the error message above." }, "org_identity_nologin_banner": { - "en": "Organization Identity is not login enabled" + "en": "Identity not enabled for login" }, "org_identity_nologin_description": { - "en": "The identifier - %ORGID% - is not a valid authenticator. Please contact our support and make sure to include the error message above." + "en": "Your identity (%ORGID%) cannot be used for login. Please contact our support and make sure to include the error message above." }, "org_identity_removed_banner": { - "en": "Organization Identity Removed" + "en": "Identity not valid for login" }, "org_identity_removed_description": { - "en": "The identifier - %ORGID% - is not a valid authenticator. The subscription from %AUTHNAUTHORITY% has been Removed.
Please contact our support and make sure to include the error message above." + "en": "Your identity (%ORGID%) has been removed. Please contact our support and make sure to include the error message above." }, "petition_info": { - "en": "The identifier %ORGIDENT% is in Email Pending Confirmation Status. Please check your Mail %MAIL% Inbox or Spam for further information. " + "en": "The identifier %ORGIDENT% is in Email Pending Confirmation Status. Please check your Mail %MAIL% Inbox or Spam for further information. " }, "petition_invalidate_msg": { "en": "

This action will invalidate any previous confirmation links.

" }, "petition_token_expired": { - "en": "
Email confirmation token EXPIRED  %DATE% ago
" + "en": "
Email confirmation token EXPIRED  %DATE% ago
" }, "petition_token_expires": { - "en": "
Email confirmation token EXPIRES in  %DATE%
" + "en": "
Email confirmation token EXPIRES in  %DATE%
" }, "petition_user_notify": { "en": "

We have sent an email with a confirmation link to your email address %MAIL%. In order to complete the sign-up process, please click the confirmation link. If you do not find the email in your Inbox, please check your Spam or Junk folder for an email from \"RCIAM Notifications\". If you do find the email in these folders, mark the email as \"safe\" or \"not spam\" to ensure that you receive any future notifications about your RCIAM ID.

You can also click the \"Resend Verfication Email\" button below to have another email sent to you." @@ -50,7 +50,13 @@ "resend_confirmation_email": { "en": "Please verify your email address by clicking the link in the email we sent you" }, + "user_suspended": { + "en": "Your identity (%ORGID%) has been suspended. Please contact our support and make sure to include the error message above" + }, + "user_suspended_title": { + "en": "Identity suspended" + }, "yes": { - "en": "Resend Verfication Email" + "en": "Resend Verification Email" } } diff --git a/lib/Auth/Process/COmanageDbClient.php b/lib/Auth/Process/COmanageDbClient.php index bc06f69..9f01ba0 100644 --- a/lib/Auth/Process/COmanageDbClient.php +++ b/lib/Auth/Process/COmanageDbClient.php @@ -317,14 +317,22 @@ public function process(&$state) } - if (empty($basicInfo['id']) // User is NOT present in the Registry OR || empty($basicInfo['status']) // User has no status in the Registry OR || ($basicInfo['status'] !== StatusEnum::Active // (User is NOT ACTIVE in the Registry AND && $basicInfo['status'] !== StatusEnum::GracePeriod)) { // User is NOT in GRACE PERIOD in the Registry) // XXX User is Suspended if ($basicInfo['status'] === StatusEnum::Suspended) { // User is SUSPENDED - $this->showError('attrauthcomanage:attrauthcomanage:exception_SUSPENDED_USER'); + // Redirect to User notification + $pt_noty = [ + 'level' => 'error', + 'description' => ['user_suspended' => [ + '%ORGID%' => $orgId, + ]], + 'status' => 'user_suspended_title', // This is a dictionary key + 'yes_btn_show' => false, + ]; + $this->showNoty($pt_noty, $state); } // XXX Petition in Pending Confirmation if ($basicInfo['status'] === StatusEnum::PendingConfirmation) { // User is PENDING CONFIRMATION