Skip to content
This repository has been archived by the owner on Feb 15, 2025. It is now read-only.

Commit

Permalink
Merge branch 'release-2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasLiampotis committed Jul 12, 2021
2 parents 13e40df + 4c82bf4 commit d4c2b20
Show file tree
Hide file tree
Showing 44 changed files with 4,316 additions and 20 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ 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).

## [v2.1.0] - 2021-07-12

### Added

- Support for resending email verificaton when the user status is in pending confirmation

#### Changed

- Construct VO membership entitlements if the user is active or in grace period

## [v2.0.5] - 2021-04-08

### Added
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ The following authproc filter configuration options are supported:
* `voRoles`: An array of default roles to be used for the composition of the entitlements.
* `urnAuthority`: A string to use as the authority of the generated `eduPersonEntitlement` URN values containing group membership and role information.
* `registryUrls`: An array of COmanage endpoints representing standard Enrollment Flow types. All the four endpoints are mandatory.
* `comanage_api_username`: COmanage REST API username.
* `comanage_api_password`: COmanage REST API password.

* Optional:
* `voGroupPrefix`: An array of group prefixes per (CO)mmunity to be used for the composition of the entitlements. Defaults to `urlencode($co_name) . ":group"`.
* `coUserIdType`: A string that indicates the type of the identifier that the users have. Defaults to `epuid`.
Expand Down Expand Up @@ -110,6 +113,8 @@ Note: In case you need to change the format of the entitlements you need to modi
'urnNamespace' => 'urn:mace:example.org',
'urnAuthority' => 'example.eu',
'mergeEntitlements' => false,
'comanage_api_username' => 'rciam',
'comanage_api_password' => 'password',
'certificate' => false,
'retrieveSshKeys' => true,
'registryUrls' => [
Expand Down
5 changes: 4 additions & 1 deletion dictionaries/attrauthcomanage.definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
},
"exception_description": {
"en": "An unexpected error occurred while retrieving attributes from an external attribute authority. The exception was:"
},
"privacy_policy": {
"en": "Privacy Policy for the Service"
}
}
}
8 changes: 8 additions & 0 deletions dictionaries/logout.definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"title": {
"en": "Logged out"
},
"logged_out_text": {
"en": "You have been logged out."
}
}
38 changes: 38 additions & 0 deletions dictionaries/noty.definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"yes": {
"en": "Resend Verfication Email"
},
"no": {
"en": "Abort Login"
},
"title": {
"en": "Please verify your email address by clicking the link in the email we sent you"
},
"msg_title": {
"en": "<b>This is your current status:</b>"
},
"default_status": {
"en": "Action Required"
},
"account_pending_confirmation": {
"en": "Account in Pending Email Confirmation Status"
},
"invitation_restored": {
"en": "Invitation has been restored."
},
"petition_info": {
"en": "The identifier <cite><b>%ORGIDENT%</b></cite> is in Email Pending Confirmation Status.&nbspPlease check your Mail <cite><b>%MAIL%</b></cite> Inbox or Spam for further information.&nbsp"
},
"petition_user_notify": {
"en": "<p class=\"petition-user-notify\">We have sent an email with a confirmation link to your email address <cite><b>%MAIL%</b></cite>. 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.</p><p>You can also click the <strong>\"Resend Verfication Email\"</strong> button below to have another email sent to you."
},
"petition_token_expired": {
"en": "<div class=\"invite-expire\">Email confirmation token EXPIRED <b>&nbsp%DATE%</b>&nbspago</div>"
},
"petition_token_expires": {
"en": "<div class=\"invite-expire\">Email confirmation token EXPIRES in <b>&nbsp%DATE%</b></div>"
},
"petition_invalidate_msg": {
"en": "<p><i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>This action will invalidate any previous confirmation links.</p>"
}
}
50 changes: 50 additions & 0 deletions docs/model/aup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
AUP Model is stored in the state, `$state['rciamAttributes']['aup']`. In addition, the model encapsulates two additional structures, the `vo` and the `agreed` ones, under the respective fields. Both of these directly correlate to the AUP model.
* `vo` structure encompasses VO associated information with this AUP
* `agreed` structure encompasses information on the last agreement for this AUP

:warning: `vo` field is set to `null` when the AUP is not associated with any VO

:warning: `agreed` field is set to `null` if the user hasn't agreed with any version of this AUP

```bash
{
"Version":"1.0",
"aup":
[
{
"id": "<cm_co_terms_and_conditions::id>",
"description": "<cm_co_terms_and_conditions::description>",
"url": "cm_co_terms_and_conditions::url",
"modified": "<cm_co_terms_and_conditions::modified>",
"vo":
{
"id": "<cm_cous::id>",
"name": "<cm_cous::name>"
},
"version": "<cm_co_terms_and_conditions::revision>",
"agreed":
{
"id": "<cm_co_t_and_c_agreements::id>",
"aupId": "<cm_co_t_and_c_agreements::co_terms_and_conditions_id>",
"date": "<cm_co_t_and_c_agreements::agreement_time>",
"version": "<cm_co_terms_and_conditions::cm_co_terms_and_conditions_id::revision>"
}
}
]
}
```
<pre>
* id Id of the AUP in the COmanage Registry
* description Short description of the AUP
* url URL pointing to the AUP webpage
* modified Date when the AUP was last modified in the COmanage Registry
* vo VO associated information with this AUP
* id Id of the VO associated with this AUP
* name Name of the VO associated with this AUP
* version Current version of the AUP
* agreed Information on the last agreement for this AUP
* id Id of the AUP agreement
* aupId Id of the last agreed AUP
* date Date when the AUP agreement was signed
* version Version of the agreed AUP
</pre>
18 changes: 4 additions & 14 deletions lib/Attributes/SshPublicKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,10 @@
use SimpleSAML\Database;
use SimpleSAML\Error;
use SimpleSAML\Logger;
use SimpleSAML\Module\attrauthcomanage\Enums\SshKeyTypeEnum as SshKeyTypeEnum;

class SshPublicKey
class SshPublicKey implements SshKeyTypeEnum
{

public static $SSH_PUBLIC_KEY_TYPE = [
'DSA' => 'ssh-dss',
'ECDSA' => 'ecdsa-sha2-nistp256',
'ECDSA384' => 'ecdsa-sha2-nistp384',
'ECDSA521' => 'ecdsa-sha2-nistp521',
'ED25519' => 'ssh-ed25519',
'RSA' => 'ssh-rsa',
'RSA1' => 'ssh-rsa1',
];

/**
* Query the SSH table and fetch all SSH keys related to the CO Person
*
Expand Down Expand Up @@ -80,9 +70,9 @@ public function getSshPublicKeys($personId)
return $result;
}

// todo: This is redundant. Remove it
// Return SSH Public Key Type
public static function getSshPublicKeyType($key)
{
return self::$SSH_PUBLIC_KEY_TYPE[$key];
return constant("self::" . $key);
}
}
18 changes: 18 additions & 0 deletions lib/Auth/Logout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace SimpleSAML\Module\attrauthcomanage\Auth;

use SimpleSAML\Utils\HTTP;
use SimpleSAML\Module;
use SimpleSAML\Idp;

/**
*
* @package SimpleSAMLphp
*/
class Logout {
public static function postLogout(IdP $idp, array $state) {
$url = Module::getModuleURL('attrauthcomanage/logout.ctrl.php');
HTTP::redirectTrustedURL($url);
}
}
93 changes: 88 additions & 5 deletions lib/Auth/Process/COmanageDbClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
use SimpleSAML\Utils\HTTP;
use SimpleSAML\Database;
use SimpleSAML\Module\attrauthcomanage\Attributes;
use SimpleSAML\Module\attrauthcomanage\Enrollment;
use SimpleSAML\Module\attrauthcomanage\Enums\StatusEnum as StatusEnum;
use SimpleSAML\Module\attrauthcomanage\Enums\EndpointCmgEnum as EndpointCmgEnum;

class COmanageDbClient extends \SimpleSAML\Auth\ProcessingFilter
{
Expand Down Expand Up @@ -102,6 +105,8 @@ class COmanageDbClient extends \SimpleSAML\Auth\ProcessingFilter
private $voRoles = [];
private $voRolesDef = [];
private $coGroupMemberships = [];
private $comanage_api_username = null;
private $comanage_api_password = null;

private $basicInfoQuery = 'select'
. ' person.id,'
Expand Down Expand Up @@ -328,10 +333,53 @@ public function process(&$state)
if (!empty($basicInfo)) {
$state['basicInfo'] = $basicInfo;
}
if (empty($basicInfo['id']) || empty($basicInfo['status']) || ($basicInfo['status'] !== 'A' && $basicInfo['status'] !== 'GP')) {
if ($basicInfo['status'] === 'S') {



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');
}
// XXX Petition in Pending Confirmation
if ($basicInfo['status'] === StatusEnum::PendingConfirmation) { // User is PENDING CONFIRMATION
// Get Petition Id
$petition_cfg = [
'enrollee_co_person_id' => (int)$basicInfo['id'],
'petition_status' => $basicInfo['status'],
'orgIdentifier' => $state['Attributes'][$this->userIdAttribute][0],
'co_id' => $this->coId,
];
$petition_handler = new Enrollment\PetitionHandler($petition_cfg);
$petition = $petition_handler->getPetitionFromPersonIdPetStatus();
$endpoint = str_replace('%id%',
$petition[0]['petition_id'],
EndpointCmgEnum::ConfirmationEmailResend);
$state['rciamAttributes']['comanage_api_user'] = [
'username' => $this->comanage_api_username,
'password' => $this->comanage_api_password,
];
if(!empty($petition)) {
// Get petition id and redirect to email view
$pt_noty = [
'level' => $petition_handler->getBannerClass(),
'description' => $petition_handler->getUserNotify(),
//'status' => 'account_pending_confirmation', // This is a dictionary key
'icon' => 'email.gif',
'yes_btn_show' => true,
'form_fields' => [
'send_endpoint' => $endpoint,
'mail' => $petition[0]['mail'],
],
];
$this->showNoty($pt_noty, $state);
}
}

// XXX User is eligible to proceed to service
$state['UserID'] = $orgId;
$state['ReturnProc'] = [get_class($this), 'retrieveCOPersonData'];
$params = [];
Expand Down Expand Up @@ -761,7 +809,7 @@ private function getMemberships($co_id, $co_person_id)
. " AND cous.cou_id IS NULL"
. " LEFT OUTER JOIN cm_co_person_roles AS ROLE ON cous.id = role.cou_id"
. " AND role.co_person_role_id IS NULL"
. " AND role.status = 'A'"
. " AND role.status IN ('A', 'GP')"
. " AND NOT role.deleted AND role.co_person_id = members.co_person_id"
. " GROUP BY"
. " groups.name";
Expand Down Expand Up @@ -1131,7 +1179,7 @@ private function retrieveCOPersonData(&$state)
// XXX Check if the identifier is an authenticator
if (!$this->isIdpIdentLogin($orgId, $orgIdentifiers)) {
// Normally, this should not happen
$err_msg = 'The identifier <b>- ' . $orgId . ' -</b><br>is not present in your EGI account or is not a valid authenticator.<br>Please contact support for further assistance.';
$err_msg = 'The identifier <b>- ' . $orgId . ' -</b><br>is not present in your account or is not a valid authenticator.<br>Please contact support for further assistance.';
throw new Exception($err_msg);
}
// XXX Check if the identifier is valid or has expired
Expand Down Expand Up @@ -1418,9 +1466,24 @@ static function($group) use ($cou_id) {
}
}
);
if (isset($cou) && is_array($cou)) {
if (!empty($cou)) {
// XXX User is COU member
$cou = array_values($cou);
$tmp['vo']['name'] = $cou[0]['group_name'];
} else {
// XXX User is ONLY COU:admins member
$group = array_filter(
$co_memberships,
static function($group) use ($cou_id) {
if ((int)$group['cou_id'] === (int)$cou_id
&& strpos($group['group_name'], ':admins') !== false) {
return $group;
}
}
);
$group = array_values($group);
$group_name = explode(':admins', $group[0]['group_name'])[0];
$tmp['vo']['name'] = $group_name;
}
}
$tmp['agreed'] = null;
Expand Down Expand Up @@ -1747,6 +1810,8 @@ private function validateConfigParamRules() {
'coTermsId' => 'is_int',
'retrieveAUP' => 'is_bool',
'retrieveSshKeys' => 'is_bool',
'comanage_api_username' => 'is_string',
'comanage_api_password' => 'is_string',
],
];
}
Expand All @@ -1767,4 +1832,22 @@ private function showError($e, $parameters = NULL)
exit();
}

/**
* @param string[] $args
* @param [] $state
*
* @example $pt_noty = [
* 'level' => $pt_hdler->getBannerClass(),
* 'description' => $pt_hdler->getInfoHtmlElement(),
* 'status' => 'account_pending_confirmation', // This is a dictionary key
* ];
*/
private function showNoty($args, $state)
{
$state['noty'] = $args;
$id = State::saveState($state, 'attrauthcomanage_noty_state');
$url = Module::getModuleURL('attrauthcomanage/noty.ctrl.php');
HTTP::redirectTrustedURL($url, ['StateId' => $id]);
}

}
Loading

0 comments on commit d4c2b20

Please sign in to comment.