Skip to content
Permalink
e6611f0bb8
Switch branches/tags

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?
Go to file
 
 
Cannot retrieve contributors at this time
665 lines (556 sloc) 19.7 KB
<?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', 'GrouperLite.Lib/');
App::uses('GrouperAttribute', 'GrouperLite.Model/');
/***
* Class GrouperGroup
*
* Model class that does most of the heavy lifting in Grouper Lite Widget
*/
class GrouperGroup extends GrouperLiteAppModel
{
/** @var string $name used by CakePHP for locating model */
public $name = "GrouperGroup";
/** @var GrouperApiAccess $grouperAPI */
public $grouperAPI = null;
private $totalRecords = 0;
/** @var string Group whose members can create Groups via Template process*/
private $templateCreationGroup = 'ref:workinggroupadmins';
/**
* Verifies if user is an owner/admin of a group and then stores results in Session.
* Session variable is reset on Group Creation and Group Deletion
*
* @param string $userId Id of User
* @return String T or F
* @throws GrouperLiteException
*
* @see GrouperGroup::resetUserOwner()
*
*/
public function isUserOwner(string $userId) {
if (CakeSession::check('Plugin.Grouper.isUserOwner')) {
return CakeSession::read('Plugin.Grouper.isUserOwner');
}
$this->initApi();
try {
$args = array();
$args['userId'] = $userId;
$ownGroups = $this->grouperAPI->getOwnedGroups($args);
if (count($ownGroups) > 0) {
CakeSession::write('Plugin.Grouper.isUserOwner', 'T');
return 'T';
}
CakeSession::write('Plugin.Grouper.isUserOwner', 'F');
return 'F';
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Used to instantiate API class
*
* Tried to use the constructor for GrouperGroup to set this but it was triggering the GrouperAPIAccess class
* to instantiate before the Controller was able populate the connection settings from the DB into the Session,
* so error was being thrown.
* Now will call this before each function call to verify set.
*/
private function initApi() {
if ($this->grouperAPI == null) {
$this->grouperAPI = new GrouperApiAccess();
}
}
/**
* Return all Groups that a User belongs to in Grouper.
* Will also add Optin Groups and flag them as joined so can display Optout option in UI.
*
* @param array $conditions Listing of conditions for display of records, including UserId
* @return array Records of Groups from Grouper that the User belongs to
* @throws GrouperLiteException
*
*/
public function filteredMemberOfGroups(array $conditions) {
$this->initApi();
try {
$memberOfGroups = $this->memberOfGroups($conditions);
// Determine which groups can be left by user, if want.
$optInGroups = $this->grouperAPI->getOptinGroups($conditions);
foreach ($memberOfGroups as &$memberOfGroup) {
foreach ($optInGroups as $key => $value) {
if ($value['name'] == $memberOfGroup['name']) {
//Match!
$memberOfGroup['optedin'] = true;
//Remove Optin group since already found and now less loops
unset($optInGroups[$key]);
break;
}
}
}
return $this->getFriendlyName($memberOfGroups);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
public function filteredMemberOfEmails(array $conditions) {
$memberOfEmails = $this->filteredMemberOfGroups($conditions);
// Strip out all Groups that are not in Sympa Stem/Directory
foreach($memberOfEmails as $key => $value){
if(strpos($value['name'], 'sympa') === false) {
unset($memberOfEmails[$key]);
}
}
return $memberOfEmails;
}
/**
* Internal process used by other functions to fetch Groups the User is a member of
*
* @param array $conditions Listing of conditions for display of records, including UserId
* @return array Records of Groups from Grouper that the User belongs to
* @throws GrouperLiteException
*
*/
private function memberOfGroups(array $conditions) {
try {
return $this->grouperAPI->getGrouperMemberOfGroups($conditions);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Determine if result set contains friendly name, if so add as a new attribute in result set
*
* @param array $groups Current result set of Groups
* @return array Same result set with added param for friendly name
*
*/
private function getFriendlyName(array $groups) {
//NOT fetching attributes now, just using name display name as friendly name, if different from name field
foreach ($groups as &$group) {
//$group['friendlyName'] = $group['displayName'];
$nameSections = explode(':', $group['name']);
$friendlySections = explode(':', $group['displayName']);
$numberNameSections = count($nameSections);
for ($x = 0; $x < $numberNameSections; $x++) {
if ($nameSections[$x] == $friendlySections[$x]) {
unset($friendlySections[$x]);
}
}
$group['friendlyName'] = implode(':', $friendlySections);
if (strlen($group['friendlyName']) == 0) {
$group['friendlyName'] = $group['name'];
}
}
return $groups;
/* Old Process, keeping in case changes back!
foreach ($groups as &$group) {
$group['friendlyName'] = $group['displayName'];
$attributes = $this->grouperAPI->getGroupAttributes(array('conditions' => array('groupName' => $group['displayName'])));
foreach ($attributes as $attribute) {
if ($attribute['attributeDefNameName'] == $this->friendly) {
if (isset($attribute['wsAttributeAssignValues']['valueSystem'])) {
$group['friendlyName'] = $attribute['wsAttributeAssignValues']['valueSystem'];
}
break;
}
}
}*/
}
/**
* Gets the Grouper Groups params and values as well as its associated attributes.
*
* @param string $groupName Name of Group, do not confuse with DisplayName field!
* @return array An set of attributes associated to a specific Grouper Group
* @throws GrouperLiteException
*/
public function groupDescriptions(string $groupName) {
$this->initApi();
try {
$args = array();
$args['groupName'] = $groupName;
$groupDescription = $this->grouperAPI->getGrouperGroupDescription($args);
$groupInfo = $this->getFriendlyName($groupDescription);
//make call to get attributes for group
$grouperAtt = new GrouperAttribute();
$groupAttributes = $grouperAtt->getGroupAttributes($groupName);
$groupInfo[0]["attributes"] = $groupAttributes;
return $groupInfo;
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Process for User to Leave a Group
*
* @param string $userId Id of User
* @param string $groupName Name of Group Leaving, do not confuse with DisplayName field!
* @return bool True|False
* @throws GrouperLiteException
*
*/
public function leaveGroup(string $userId, string $groupName) {
$this->initApi();
try {
$args = array();
$args['LeaveJoin'] = 'Leave';
$args['userId'] = $userId;
$args['groupName'] = $groupName;
return $this->grouperAPI->grouperGroupLeaveOrJoin($args);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Process for User to Join a Group
*
* @param string $userId Id of User
* @param string $groupName Name of Group Joining, do not confuse with DisplayName field!
* @return bool True|False
* @throws GrouperLiteException
*
*/
public function joinGroup(string $userId, string $groupName) {
$this->initApi();
try {
$args = array();
$args['LeaveJoin'] = 'Join';
$args['userId'] = $userId;
$args['groupName'] = $groupName;
return $this->grouperAPI->grouperGroupLeaveOrJoin($args);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Return all Grouper Groups that the User has a role of owner/admin
*
* @param array $conditions Listing of conditions for display of records, including UserId
* @return array
* @throws GrouperLiteException
*
*/
public function ownerGroups(array $conditions) {
$this->initApi();
try {
$ownGroups = $this->grouperAPI->getOwnedGroups($conditions);
return $this->getFriendlyName($ownGroups);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Get members associated to a specific Grouper Group
*
* @param array $conditions Listing of conditions for display of records
* @return array Listing of members in requested Grouper Group
* @throws GrouperLiteException Captured in Controller
*
*/
public function membersInGroup(array $conditions) {
$this->initApi();
try {
return $this->grouperAPI->getMembersInGroup($conditions);
} 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 array $conditions Listing of conditions for display of records, including UserId
* @return array Listing of Optin groups available in Grouper
* @throws GrouperLiteException Captured in Controller
*/
public function optinGroups(array $conditions) {
$this->initApi();
try {
$joinOrLeave = $this->grouperAPI->getOptinGroups($conditions);
$userGroups = $this->memberOfGroups($conditions);
//See if Optin group match any of the groups user already belongs to.
foreach ($joinOrLeave as $key => $value) {
foreach ($userGroups as $userGroup) {
if ($value['name'] == $userGroup['name']) {
//Match!!
//Removing from array since already a member of.
unset($joinOrLeave[$key]);
break;
}
}
}
//$finalSet = $this->paginateRecords($joinOrLeave, $conditions);
return $this->getFriendlyName($joinOrLeave);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
public function optinEmailGroups(array $conditions) {
$allGroups = $this->optinGroups($conditions);
// Strip out all Groups that are not in Sympa Stem/Directory
foreach($allGroups as $key => $value){
if(strpos($value['name'], 'sympa') === false) {
unset($allGroups[$key]);
}
}
return $allGroups;
}
/**
* Determine if User can use the Grouper Template to create a suite of Groups including Email lists.
*
* @param string $userId Id of User
* @return string T for True and F for False
* @throws GrouperLiteException
*/
public function isTemplateUser(string $userId) {
if (CakeSession::check('Plugin.Grouper.isTemplateUser')) {
return CakeSession::read('Plugin.Grouper.isTemplateUser');
}
$this->initApi();
try {
$args = array();
$args['userId'] = $userId;
$memberOfGroups = $this->grouperAPI->getGrouperMemberOfGroups($args);
//now cycle through and see if part of correct group to be able to use template
$member = 'F';
foreach ($memberOfGroups as $memberOfGroup) {
if ($memberOfGroup['name'] == $this->templateCreationGroup) {
$member = 'T';
break;
}
}
if ($member == 'T') {
CakeSession::write('Plugin.Grouper.isTemplateUser', 'T');
return 'T';
}
CakeSession::write('Plugin.Grouper.isTemplateUser', 'F');
return 'F';
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* 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 bool True if successfully created record
* @throws GrouperLiteException
*
*/
public function createGroupWithTemplate(string $userId, array $groupData) {
$this->initApi();
try {
//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;
// Reset Session variable that shows if User is an owner or not
$this->resetUserOwner();
return $this->grouperAPI->createGroupWithTemplate($args);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Delete a Grouper Group using the Template methodology in Grouper
*
* @param string $userId Id of User
* @param array $groupData Data needed to delete a Grouper Group via Template
* @return bool True if successfully deleted record
* @throws GrouperLiteException
*
*/
public function deleteGroupWithTemplate(string $userId, array $groupData) {
$this->initApi();
try {
$args = array();
$args['userId'] = $userId;
$args['workingGroupExt'] = $groupData['workingGroupExt'];
// Reset Session variable that shows if User is an owner or not
$this->resetUserOwner();
return $this->grouperAPI->deleteGroupWithTemplate($args);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Creates/Updates a new Grouper Group not Template related
*
* @param string $userId Id of user
* @param array $data Data from form to Save in Grouper as a Group
* @return bool True if saved | False if already created
* @throws GrouperLiteException
*
*/
public function createUpdateGroup(string $userId, array $data) {
$this->initApi();
try {
$args = $data;
$args['userId'] = $userId;
// Reset Session variable that shows if User is an owner or not
$this->resetUserOwner();
return $this->grouperAPI->createUpdateGroup($args);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Private function used to reset the IsUserOwner Session variable,
* that maintains the status of a user being an owner/admin of a group
*
* @see GrouperGroup::isUserOwner()
*/
private function resetUserOwner() {
if (CakeSession::check('Plugin.Grouper.isUserOwner')) {
CakeSession::delete('Plugin.Grouper.isUserOwner');
}
}
/**
* Get Grouper Stems where User has authority to create a Grouper Group
*
* @param string $userId Id of User
* @return array Stem records
* @throws GrouperLiteException
*/
public function getOwnedStems(string $userId) {
$this->initApi();
try {
$args = array();
$args['userId'] = $userId;
return $this->grouperAPI->getOwnedStems($args);
} 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 due to the fact that the grouperName is autogenerated and this app needs to search
* attributes which the Grouper WS does not do.
*
* @param array $conditions Listing of conditions for display of records, including UserId
* @return array Records that meet search criteria
* @throws Exception Captured in Controller
*/
public function getSearchedGroups(array $conditions) {
$this->initApi();
try {
//Breakout page where search was called and forward to appropriate method for processing
$page = $conditions['searchpage'];
$pageResults = $this->$page($conditions);
$returnResults = array();
$searchCriteria = $conditions['searchcriteria'];
foreach ($pageResults as $result) {
$match = preg_grep("/$searchCriteria/i", $result);
if (!empty($match)) {
$returnResults[] = $result;
}
}
return $returnResults;
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . ': An error occurred');
throw $e;
}
}
/**
* Method needed to support Pagination
* Adjusted to fit the data source being the Grouper API vs DB calls
*
* @param array $conditions Listing of conditions for display of records with pagination
* @return array Records requested by user with pagination support
*
*/
public function paginate($conditions) {
//Pull out the method that should be run.
$method = $conditions['method'];
$resultSet = $this->$method($conditions);
return $this->paginateRecords($resultSet, $conditions);
}
/**
* Parses returned records to display only requested records for pagination.
*
* @param array $recSet All Grouper Records associated to User's request
* @param array $conditions Listing of conditions for display of records with pagination
* @return array Records requested by user with pagination support
*
*/
private function paginateRecords(array $recSet, array $conditions) {
//set for pagination record count
$this->totalRecords = count($recSet);
//Return all, if requested
if (strtolower($conditions['limit']) == 'all') {
return $recSet;
}
//Now slice recordset to return correct set of records.
$page = $conditions['page'] - 1;
$limit = $conditions['limit'];
if ($page == 0) {
$start = 0;
} else {
$start = $page * $limit;
}
$end = $start + $limit;
return array_slice($recSet, $start, $end);
}
/**
* Needed method to support Cake's pagination in the views
*
* @param null $conditions Listing of conditions for display of records with pagination
* @param int $recursive
* @param array $extra
* @return int Total number of Grouper Records returned by Grouper API call
*
*/
public function paginateCount($conditions = null, $recursive = 0,
$extra = array()) {
return $this->totalRecords;
}
}