From 4bf41f29517e8e1a485f3dee6a75170576c909d0 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Mon, 19 Feb 2024 10:16:52 +0000 Subject: [PATCH] Further simplify the code. Added test requests. --- Controller/GrouperGroupsController.php | 4 +- Lib/GrouperApiAccess.php | 416 +++++++++++++------------ Lib/GrouperHTTPWrapper.php | 68 ++-- Lib/enum.php | 6 + Model/CoGrouperLiteWidget.php | 2 + Model/GrouperGroup.php | 104 ++----- Test/HttpRequests/grouper.http | 16 + Test/HttpRequests/http-client.env.json | 6 + 8 files changed, 336 insertions(+), 286 deletions(-) create mode 100644 Test/HttpRequests/grouper.http create mode 100644 Test/HttpRequests/http-client.env.json diff --git a/Controller/GrouperGroupsController.php b/Controller/GrouperGroupsController.php index b842c72..7d7cff8 100644 --- a/Controller/GrouperGroupsController.php +++ b/Controller/GrouperGroupsController.php @@ -203,7 +203,7 @@ public function addSubscriber() { ]; try { - $resultAdd = $this->GrouperGroup->addMemberToGroup($scope, + $resultAdd = $this->GrouperGroup->addGrouperGroupMember($scope, $this->userId, $this->CoGrouperLiteWidget->getConfig()); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($resultAdd, true)); } catch (Exception $e) { @@ -349,7 +349,7 @@ public function removeSubscriber() { ]; try { - $resultRemove = $this->GrouperGroup->removeMemberToGroup($scope, + $resultRemove = $this->GrouperGroup->removeGrouperGroupMember($scope, $this->userId, $this->CoGrouperLiteWidget->getConfig()); diff --git a/Lib/GrouperApiAccess.php b/Lib/GrouperApiAccess.php index 144abc9..201a233 100644 --- a/Lib/GrouperApiAccess.php +++ b/Lib/GrouperApiAccess.php @@ -78,41 +78,36 @@ public function __construct(array $cfg) * @return string Requests success or not * @throws GrouperLiteWidgetException|JsonException */ - public function addMemberToGroup(array $queryData) + public function addGrouperGroupMember(array $queryData) { $groupName = $queryData['groupName']; $connectionUrl = "{$this->config['fullUrl']}/groups/$groupName/members"; //Build request logic - $usersToAdd = array( - 'WsRestAddMemberRequest' => array( - 'subjectLookups' => array( - array('subjectId' => $queryData['addUserId']), - ), + $usersToAdd = [ + 'WsRestAddMemberRequest' => [ + 'subjectLookups' => [ + ['subjectId' => $queryData['addUserId']], + ], 'replaceAllExisting' => 'F', - 'actAsSubjectLookup' => array( + 'actAsSubjectLookup' => [ 'subjectId' => $queryData['userId'] - ) - ) - ); + ] + ] + ]; - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); try { $results = $this->http->sendRequest('PUT', $connectionUrl, json_encode($usersToAdd, JSON_THROW_ON_ERROR)); CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); - - // Parse out relevant records to send front end - if (isset($results['WsAddMemberResults']['results'][0]['resultMetadata'])) { - return $results['WsAddMemberResults']['results'][0]['resultMetadata']['resultCode']; - } } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return ''; + return $results['WsAddMemberResults']['results'][0]['resultMetadata']['resultCode'] ?? ''; } /** @@ -136,27 +131,27 @@ public function createGroupWithTemplate(array $queryData) } //Build request logic - $inputFields = array(); + $inputFields = []; foreach ($data as $key => $value) { - $inputFields[] = array('name' => $key, 'value' => $value); + $inputFields[] = ['name' => $key, 'value' => $value]; } - $groupToSave = array( - 'WsRestGshTemplateExecRequest' => array( - 'gshTemplateActAsSubjectLookup' => array( + $groupToSave = [ + 'WsRestGshTemplateExecRequest' => [ + 'gshTemplateActAsSubjectLookup' => [ 'subjectSourceId' => 'ldap', 'subjectId' => $userId - ), - 'ownerStemLookup' => array( + ], + 'ownerStemLookup' => [ 'stemName' => 'ref:incommon-collab' - ), + ], 'ownerType' => 'stem', 'configId' => 'createNewWorkingGroup', 'inputs' => $inputFields - ) - ); + ] + ]; - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); $connectionUrl = "{$this->config['fullUrl']}/gshTemplateExec"; $status = true; @@ -217,26 +212,26 @@ public function createUpdateGroup(array $queryData) $newGroupToSave = "$stemName:$newGroupName"; //Build request logic - $groupToSave = array( - 'WsRestGroupSaveRequest' => array( - 'actAsSubjectLookup' => array( + $groupToSave = [ + 'WsRestGroupSaveRequest' => [ + 'actAsSubjectLookup' => [ 'subjectId' => $userId - ), - 'wsGroupToSaves' => array( - array( - 'wsGroup' => array( + ], + 'wsGroupToSaves' => [ + [ + 'wsGroup' => [ 'description' => $groupDescription, 'name' => $newGroupToSave, 'displayExtension' => $groupName - ), - 'wsGroupLookup' => array( + ], + 'wsGroupLookup' => [ 'groupName' => $groupDescription - ) - ) - ) - ) - ); - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + ] + ] + ] + ] + ]; + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); $connectionUrl = "{$this->config['fullUrl']}/groups"; try { @@ -248,16 +243,8 @@ public function createUpdateGroup(array $queryData) throw $e; } - if (isset($results['WsGroupSaveResults']['results']['resultMetadata']['resultCode']) - && stripos( - $results['WsGroupSaveResults']['results']['resultMetadata']['resultCode'], - 'Success', - 0 - ) !== false) { - return true; - } - - return false; + return isset($results['WsGroupSaveResults']['results']['resultMetadata']['resultCode']) + && $results['WsGroupSaveResults']['results']['resultMetadata']['resultCode'] === GrouperResultCodesEnum::SUCCESS; } /** @@ -272,31 +259,30 @@ public function createUpdateGroup(array $queryData) */ public function deleteGroupWithTemplate(array $queryData) { - $workingGroupExt = $queryData['workingGroupExt']; $userId = $queryData['userId']; - $groupToDelete = array( - 'WsRestGshTemplateExecRequest' => array( - 'gshTemplateActAsSubjectLookup' => array( + $groupToDelete = [ + 'WsRestGshTemplateExecRequest' => [ + 'gshTemplateActAsSubjectLookup' => [ 'subjectSourceId' => 'ldap', 'subjectId' => $userId - ), - 'ownerStemLookup' => array( + ], + 'ownerStemLookup' => [ 'stemName' => 'ref:incommon-collab' - ), + ], 'ownerType' => 'stem', 'configId' => 'createWorkingGroup', - 'inputs' => array( - array( + 'inputs' => [ + [ 'name' => 'gsh_input_workingGroupExtension', 'value' => $workingGroupExt - ) - ) - ) - ); + ] + ] + ] + ]; - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); $connectionUrl = "{$this->config['fullUrl']}/gshTemplateExec"; try { @@ -332,21 +318,21 @@ public function deleteGroupWithTemplate(array $queryData) public function getGrouperGroupInfo(array $queryData) { $groupName = $queryData['groupName']; - $groupInfo = array(); + $groupInfo = []; //Build request logic - $stemToFind = array( - 'WsRestGetAttributeAssignmentsRequest' => array( + $stemToFind = [ + 'WsRestGetAttributeAssignmentsRequest' => [ 'attributeAssignType' => 'group', 'includeAssignmentsOnAssignments' => 'T', - 'wsOwnerGroupLookups' => array( - array( + 'wsOwnerGroupLookups' => [ + [ 'groupName' => $groupName, - ) - ) - ) - ); - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + ] + ] + ] + ]; + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); $connectionUrl = "{$this->config['fullUrl']}/attributeAssignments"; try { @@ -365,7 +351,7 @@ public function getGrouperGroupInfo(array $queryData) } //Now get the Group Attributes and add them to group - $groupInfo[0]['attributes'] = $results['WsGetAttributeAssignmentsResults']['wsAttributeAssigns'] ?? array(); + $groupInfo[0]['attributes'] = $results['WsGetAttributeAssignmentsResults']['wsAttributeAssigns'] ?? []; return $groupInfo; } @@ -376,28 +362,21 @@ public function getGrouperGroupInfo(array $queryData) * Note: Params added at end make sure that the groups returned can only be viewed by the member logged into * Grouper Lite * - * @param array $queryData Array of conditions for querying + * @param string $userId + * * @return array Membership records that User is a member of in Grouper * * @throws GrouperLiteWidgetException */ - public function getGrouperMemberOfGroups(array $queryData, string $groupName = null) + public function getGrouperMemberOfGroups(string $userId) { - if(empty($queryData['userId'])) { + if(empty($userId)) { return []; } - $connectionUrl = "{$this->config['fullUrl']}/subjects/{$queryData['userId']}/groups?"; - $queryParameters = "wsLiteObjectType=WsRestGetGroupsLiteRequest" - . "&actAsSubjectId={$queryData['userId']}"; - if($groupName !== null) { - $queryParameters = "wsLiteObjectType=WsRestGetGroupsLiteRequest" - . "&groupName={$groupName}" - . "&queryFilterType=FIND_BY_GROUP_NAME_EXACT" - . "&actAsSubjectId={$queryData['userId']}"; - } - $connectionUrl .= $queryParameters; - + $connectionUrl = "{$this->config['fullUrl']}/subjects/{$userId}/groups?" + . 'wsLiteObjectType=WsRestGetGroupsLiteRequest' + . "&actAsSubjectId={$userId}"; try { $results = $this->http->sendRequest('GET', $connectionUrl); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); @@ -420,45 +399,43 @@ public function getGrouperMemberOfGroups(array $queryData, string $groupName = n */ public function getMembersInGroup(array $queryData) { //Build request logic - $usersToShow = array( - 'WsRestGetMembersRequest' => array( - 'actAsSubjectLookup' => array( + $usersToShow = [ + 'WsRestGetMembersRequest' => [ + 'actAsSubjectLookup' => [ 'subjectId' => $queryData['userId'] - ), - 'wsGroupLookups' => array( - array('groupName' => $queryData['groupName']) - ), - 'subjectAttributeNames' => array('name') - ) - ); - $connectionUrl = "{$this->config['fullUrl']}/groups"; + ], + 'wsGroupLookups' => [ + ['groupName' => $queryData['groupName']] + ], + 'subjectAttributeNames' => ['name'] + ] + ]; + $connectionUrl = "{$this->config['fullUrl']}/groups"; + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); try { - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); - $results = $this->http->sendRequest('POST', $connectionUrl, json_encode($usersToShow, JSON_THROW_ON_ERROR)); CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); + } catch (Exception $e) { + CakeLog::write('error', __METHOD__ . ': An error occurred'); + throw $e; + } - // Parse out relevant records to send front end - if(isset($results['WsGetMembersResults']['results'][0]['resultMetadata']['resultCode']) - && $results['WsGetMembersResults']['results'][0]['resultMetadata']['resultCode'] == 'GROUP_NOT_FOUND') { - return array(array( + // Parse out relevant records to send front end + if(isset($results['WsGetMembersResults']['results'][0]['resultMetadata']['resultCode']) + && $results['WsGetMembersResults']['results'][0]['resultMetadata']['resultCode'] == 'GROUP_NOT_FOUND') { + return [ + [ 'sourceId' => 'NoAccess', 'name' => '', 'id' => '' - )); - } - if (isset($results['WsGetMembersResults']['results'][0]['wsSubjects'])) { - return $results['WsGetMembersResults']['results'][0]['wsSubjects']; - } - } catch (Exception $e) { - CakeLog::write('error', __METHOD__ . ': An error occurred'); - throw $e; + ] + ]; } - return array(); + return $results['WsGetMembersResults']['results'][0]['wsSubjects'] ?? []; } /** @@ -477,15 +454,11 @@ public function getOptionalGroups(array $queryData) try { $results = $this->useMembershipUrl($queryData); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); - - if (isset($results['WsGetMembershipsResults']['wsGroups'])) { - return $results['WsGetMembershipsResults']['wsGroups']; - } } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return array(); + return $results['WsGetMembershipsResults']['wsGroups'] ?? []; } /** @@ -498,9 +471,6 @@ public function getOptionalGroups(array $queryData) */ public function getOwnedGroups(array $queryData) { - $admins = array(); - $updaters = array(); - try { $queryData['groupType'] = 'admin'; $resultsAdmin = $this->useMembershipUrl($queryData); @@ -509,19 +479,13 @@ public function getOwnedGroups(array $queryData) $queryData['groupType'] = 'update'; $resultsUpdate = $this->useMembershipUrl($queryData); CakeLog::write('debug', __METHOD__ . '::response updates: ' . var_export($resultsUpdate, true)); - - if (isset($resultsAdmin['WsGetMembershipsResults']['wsGroups'])) { - $admins = $resultsAdmin['WsGetMembershipsResults']['wsGroups']; - } - if (isset($resultsUpdate['WsGetMembershipsResults']['wsGroups'])) { - $updaters = $resultsUpdate['WsGetMembershipsResults']['wsGroups']; - } - - return $this->removeDuplicates($admins, $updaters); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } + + return $this->removeDuplicates($resultsAdmin['WsGetMembershipsResults']['wsGroups'] ?? [], + $resultsUpdate['WsGetMembershipsResults']['wsGroups'] ?? []); } /** @@ -539,15 +503,56 @@ public function getOwnedStems(array $queryData) try { $results = $this->useMembershipUrl($queryData); + } catch (Exception $e) { + CakeLog::write('error', __METHOD__ . ': An error occurred'); + throw $e; + } + return $results['WsGetMembershipsResults']['wsStems'] ?? []; + } - if (isset($results['WsGetMembershipsResults']['wsStems']) && $results['WsGetMembershipsResults']['wsStems'] != NULL) { - return $results['WsGetMembershipsResults']['wsStems']; - } + /** + * For Optin groups, calls Grouper WS to join a group + * + * @param string $userId + * @param string $groupName + * + * @return bool True if join or leave successful, False if not + * @throws GrouperLiteWidgetException + * @throws JsonException + */ + public function joinGrouperGroup(string $userId, string $groupName) + { + if(empty($userId) || empty($groupName)) { + return false; + } + + //Build request logic + $groupCommand = [ + 'WsRestAddMemberRequest' => [ + 'actAsSubjectLookup' => [ + 'subjectId' => $userId + ], + 'replaceAllExisting' => 'F', + 'subjectLookups' => [ + ['subjectId' => $userId] + ] + ] + ]; + + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); + $connectionUrl = "{$this->config['fullUrl']}/groups/{$groupName}/members"; + + try { + $results = $this->http->sendRequest('PUT', $connectionUrl, json_encode($groupCommand, JSON_THROW_ON_ERROR)); + CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); + CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return array(); + + return isset($results['WsAddMemberResults']['wsGroupAssigned']) + && $results['WsAddMemberResults']['wsGroupAssigned']['name'] == urldecode($groupName); } /** @@ -558,59 +563,72 @@ public function getOwnedStems(array $queryData) * @return bool True if join or leave successful, False if not * @throws GrouperLiteWidgetException|JsonException */ - public function grouperGroupLeaveOrJoin(array $queryData) + public function leaveGrouperGroup(string $userId, string $groupName) { - $groupName = $queryData['groupName']; - $userId = $queryData['userId']; - $groupLeaveOrJoin = $queryData['LeaveJoin']; - $groupName = urlencode($groupName); - - if ($groupLeaveOrJoin == "Leave") { - $memberRequest = "WsRestDeleteMemberRequest"; - $resultResponse = 'WsDeleteMemberResults'; - $resultGroup = 'wsGroup'; - } elseif ($groupLeaveOrJoin == "Join") { - $memberRequest = "WsRestAddMemberRequest"; - $resultResponse = 'WsAddMemberResults'; - $resultGroup = 'wsGroupAssigned'; - } else { - CakeLog::write('error', __METHOD__ . ": Option of $groupLeaveOrJoin is not supported"); - throw new GrouperLiteWidgetException("Received option of $groupLeaveOrJoin which is not supported"); + if(empty($userId) || empty($groupName)) { + return false; } //Build request logic - $groupCommand = array( - $memberRequest => array( - "actAsSubjectLookup" => array( - "subjectId" => $userId - ), - "replaceAllExisting" => "F", - "subjectLookups" => array( - array("subjectId" => $userId) - ) - ) - ); + $groupCommand = [ + '$memberRequest' => [ + 'actAsSubjectLookup' => [ + 'subjectId' => $userId + ], + 'replaceAllExisting' => 'F', + 'subjectLookups' => [ + ['subjectId' => $userId] + ] + ] + ]; - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); - $connectionUrl = "{$this->config['fullUrl']}/groups/$groupName/members"; + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); + $connectionUrl = "{$this->config['fullUrl']}/groups/{$groupName}/members"; try { $results = $this->http->sendRequest('PUT', $connectionUrl, json_encode($groupCommand, JSON_THROW_ON_ERROR)); CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); + } catch (Exception $e) { + CakeLog::write('error', __METHOD__ . ': An error occurred'); + throw $e; + } - if (isset($results[$resultResponse][$resultGroup])) { - $groupAssigned = $results[$resultResponse][$resultGroup]['name']; - if ($groupAssigned == urldecode($groupName)) { - return true; - } - } + return isset($results['WsDeleteMemberResults']['wsGroup']) + && $results['WsDeleteMemberResults']['wsGroup']['name'] == urldecode($groupName); + } + + /** + * Is the user member of the Group + * + * @param string $groupName + * @param string $userId + * + * @return bool + * + * @throws GrouperLiteWidgetException + */ + public function isMemberOf(string $groupName, string $userId): bool + { + if(empty($userId) || empty($groupName)) { + return []; + } + + $groupNameEncoded = $this->urlGrouperEncode($groupName); + + $connectionUrl = "{$this->config['fullUrl']}/groups" + . "/{$groupNameEncoded}/members/{$userId}"; + try { + $results = $this->http->sendRequest('GET', $connectionUrl); + CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); + CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return false; + return isset($results['WsHasMemberLiteResul']['resultMetadata']['resultCode']) + && $results['WsHasMemberLiteResul']['resultMetadata']['resultCode'] === GrouperResultCodesEnum::IS_MEMBER; } /** @@ -654,40 +672,50 @@ public function removeDuplicates(array $arrOne, array $arrTwo) * @throws GrouperLiteWidgetException * @throws JsonException */ - public function removeMemberToGroup(array $queryData) + public function removeGrouperGroupMember(array $queryData) { $groupName = $queryData['groupName']; $connectionUrl = "{$this->config['fullUrl']}/groups/$groupName/members"; //Build request logic - $userToDelete = array( - 'WsRestDeleteMemberRequest' => array( - 'subjectLookups' => array( - array('subjectId' => $queryData['remUserId']), - ), - 'actAsSubjectLookup' => array( + $userToDelete = [ + 'WsRestDeleteMemberRequest' => [ + 'subjectLookups' => [ + ['subjectId' => $queryData['remUserId']], + ], + 'actAsSubjectLookup' => [ 'subjectId' => $queryData['userId'] - ) - ) - ); + ] + ] + ]; - $this->http->setHeader(array('Content-Type' => 'application/json', 'Accept' => 'application/json')); + $this->http->setHeader(['Content-Type' => 'application/json', 'Accept' => 'application/json']); try { - $results = $this->http->sendRequest('POST', $connectionUrl, json_encode($userToDelete, JSON_THROW_ON_ERROR)); + $results = $this->http->sendRequest('POST', + $connectionUrl, json_encode($userToDelete, + JSON_THROW_ON_ERROR)); CakeLog::write('debug', __METHOD__ . '::connection url: ' . $connectionUrl); CakeLog::write('debug', __METHOD__ . '::response: ' . var_export($results, true)); - - // Parse out relevant records to send front end - if (isset($results['WsDeleteMemberResults']['results'][0]['resultMetadata'])) { - return $results['WsDeleteMemberResults']['results'][0]['resultMetadata']['resultCode']; - } } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return ''; + // Parse out relevant records to send front end + return $results['WsDeleteMemberResults']['results'][0]['resultMetadata']['resultCode'] ?? ''; + } + + /** + * Properly encode the attribute for the URL + * + * @param string $url + * + * @return string + */ + public function urlGrouperEncode(string $url) { + $url = urlencode($url); + return str_replace(':', '%3A', $url); } /** diff --git a/Lib/GrouperHTTPWrapper.php b/Lib/GrouperHTTPWrapper.php index 9df9640..eb2d4ff 100644 --- a/Lib/GrouperHTTPWrapper.php +++ b/Lib/GrouperHTTPWrapper.php @@ -35,14 +35,26 @@ */ class GrouperHTTPWrapper extends HttpSocket { - //Connection array sent to HttpSocket - private $_request = array(); + /** + * @var array + * + * Connection array sent to HttpSocket + */ + private array $_request = []; - // Grouper User Account to access Grouper Web Services - private $_user; + /** + * @var string + * + * Grouper User Account to access Grouper Web Services + */ + private string $_user; - // Password of Grouper User Account - private $_password; + /** + * @var string + * + * Password of Grouper User Account + */ + private string $_password; /** * GrouperHTTPWrapper constructor. @@ -57,13 +69,26 @@ public function __construct($config = array()) { $this->config['ssl_verify_peer'] = false; } + + /** + * Enable SSL Verify configuration + * + * @return void + */ + public function enableSSLVerify(): void + { + $this->config['ssl_verify_peer'] = true; + } + + /** - * Setter for SSL Verify Peer + * Disable SSL Verify Configuration * - * @param boolean $val + * @return void */ - public function setSSLVerify(bool $val) { - $this->config['ssl_verify_peer'] = $val; + public function disableSSLVerify(): void + { + $this->config['ssl_verify_peer'] = false; } /** @@ -71,9 +96,11 @@ public function setSSLVerify(bool $val) { * * @param string $user */ - public function setUser(string $user) { - - $this->_user = $user; + public function setUser(string $user): void + { + if (!empty($user)) { + $this->_user = $user; + } } /** @@ -81,9 +108,11 @@ public function setUser(string $user) { * * @param string $password */ - public function setPassword(string $password) { - - $this->_password = $password; + public function setPassword(string $password): void + { + if (!empty($password)) { + $this->_password = $password; + } } /** @@ -91,8 +120,11 @@ public function setPassword(string $password) { * * @param array $headerSetting */ - public function setHeader(array $headerSetting) { - $this->_request['header'] = $headerSetting; + public function setHeader(array $headerSetting): void + { + if (!empty($headerSetting)) { + $this->_request['header'] = $headerSetting; + } } /** diff --git a/Lib/enum.php b/Lib/enum.php index 172319a..5fb9689 100644 --- a/Lib/enum.php +++ b/Lib/enum.php @@ -14,4 +14,10 @@ class GrouperSpecialGroups { /** Group whose members cannot see Grouper button, even if admin */ const GROUPER_VISIBLE_GROUP = 'app:comanage:LiteUI:grouperVisible'; +} + +class GrouperResultCodesEnum { + const IS_MEMBER = 'IS_MEMBER'; + const SUCCESS = 'SUCCESS'; + const GROUP_NOT_FOUND = 'GROUP_NOT_FOUND'; } \ No newline at end of file diff --git a/Model/CoGrouperLiteWidget.php b/Model/CoGrouperLiteWidget.php index 9266390..5181291 100644 --- a/Model/CoGrouperLiteWidget.php +++ b/Model/CoGrouperLiteWidget.php @@ -119,6 +119,8 @@ class CoGrouperLiteWidget extends CoDashboardWidgetBackend { 'allowEmpty' => false ) ), + // TODO: Are there any limitation regarding the acceptable group name characters + // For COmanage there are so we need to check this as well 'act_as_grp_name' => array( 'rule' => '/.*/', 'required' => false, diff --git a/Model/GrouperGroup.php b/Model/GrouperGroup.php index 599c19d..18d776e 100644 --- a/Model/GrouperGroup.php +++ b/Model/GrouperGroup.php @@ -84,18 +84,17 @@ class GrouperGroup extends GrouperLiteWidgetAppModel public function isUserOwner(string $userId, array $cfg) { $this->initApi($cfg); + $args = array(); + $args['userId'] = $userId; try { - $args = array(); - $args['userId'] = $userId; - $ownGroups = $this->grouperAPI->getOwnedGroups($args); - - return count($ownGroups) > 0 ? 'T' : 'F'; } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } + + return count($ownGroups) > 0 ? 'T' : 'F'; } /** @@ -109,28 +108,16 @@ public function isUserOwner(string $userId, array $cfg) */ public function isGrouperVisible(string $userId, array $cfg) { - $member = 'F'; - $this->initApi($cfg); - $args = []; - $args['userId'] = $userId; try { - $memberOfGroups = $this->grouperAPI->getGrouperMemberOfGroups($args, - GrouperSpecialGroups::GROUPER_VISIBLE_GROUP); - - foreach ($memberOfGroups as $memberOfGroup) { - if ($memberOfGroup['name'] == GrouperSpecialGroups::GROUPER_VISIBLE_GROUP) { - $member = 'T'; - break; - } - } + $isMember = $this->grouperAPI->isMemberOf(GrouperSpecialGroups::GROUPER_VISIBLE_GROUP, $userId); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return $member; + return $isMember ? 'T' : 'F'; } /** @@ -161,7 +148,7 @@ public function filteredMemberOfGroups(array $conditions, array $cfg) $this->initApi($cfg); try { - $memberOfGroups = $this->memberOfGroups($conditions); + $memberOfGroups = $this->memberOfGroups($conditions, $cfg); $conditions['groupType'] = 'optouts'; // Determine which groups can be left by user, if want. @@ -189,10 +176,12 @@ public function filteredMemberOfGroups(array $conditions, array $cfg) * * @since COmanage Registry v4.4.0 */ - private function memberOfGroups(array $conditions) + private function memberOfGroups(array $conditions, array $cfg) { + $this->initApi($cfg); + try { - return $this->grouperAPI->getGrouperMemberOfGroups($conditions); + return $this->grouperAPI->getGrouperMemberOfGroups($conditions['userId']); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; @@ -217,13 +206,7 @@ public function leaveGroup(string $userId, string $groupName, array $cfg) $this->initApi($cfg); try { - $args = array(); - $args['LeaveJoin'] = 'Leave'; - $args['userId'] = $userId; - $args['groupName'] = $groupName; - - return $this->grouperAPI->grouperGroupLeaveOrJoin($args); - + return $this->grouperAPI->leaveGrouperGroup($userId, $groupName); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; @@ -245,13 +228,7 @@ public function joinGroup(string $userId, string $groupName, array $cfg) $this->initApi($cfg); try { - $args = array(); - $args['LeaveJoin'] = 'Join'; - $args['userId'] = $userId; - $args['groupName'] = $groupName; - - return $this->grouperAPI->grouperGroupLeaveOrJoin($args); - + return $this->grouperAPI->joinGrouperGroup($userId, $groupName); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; @@ -299,24 +276,23 @@ public function membersInGroup(array $conditions, string $userId, array $cfg) try { $groupMembers = $this->grouperAPI->getMembersInGroup($conditions); + } catch (Exception $e) { + CakeLog::write('error', __METHOD__ . ': An error occurred'); + throw $e; + } - if (count($groupMembers) < 1) { - return $groupMembers; - } - - $finalMembers = array(); - foreach ($groupMembers as $member) { - if ($member['sourceId'] !== 'g:gsa') { - $finalMembers[] = $member; - } + if (count($groupMembers) < 1) { + return $groupMembers; + } + $finalMembers = []; + foreach ($groupMembers as $member) { + if ($member['sourceId'] !== 'g:gsa') { + $finalMembers[] = $member; } - return $finalMembers; - } catch (Exception $e) { - CakeLog::write('error', __METHOD__ . ': An error occurred'); - throw $e; } + return $finalMembers; } /** @@ -329,17 +305,14 @@ public function membersInGroup(array $conditions, string $userId, array $cfg) * * @since COmanage Registry v4.4.0 */ - public function addMemberToGroup(array $conditions, string $userId, array $cfg) + public function addGrouperGroupMember(array $conditions, string $userId, array $cfg) { $this->initApi($cfg); $conditions['userId'] = $userId; try { - $resultAdd = $this->grouperAPI->addMemberToGroup($conditions); - - return $resultAdd; - + return $this->grouperAPI->addGrouperGroupMember($conditions); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; @@ -356,14 +329,14 @@ public function addMemberToGroup(array $conditions, string $userId, array $cfg) * * @since COmanage Registry v4.4.0 */ - public function removeMemberToGroup(array $conditions, string $userId, array $cfg) + public function removeGrouperGroupMember(array $conditions, string $userId, array $cfg) { $this->initApi($cfg); $conditions['userId'] = $userId; try { - return $this->grouperAPI->removeMemberToGroup($conditions); + return $this->grouperAPI->removeGrouperGroupMember($conditions); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; @@ -391,7 +364,7 @@ public function optinGroups(array $conditions, array $cfg) // Groups the user can join or leave $joinOrLeave = $this->grouperAPI->getOptionalGroups($conditions); // Groups the user is a member of - $userGroups = $this->memberOfGroups($conditions); + $userGroups = $this->memberOfGroups($conditions, $cfg); // Extract the names of the Groups the user is a member of $userGroupsNames = Hash::extract($userGroups, '{n}.name'); // Return the groups the user can join and is not a member of @@ -413,29 +386,16 @@ public function optinGroups(array $conditions, array $cfg) */ public function isTemplateUser(string $userId, array $cfg) { - $member = 'F'; - $this->initApi($cfg); - $args = array(); - $args['userId'] = $userId; try { - $memberOfGroups = $this->grouperAPI->getGrouperMemberOfGroups($args, - GrouperSpecialGroups::TEMPLATE_CREATION_GROUP); - //now cycle through and see if part of correct group to be able to use template - foreach ($memberOfGroups as $memberOfGroup) { - if ($memberOfGroup['name'] == GrouperSpecialGroups::TEMPLATE_CREATION_GROUP) { - $member = 'T'; - break; - } - } - + $isMember = $this->grouperAPI->isMemberOf(GrouperSpecialGroups::TEMPLATE_CREATION_GROUP, $userId); } catch (Exception $e) { CakeLog::write('error', __METHOD__ . ': An error occurred'); throw $e; } - return $member; + return $isMember ? 'T' : 'F'; } /** diff --git a/Test/HttpRequests/grouper.http b/Test/HttpRequests/grouper.http new file mode 100644 index 0000000..4fb3c28 --- /dev/null +++ b/Test/HttpRequests/grouper.http @@ -0,0 +1,16 @@ +# https://spaces.at.internet2.edu/display/Grouper/Grouper+Web+Services + +### GET groups the actAs is a member of +GET https://{{ host }}/grouper-ws/servicesRest/{{version}}/subjects/{{identifier}}/groups? + wsLiteObjectType=WsRestGetGroupsLiteRequest& + actAsSubjectId={{identifier}} +Authorization: Basic {{username}} {{password}} + + +### isMember of Group +GET https://{{ host }}/grouper-ws/servicesRest/{{version}}/groups/test%3AviewOnly/members/{{identifier}} +Authorization: Basic {{username}} {{password}} + +### Get memberships +GET https://{{ host }}/grouper-ws/servicesRest/{{version}}/subjects/{{identifier}}/groups/test%3AviewOnly/memberships +Authorization: Basic {{username}} {{password}} \ No newline at end of file diff --git a/Test/HttpRequests/http-client.env.json b/Test/HttpRequests/http-client.env.json new file mode 100644 index 0000000..9313194 --- /dev/null +++ b/Test/HttpRequests/http-client.env.json @@ -0,0 +1,6 @@ +{ + "grouper": { + "host": "grouper.dev.at.internet2.edu", + "version": "v2_5_000" + } +} \ No newline at end of file