Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
comanage-grouper-widget/Model/GrouperGroup.php
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
918 lines (822 sloc)
29.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* COmanage Registry Grouper Lite Widget Groups Model | |
* | |
* Portions licensed to the University Corporation for Advanced Internet | |
* Development, Inc. ("UCAID") under one or more contributor license agreements. | |
* See the NOTICE file distributed with this work for additional information | |
* regarding copyright ownership. | |
* | |
* UCAID licenses this file to you under the Apache License, Version 2.0 | |
* (the "License"); you may not use this file except in compliance with the | |
* License. You may obtain a copy of the License at: | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
* @link http://www.internet2.edu/comanage COmanage Project | |
* @package registry-plugin | |
* @since COmanage Registry v3.2.0 | |
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) | |
*/ | |
App::uses('GrouperApiAccess', 'GrouperLiteWidget.Lib/'); | |
App::uses('GrouperAttribute', 'GrouperLiteWidget.Model/'); | |
/*** | |
* Class GrouperGroup | |
* | |
* Model class that does most of the heavy lifting in Grouper Lite Widget | |
*/ | |
class GrouperGroup extends GrouperLiteWidgetAppModel | |
{ | |
// XXX According to the documentation (https://spaces.at.internet2.edu/display/Grouper/UI+Terminology) | |
// the displayExtension is the Friendly Name of the Group. | |
/** @var string $name used by CakePHP for locating model */ | |
public $name = 'GrouperGroup'; | |
/** @var GrouperApiAccess $grouperAPI */ | |
private $grouperAPI = null; | |
private $wgStemsTopLevel = array( | |
'ref:incommon-collab', | |
'ref:internet2-collab' | |
); | |
// Current listing of groups that are associated to Working Groups | |
private $wgStemsAllGroups = array( | |
'app:jira', | |
'app:confluence', | |
'app:sympa:internet2', | |
'app:sympa:incommon', | |
'ref:incommon-collab', | |
'ref:internet2-collab' | |
); | |
/** | |
* Verifies if a user is an owner/admin of a group. | |
* Session variable is reset on Group Creation and Group Deletion | |
* | |
* @param string $userId Id of User | |
* @param string $actorUserId | |
* @param array $cfg | |
* | |
* @return bool T or F | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function isUserGroupOwner(string $userId, string $actorUserId, array $cfg): bool | |
{ | |
$this->initApi($cfg); | |
if(empty($userId) || empty($actorUserId)) { | |
return false; | |
} | |
try { | |
$resultsAdmin = $this->grouperAPI->getUserMemberships($userId, $actorUserId, GrouperGroupTypeEnum::ADMIN); | |
$resultsUpdate = $this->grouperAPI->getUserMemberships($userId, $actorUserId, GrouperGroupTypeEnum::UPDATE); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
return count($resultsAdmin['WsGetMembershipsResults']['wsGroups'] ?? []) > 0 | |
|| count($resultsUpdate['WsGetMembershipsResults']['wsGroups'] ?? []) > 0; | |
} | |
/** | |
* Verifies if user can see the Grouper link button. Even if owner, may be not allowed to see it. | |
* | |
* @param string $userId Id of User | |
* @return String T or F | |
* @throws GrouperLiteWidgetException | |
* | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function isGrouperVisible(string $userId, array $cfg): string | |
{ | |
$this->initApi($cfg); | |
try { | |
$isMember = $this->grouperAPI->isMemberOfGroup(GrouperSpecialGroups::GROUPER_VISIBLE_GROUP, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
return $isMember ? 'T' : 'F'; | |
} | |
/** | |
* Grouper API Instance Singleton | |
* | |
* @throws GrouperLiteWidgetException | |
* | |
* @since COmanage Registry v4.4.0 | |
*/ | |
private function initApi(array $cfg) { | |
if ($this->grouperAPI === null) { | |
$this->grouperAPI = new GrouperApiAccess($cfg); | |
} | |
} | |
/** | |
* Add a member to a specific Grouper Group | |
* | |
* @param string $actorUserId Id of User | |
* @param string $groupName | |
* @param string $addUserId | |
* @param array $cfg | |
* | |
* @return string success of Request | |
* @throws GrouperLiteWidgetException Captured in Controller | |
* @throws JsonException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function addGroupMember(string $actorUserId, string $groupName, string $addUserId, array $cfg) | |
{ | |
$this->initApi($cfg); | |
return $this->grouperAPI->addGroupMember($actorUserId, $groupName, $addUserId); | |
} | |
/** | |
* Breakout Working Groups from AdHoc Groups. | |
* | |
* @param array $recordSet | |
* @return array[] | |
* | |
*/ | |
public function breakoutWrkFromAdHocGroups(array $recordSet): array | |
{ | |
$wgData = []; | |
$notWGData = []; | |
//Parse out the Working Groups from the Ad-hoc groups | |
foreach ($recordSet as $record) { | |
if (isset($record['WGName'])) { | |
$wgData[] = $record; | |
} else { | |
$notWGData[] = $record; | |
} | |
} | |
return [ | |
'adhoc' => $notWGData, | |
'working' => $wgData | |
]; | |
} | |
/** | |
* Create a new Grouper Group using the Template methodology in Grouper | |
* | |
* @param string $userId Id of User | |
* @param array $groupData Data needed to create new Grouper Group via Template | |
* @return array status and error message, if applicable | |
* @throws GrouperLiteWidgetException | |
* | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function createGroupWithTemplate(string $userId, array $groupData, array $cfg) | |
{ | |
$this->initApi($cfg); | |
//Need to massage incoming data to meet Grouper Template requirements | |
$fields = array( | |
'gsh_input_isSympa', | |
'gsh_input_isSympaModerated', | |
'gsh_input_isOptin', | |
'gsh_input_isConfluence', | |
'gsh_input_isJira' | |
); | |
// Template does not except true/false, so convert to string and send that way | |
foreach ($fields as $field) { | |
($groupData[$field] == '0') ? $groupData[$field] = 'false' : $groupData[$field] = 'true'; | |
} | |
$args = array(); | |
$args['userId'] = $userId; | |
$args['data'] = $groupData; | |
try { | |
return $this->grouperAPI->createGroupWithTemplate($args); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Construct picker(like) response data based on mode and term | |
* | |
* @param integer $coId CO ID | |
* @param string $mode Search mode to apply filters for | |
* @param array $coPersonIds List of PersonIds | |
* | |
* @return array Array of CO Person records | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function dataConstructForPicker(int $coId, string $mode, array $coPersonIds): array | |
{ | |
if(empty($coPersonIds)) { | |
return []; | |
} | |
$this->CoPerson = ClassRegistry::init('CoPerson'); | |
$this->Co = ClassRegistry::init('Co'); | |
$matches = []; | |
if(count($coPersonIds) > 100) { | |
// We don't return large sets to avoid slow performance | |
$matches[] = array( | |
'value' => -1, | |
'label' => _txt('er.picker.toomany') | |
); | |
} else { | |
$people = $this->CoPerson->filterPicker($coId, $coPersonIds, $mode); | |
$pickerEmailType = $this->Co->CoSetting->getPersonPickerEmailType($coId); | |
$pickerIdentifierType = $this->Co->CoSetting->getPersonPickerIdentifierType($coId); | |
$pickerDisplayTypes = $this->Co->CoSetting->getPersonPickerDisplayTypes($coId); | |
foreach($people as $p) { | |
$label = generateCn($p['Name'][0]); | |
$idArr = $p['Identifier']; | |
$emailArr = $p['EmailAddress']; | |
$email = ''; | |
$email_short = ''; | |
$emailLabel = ''; | |
$id = ''; | |
$id_short = ''; | |
$idLabel = ''; | |
// Iterate over the email array | |
if(!empty($emailArr) && !empty($pickerEmailType)) { | |
$emailLabel = !empty($pickerDisplayTypes) ? _txt('fd.extended_type.generic.label', array(_txt('fd.email_address.mail'), $pickerEmailType)) | |
: _txt('fd.email_address.mail') . ': '; | |
foreach($emailArr as $e) { | |
if($e['type'] == $pickerEmailType) { | |
$email = $e['mail']; | |
$email_short = mb_strimwidth($e['mail'], 0, 30, '...'); | |
break; | |
} | |
} | |
} | |
// Set the identifier for display (and limit it to 30 characters max) | |
if(!empty($idArr[0]['identifier']) && !empty($pickerIdentifierType)) { | |
if(!empty($pickerDisplayTypes)) { | |
$idLabel = _txt('fd.extended_type.generic.label', array(_txt('fd.identifier.identifier'), $pickerIdentifierType)); | |
} | |
else { | |
$idLabel = _txt('fd.identifier.identifier') . ': '; | |
} | |
foreach($idArr as $i) { | |
if($i['type'] == $pickerIdentifierType) { | |
$id_short = mb_strimwidth($i['identifier'], 0, 30, '...'); | |
$id = $i['identifier']; | |
break; | |
} | |
} | |
} | |
// Make sure we don't already have an entry for this CO Person ID | |
if(!Hash::check($matches, '{n}[value='.$p['CoPerson']['id'].']')) { | |
$matches[] = array( | |
'value' => $p['CoPerson']['id'], | |
'label' => $label, | |
'email' => $email, | |
'emailShort' => $email_short, | |
'emailLabel' => $emailLabel, | |
'emailType' => $pickerEmailType, | |
'identifier' => $id, | |
'identifierShort' => $id_short, | |
'identifierLabel' => $idLabel, | |
'identifierType' => $pickerIdentifierType | |
); | |
} | |
} | |
} | |
return $matches; | |
} | |
/** | |
* Return all Groups that a User belongs to in Grouper. | |
* Will also add OptOut Groups and flag them as joined so can display an Optout option in the UI. | |
* | |
* @param string $userId | |
* @param string $actorUserId | |
* @param array $cfg | |
* | |
* @return array Records of Groups from Grouper that the User belongs to | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function filteredMemberOfGroups(string $userId, string $actorUserId, array $cfg): array | |
{ | |
$this->initApi($cfg); | |
try { | |
$memberOfGroups = $this->memberOfGroups($actorUserId, $userId, $cfg); | |
// Determine which groups can be left by user, if wanted. | |
$optOutGroups = $this->grouperAPI->getUserMemberships($userId, $actorUserId, GrouperGroupTypeEnum::OPTOUTS); | |
$optOutGroupsNames = Hash::combine($optOutGroups, '{n}.name', '{n}.displayExtension'); | |
foreach ($memberOfGroups as &$memberOfGroup) { | |
$memberOfGroup['optOut'] = isset($optOutGroupsNames[$memberOfGroup['name']]); | |
} | |
return $this->getFriendlyWorkingGroupName($memberOfGroups, 'member'); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Find People based on mode and term | |
* | |
* @param integer $coId CO ID | |
* @param string $mode Search mode to apply filters for | |
* @param string|null $term Search block | |
* | |
* @return array Array of CO Person records | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function findForPicker(int $coId, string $mode, ?string $term): array | |
{ | |
$coPersonIds = []; | |
$this->CoPerson = ClassRegistry::init('CoPerson'); | |
// jquery Autocomplete sends the search as url?term=foo | |
if(!empty($term)) { | |
// Leverage-model-specific keyword search | |
// Note EmailAddress and Identifier don't support substring search | |
foreach(array('Name', 'EmailAddress', 'Identifier') as $m) { | |
$hits = $this->CoPerson->$m->search($coId, $term, 25); | |
$coPersonIds = array_merge($coPersonIds, Hash::extract($hits, '{n}.CoPerson.id')); | |
} | |
} | |
$coPersonIds = array_unique($coPersonIds); | |
// Look up additional information to provide hints as to which person is which. | |
// We only do this when there are relatively small numbers of results to | |
// avoid making a bunch of database queries early in the search. | |
return $this->dataConstructForPicker($coId, $term,$coPersonIds); | |
} | |
/** | |
* Return array of Working Groups for display on COManage site. | |
* Logic is for each WG to have one key=>value of main WG name, then array of all associated | |
* Groups. | |
* | |
* NOTE: This is a major hack due to Grouper not giving us the right logic for displaying, so have to run all | |
* groups through a mapped listing of types of Groups in a WG to see if match and then parse and massage to display | |
* | |
* @param array $groups Listing of Groups | |
* @return array Listing of Groups in WG format for display | |
* @since COmanage Registry v4.4.0 | |
*/ | |
private function getFriendlyWorkingGroupName(array $groups, string $method) { | |
$arrayIndex = 0; | |
$workingGroups = array(); | |
//First need to loop through all groups and pull in all top levels | |
$topLevelWG = array(); | |
foreach ($groups as $group) { | |
foreach ($this->wgStemsTopLevel as $stem) { | |
$len = strlen($stem); | |
if (substr(strtolower($group['name']), 0, $len) === $stem) { | |
$stemSections = explode(':', $group['name']); | |
//Get a third section, since will always by after ref:something:here | |
if (in_array($stemSections[2], $topLevelWG) === false) { | |
$topLevelWG[] = $stemSections[2]; | |
} | |
} | |
} | |
} | |
//Loop through groups to see if possibly part of a Working Group | |
foreach ($groups as &$group) { | |
foreach ($this->wgStemsAllGroups as $stem) { | |
$len = strlen($stem); | |
// if match to name of group within WG mapping then start making a WG group array | |
if (substr(strtolower($group['name']), 0, $len) === $stem) { | |
$tempGroup = $group; | |
if ($stem == 'ref:incommon-collab' || $stem == 'ref:internet2-collab') { | |
$mainGroup = true; | |
} else { | |
$mainGroup = false; | |
} | |
$stemSections = explode(':', $group['name']); | |
$displaySections = explode(':', $group['displayName']); | |
//Get second to last stem section | |
$sectionCount = 2; | |
//If group not part of a top level WG, then do not show! | |
if (in_array($stemSections[$sectionCount], $topLevelWG) === false) { | |
break; | |
} | |
$tempGroup['WGName'] = $stemSections[$sectionCount]; | |
$tempGroup['WGShowName'] = $displaySections[$sectionCount]; | |
// Get user type, which is after the WG name | |
if (isset($stemSections[$sectionCount + 1])) { | |
$tempGroup['WGRole'] = $stemSections[$sectionCount + 1]; | |
} else { | |
$tempGroup['WGRole'] = ''; | |
} | |
$appCount = 0; | |
$appName = ''; | |
foreach ($stemSections as $stemSection) { | |
//Skip first entry | |
if ($appCount > 0) { | |
if ($appCount < $sectionCount) { | |
if ($appCount == 1) { | |
$appName = $stemSection; | |
} else { | |
$appName = $appName . " - " . $stemSection; | |
} | |
} | |
} | |
$appCount += 1; | |
} | |
//changed the way email list are displayed to actually show lists email address. | |
if ($appName == 'sympa - internet2' || $appName == 'sympa - incommon') { | |
if ($appName == 'sympa - internet2') { | |
$appName = $tempGroup['WGName'] . '@lists.' . 'internet2.edu'; | |
} else { | |
$appName = $tempGroup['WGName'] . '@lists.' . 'incommon.org'; | |
} | |
} | |
$tempGroup['WGApp'] = $appName; | |
if ($method == 'member') { | |
if(!$mainGroup) { | |
$workingGroups[] = $tempGroup; | |
unset($groups[$arrayIndex]); | |
} | |
} else { | |
$workingGroups[] = $tempGroup; | |
unset($groups[$arrayIndex]); | |
} | |
} | |
} | |
$arrayIndex += 1; | |
} | |
$finalWorkingGroups = array(); | |
foreach ($workingGroups as $workingGroup) { | |
//Need to set first group in final Working Group array | |
if (count($finalWorkingGroups) == 0) { | |
$finalWorkingGroups[] = array( | |
'WGName' => $workingGroup['WGName'], | |
'WGShowName' => $workingGroup['WGShowName'], | |
'Groups' => array($workingGroup) | |
); | |
} else { | |
$foundMatch = false; | |
foreach ($finalWorkingGroups as &$finalWorkingGroup) { | |
if ($finalWorkingGroup['WGName'] == $workingGroup['WGName']) { | |
$finalWorkingGroup['WGShowName'] = $workingGroup['WGShowName']; | |
$finalWorkingGroup['Groups'][] = $workingGroup; | |
$foundMatch = true; | |
} | |
} | |
if (!$foundMatch) { | |
$finalWorkingGroups[] = array( | |
'WGName' => $workingGroup['WGName'], | |
'WGShowName' => $workingGroup['WGShowName'], | |
'Groups' => array($workingGroup) | |
); | |
} | |
} | |
} | |
$friendlyGroups = array_values($groups); | |
//Now need to add the groups back together for one set | |
foreach ($friendlyGroups as $friendlyGroup) { | |
$finalWorkingGroups[] = $friendlyGroup; | |
} | |
return $finalWorkingGroups; | |
} | |
/** | |
* Retrieve the identifier for a CO Person | |
* | |
* @param int $co_person_id | |
* @param string $ident_type | |
* | |
* @return string|null | |
*/ | |
public function getIdentifierFromPersonId(int $co_person_id, string $ident_type): ?string | |
{ | |
if(empty($co_person_id) || empty($ident_type)) { | |
return null; | |
} | |
// Find the identifier | |
$args = array(); | |
$args['conditions']['Identifier.type'] = $ident_type; | |
$args['conditions']['Identifier.status'] = SuspendableStatusEnum::Active; | |
$args['conditions']['Identifier.co_person_id'] = $co_person_id; | |
$args['contain'] = false; | |
$this->Identifier = ClassRegistry::init('Identifier'); | |
$identifier = $this->Identifier->find('first', $args); | |
if (!empty($identifier)) { | |
return $identifier['Identifier']['identifier']; | |
} | |
return null; | |
} | |
/** | |
* Get members associated to a specific Grouper Group | |
* NOTE: This list only shows members, it does not pull in other groups that may be attached in Grouper as | |
* members | |
* | |
* @param string $actorUserId Id of User | |
* @param string $groupName | |
* @param array $cfg | |
* | |
* @return array Listing of members in requested Grouper Group | |
* @throws GrouperLiteWidgetException Captured in Controller | |
* @throws JsonException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function getGroupMembers(string $actorUserId, string $groupName, array $cfg): array | |
{ | |
$this->initApi($cfg); | |
try { | |
$groupMembers = $this->grouperAPI->getGroupMembers($actorUserId, $groupName); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
if (count($groupMembers) < 1) { | |
return $groupMembers; | |
} | |
$finalMembers = []; | |
foreach ($groupMembers as $member) { | |
if ($member['sourceId'] !== 'g:gsa') { | |
$finalMembers[] = $member; | |
} | |
} | |
return $finalMembers; | |
} | |
/** | |
* Return all Grouper Groups that | |
* - the User(me) has a role of owner/admin | |
* - the User (member User) is a member | |
* | |
* @param string $managerId User(me) has a role of owner/admin | |
* @param string $userId User (member User) is a member | |
* @param array $cfg | |
* | |
* @return array | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function getManagedUsers(string $managerId, string $userId, array $cfg): array { | |
if(empty($userId) || empty($managerId)) { | |
return false; | |
} | |
$this->initApi($cfg); | |
try { | |
$resultsManagerAdmin = $this->grouperAPI->getUserMemberships($managerId, | |
$managerId, | |
GrouperGroupTypeEnum::ADMIN); | |
$resultsManagerUpdate = $this->grouperAPI->getUserMemberships($managerId, | |
$managerId, | |
GrouperGroupTypeEnum::UPDATE); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
$managerGroupSet = $this->removeDuplicates($resultsManagerAdmin, $resultsManagerUpdate); | |
try { | |
// Groups the user is a member of | |
$membersGroup = $this->grouperAPI->getUserGroups($managerId, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
// Extract the names of the Groups the member-user is a member of | |
$memberGroupNames = Hash::extract($membersGroup, '{n}.name'); | |
// Return the groups the user can join and is not a member of | |
return array_values( // Restart indexing from 0(zero) on the final array | |
array_filter( // Return the groups the member-user is a member | |
$managerGroupSet, | |
static fn($value) => in_array($value['name'], $memberGroupNames) | |
) | |
); | |
} | |
/** | |
* Return all Grouper Groups that the User has a role of owner/admin | |
* | |
* @param string $userId | |
* @param string $actorUserId | |
* @param array $cfg | |
* | |
* @return array | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function getOwnedGroups(string $userId, string $actorUserId, array $cfg): array | |
{ | |
if(empty($userId) || empty($actorUserId)) { | |
return false; | |
} | |
$this->initApi($cfg); | |
try { | |
$resultsAdmin = $this->grouperAPI->getUserMemberships($userId, | |
$actorUserId, | |
GrouperGroupTypeEnum::ADMIN); | |
$resultsUpdate = $this->grouperAPI->getUserMemberships($userId, | |
$actorUserId, | |
GrouperGroupTypeEnum::UPDATE); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
return $this->removeDuplicates($resultsAdmin, $resultsUpdate); | |
} | |
/** | |
* Potential use was for creating an adhoc group by a user, not associated to WG. | |
* | |
* Gets all Stems/Folders where User is admin/owner | |
* | |
* @param string $userId | |
* @param string $actorUserId | |
* | |
* @return array Array of Stems/Folders from Grouper | |
* @throws GrouperLiteWidgetException | |
*/ | |
public function getOwnedStems(string $userId, string $actorUserId): array | |
{ | |
try { | |
return $this->grouperAPI->getUserMemberships($userId, | |
$actorUserId, | |
GrouperGroupTypeEnum::ADMIN); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Search for Groups/Lists related to Search term. | |
* | |
* Will import all records the user can see and then do search in this code rather than call Grouper WS Search | |
* functionality. This is because the grouperName is autogenerated and this app needs to search | |
* attributes which the Grouper WS does not do. | |
* | |
* @param string $userId | |
* @param string $searchCriteria | |
* @param string $searchPage | |
* @param array $cfg | |
* | |
* @return array Records that meet search criteria | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function getSearchedGroups(string $userId, string $actorUserId, string $searchCriteria, string $searchPage, array $cfg): array | |
{ | |
$this->initApi($cfg); | |
try { | |
// Breakout page where search was called and forward to appropriate method for processing | |
$pageResults = isset($searchPage) ? $this->$searchPage(userId: $userId, | |
actorUserId: $actorUserId, | |
cfg: $cfg) : []; | |
$returnResults = []; | |
foreach ($pageResults as $result) { | |
$compare = $result; | |
unset($compare['extension']); | |
unset($compare['uuid']); | |
unset($compare['enabled']); | |
unset($compare['typeOfGroup']); | |
unset($compare['idIndex']); | |
$match = preg_grep("/$searchCriteria/i", $compare); | |
if (!empty($match)) { | |
$returnResults[] = $result; | |
} | |
} | |
return $searchCriteria == 'getSearchedGroups' ? $this->getFriendlyWorkingGroupName($returnResults, 'member') | |
: $returnResults; | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Determine if a User can use the Grouper Template to create a Working Group. | |
* | |
* @param string $userId User ID | |
* @param string $groupName Group Name | |
* @param array $cfg | |
* | |
* @return bool T for True and F for False | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function isGroupMember(string $userId, string $groupName, array $cfg): bool | |
{ | |
$this->initApi($cfg); | |
try { | |
$isMember = $this->grouperAPI->isMemberOfGroup($groupName, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
return (bool)$isMember; | |
} | |
/** | |
* Determine if a User can use the Grouper Template to create a Working Group. | |
* | |
* @param string $userId User ID | |
* @param array $cfg | |
* | |
* @return bool | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function isTemplateUser(string $userId, array $cfg): bool | |
{ | |
$this->initApi($cfg); | |
try { | |
return $this->grouperAPI->isMemberOfGroup(GrouperSpecialGroups::TEMPLATE_CREATION_GROUP, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Internal process used by other functions to fetch Groups the User is a member of | |
* | |
* @param string $actorUserId | |
* @param string $userId | |
* @param array $cfg | |
* | |
* @return array Records of Groups from Grouper that the User belongs to | |
* @throws GrouperLiteWidgetException | |
* @since COmanage Registry v4.4.0 | |
*/ | |
private function memberOfGroups(string $actorUserId, string $userId, array $cfg) | |
{ | |
$this->initApi($cfg); | |
try { | |
return $this->grouperAPI->getUserGroups($actorUserId, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
} | |
/** | |
* Return all Groups the User can JOIN | |
* Get all Groups with Optin attribute set and display ones User can join. | |
* Will Match up with Groups User is already a member of to determine which Optin groups to not display | |
* | |
* @param string $userId | |
* @param string $actorUserId | |
* @param array $cfg | |
* | |
* @return array Listing of Optin groups available in Grouper | |
* @throws GrouperLiteWidgetException Captured in Controller | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function optinGroups(string $userId, string $actorUserId, array $cfg): array | |
{ | |
$this->initApi($cfg); | |
try { | |
// Groups the user can join or leave | |
$joinOrLeave = $this->grouperAPI->getUserMemberships($userId, | |
$actorUserId, | |
GrouperGroupTypeEnum::OPTINS); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
try { | |
// Groups the user is a member of | |
$userGroups = $this->grouperAPI->getUserGroups($actorUserId, $userId); | |
} catch (Exception $e) { | |
CakeLog::write('error', __METHOD__ . ': An error occurred'); | |
throw $e; | |
} | |
// I am currently not a member to any Group. Return everything | |
if(empty($userGroups)) { | |
return $joinOrLeave; | |
} | |
// 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 | |
return array_values( // Restart indexing from 0(zero) on the final array | |
array_filter( // Return the groups I am currently not a member | |
$joinOrLeave, | |
static fn($value) => !in_array($value['name'], $userGroupsNames) | |
) | |
); | |
} | |
/** | |
* Remove a member from a specific Grouper Group | |
* | |
* @param string $actorUserId | |
* @param string $groupName | |
* @param string $removeUserId | |
* @param array $cfg | |
* | |
* @return bool success of Request | |
* @throws GrouperLiteWidgetException Captured in Controller | |
* @throws JsonException Captured in Controller | |
* @since COmanage Registry v4.4.0 | |
*/ | |
public function removeGroupMember(string $actorUserId, | |
string $groupName, | |
string $removeUserId, | |
array $cfg): bool | |
{ | |
$this->initApi($cfg); | |
return $this->grouperAPI->removeGroupMember($actorUserId, $groupName, $removeUserId); | |
} | |
/** | |
* Removes duplicates where the user is the owner and the updater of the group. Just one line instead of two. | |
* | |
* @param array $arrOne | |
* @param array $arrTwo | |
* @return array | |
*/ | |
public function removeDuplicates(array $arrOne, array $arrTwo) | |
{ | |
// If one of the arrays is empty then return the other one as is | |
if(empty($arrOne) && empty($arrTwo)) { | |
return []; | |
} else if(empty($arrOne)) { | |
return $arrTwo; | |
} else if(empty($arrTwo)) { | |
return $arrOne; | |
} | |
$uniqueArr = Hash::combine($arrOne, '{n}.uuid', '{n}'); | |
foreach($arrTwo as $data) { | |
if(!isset($uniqueArr[ $data['uuid'] ])) { | |
$uniqueArr[ $data['uuid'] ] = $data; | |
} | |
} | |
return array_values($uniqueArr); | |
} | |
} |