Skip to content

Users i manage #16

Merged
merged 9 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 86 additions & 28 deletions Controller/GrouperGroupsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class GrouperGroupsController extends GrouperLiteWidgetAppController
public $helpers = array('Html', 'Form', 'Flash');

// Dynamic properties are deprecated, so we will define the property here
protected $userId = null;
private $userId = null;

public $uses = array(
'GrouperLiteWidget.GrouperGroup',
Expand All @@ -67,8 +67,8 @@ public function addSubscriber(): void
$this->layout = null;
$this->autoRender = false;

$groupName = urldecode($this->request->query['group']);
$addUserId = urldecode($this->request->query['userId']);
$groupName = $this->request->data['group'];
$addUserId = $this->request->data['userId'];

// Need to see if coming from AdHoc or from a WG (Working Group)
$groupNameFormatted = strpos($groupName, ':') === false ? 'ref:incommon-collab:' . $groupName . ':users'
Expand Down Expand Up @@ -146,6 +146,14 @@ public function beforeRender() {
$this->set('vv_coid', $this->cur_co['Co']['id']);
}

/**
* @return null
*/
public function getUserId()
{
return $this->userId;
}

/**
* Perform a "keyword" search for CO People, sort of like the CO Dashboard
* cross controller search, but intended specifically for "people finder"
Expand Down Expand Up @@ -234,7 +242,7 @@ public function groupSubscribers(): void
/**
* Listing of all Grouper Groups owned/admin by User Or search those Grouper Groups
*/
public function groupOwnerApi() {
public function groupOwnerApi(): void {
//Set initial setting
$arguments = [
'userId' => $this->userId,
Expand All @@ -261,7 +269,7 @@ public function groupOwnerApi() {
CakeLog::write('error', __METHOD__ . "::{$errorHint}: " . var_export($e->getMessage(), true));
$this->restResponse(HttpStatusCodesEnum::HTTP_INTERNAL_SERVER_ERROR, ErrorsEnum::Exception);

$this->set('groupsowners', []);
$this->set('groupowners', []);
$this->Flash->set(_txt('pl.grouperlite.message.flash.owner-group-failed'), array('key' => 'error'));
return;
}
Expand All @@ -275,7 +283,7 @@ public function groupOwnerApi() {
* This includes self-joined Optin Groups, as well as required Groups User cannot leave
*
*/
public function groupMemberApi() {
public function groupMemberApi(): void {
//Set initial setting
$arguments = [
'userId' => $this->userId,
Expand Down Expand Up @@ -404,7 +412,7 @@ public function index(): void
* @return array|bool Permissions
* @since COmanage Registry v3.2.0
*/
function isAuthorized(): array|bool
public function isAuthorized(): array|bool
{
$roles = $this->Role->calculateCMRoles();
$cfg = $this->CoGrouperLiteWidget->getConfig();
Expand All @@ -420,31 +428,32 @@ function isAuthorized(): array|bool
&& is_array($identifiers)
&& isset($identifiers['Identifier']['identifier'])
) {
$this->userId = $identifiers['Identifier']['identifier'];
$this->setUserId($identifiers['Identifier']['identifier']);
}

// Determine what operations this user can perform
// Construct the permission set for this user, which will also be passed to the view.
//Note: Leaving in current format, in case need to restrict certain pages, can just remove true and add params.
$p = array();

$p['index'] = true;
$p['groupowner'] = true;
$p['groupownerapi'] = true;
$p['groupoptin'] = true;
$p['groupoptinapi'] = true;
$p['groupmember'] = true;
$p['groupmemberapi'] = true;
$p['getBaseConfig'] = true;
$p['groupSubscribers'] = true;
$p['addSubscriber'] = true;
$p['findSubscriber'] = true;
$p['removeSubscriber'] = true;

$p['groupCreate'] = true;
$p['joinGroup'] = true;
$p['leaveGroup'] = true;
$p['groupcreatetemplate'] = true;
$p = [];

$p['index'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupowner'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupownerapi'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupoptin'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupoptinapi'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupmember'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupmemberapi'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['getBaseConfig'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupSubscribers'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['addSubscriber'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['findSubscriber'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['usermanager'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['usermanagerapi'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['removeSubscriber'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);

$p['groupCreate'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['joinGroup'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['leaveGroup'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);
$p['groupcreatetemplate'] = ($roles['cmadmin'] || $roles['coadmin'] || $roles['comember']);

$this->set('permissions', $p);

Expand Down Expand Up @@ -596,6 +605,55 @@ public function restResponse(int $status,
$this->response->send();
}

/**
* @param null $userId
*/
private function setUserId($userId): void
{
$this->userId = $userId;
}

/**
* UserManager vue route for rendering
*
* @return void
*/
public function userManager(): void
{
$this->render('index');
}

/**
* Display all Groups for the user i manage
*/
public function userManagerApi(): void
{
//Set initial setting
$cfg = $this->CoGrouperLiteWidget->getConfig();

if (!isset($this->request->query['memberid'])) {
$this->restResponse(HttpStatusCodesEnum::HTTP_BAD_REQUEST, ErrorsEnum::Exception);
}

$memberId = urldecode($this->request->query['memberid']);

try {
$groupsimanage = $this->GrouperGroup->getManagedUsers($this->userId,
$memberId,
$cfg);
} catch (Exception $e) {
CakeLog::write('error', __METHOD__ . '::get Managed Users: ' . var_export($e->getMessage(), true));
$this->restResponse(HttpStatusCodesEnum::HTTP_INTERNAL_SERVER_ERROR, ErrorsEnum::Exception);

$this->set('groupsimanage', []);
return;
}

$this->set(compact('groupsimanage'));
$this->set('_serialize', 'groupsimanage');

}

/**
* Override the default sanity check performed in AppController
*
Expand Down
3 changes: 2 additions & 1 deletion Lib/lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
'pl.grouperlite.action.view-members' => 'View members',
'pl.grouperlite.action.grouper' => 'Grouper',
'pl.grouperlite.action.members' => 'Members',
'pl.grouperlite.action.memberships' => 'Memberships',
'pl.grouperlite.action.close' => 'Close',
'pl.grouperlite.action.clear' => 'Clear',
'pl.grouperlite.action.add-user' => 'Add',
Expand Down Expand Up @@ -163,7 +164,7 @@
'pl.grouperlite.form.template.value.positive' => 'Yes',
'pl.grouperlite.form.template.value.negative' => 'No',

'pl.grouperlite.search.tags.text' => 'Search',
'pl.grouperlite.title.search' => 'Search',

'pl.grouperlite.pagination.counter' => 'Viewing {:start}-{:end} of {:count}',
'pl.grouperlite.attributes.zero-state' => 'No Attributes Associated to this Group.',
Expand Down
61 changes: 59 additions & 2 deletions Model/GrouperGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,10 @@ public function findForPicker(int $coId, string $mode, ?string $term): array
$idArr = $p['Identifier'];
$emailArr = $p['EmailAddress'];
$email = '';
$email_short = '';
$emailLabel = '';
$id = '';
$id_short = '';
$idLabel = '';

// Iterate over the email array
Expand All @@ -228,6 +230,7 @@ public function findForPicker(int $coId, string $mode, ?string $term): array
foreach($emailArr as $e) {
if($e['type'] == $pickerEmailType) {
$email = $e['mail'];
$email_short = mb_strimwidth($e['mail'], 0, 30, '...');
break;
}
}
Expand All @@ -243,7 +246,8 @@ public function findForPicker(int $coId, string $mode, ?string $term): array
}
foreach($idArr as $i) {
if($i['type'] == $pickerIdentifierType) {
$id = mb_strimwidth($i['identifier'], 0, 30, '...');
$id_short = mb_strimwidth($i['identifier'], 0, 30, '...');
$id = $i['identifier'];
break;
}
}
Expand All @@ -255,9 +259,13 @@ public function findForPicker(int $coId, string $mode, ?string $term): array
'value' => $p['CoPerson']['id'],
'label' => $label,
'email' => $email,
'emailShort' => $email_short,
'emailLabel' => $emailLabel,
'emailType' => $pickerEmailType,
'identifier' => $id,
'identifierLabel' => $idLabel
'identifierShort' => $id_short,
'identifierLabel' => $idLabel,
'identifierType' => $pickerIdentifierType
);
}
}
Expand Down Expand Up @@ -318,6 +326,55 @@ public function getOwnedGroups(string $userId, array $cfg): array
return $this->removeDuplicates($resultsAdmin, $resultsUpdate);
}

/**
* Return all Grouper Groups that
* - the User(me) has a role of owner/admin
* - the User(member User) is a member
*
* @param string $managerId
* @param string $memberId
* @param array $cfg
*
* @return array
* @throws GrouperLiteWidgetException
* @since COmanage Registry v4.4.0
*/
public function getManagedUsers(string $managerId, string $memberId, array $cfg): array {
if(empty($managerId) || empty($memberId)) {
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, $memberId);
} 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)
)
);
}

/**
* Potential use was for creating adhoc group by a user, not associated to WG.
*
Expand Down
12 changes: 12 additions & 0 deletions View/CoGrouperLiteWidgets/display.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ $idsuffix = rand();
'glid' => $glid
)
); ?>"
},
{
label: "<?php echo _txt('pl.grouperlite.nav.users-presided'); ?>",
url: "<?php print $this->Html->url(
array(
'plugin' => $pl,
'controller' => 'grouper_groups',
'action' => 'usermanager',
'co' => $coid,
'glid' => $glid
)
); ?>"
}
]
}
Expand Down
1 change: 1 addition & 0 deletions View/GrouperGroups/base.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ echo $this->Html->meta(
array('inline' => false)
);

print $this->Html->script('GrouperLiteWidget.autocomplete.grouperplugin') . PHP_EOL;
print $this->element('GrouperLiteWidget.base-styles');
print $this->Html->css('GrouperLiteWidget.co-grouper-plugin') . PHP_EOL;

Expand Down
9 changes: 8 additions & 1 deletion View/GrouperGroups/index.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import GroupMember from '<?= $this->webroot ?>grouper_lite_widget/js/page/GroupMember.js<?= $suffix ?>';
import GroupOptin from '<?= $this->webroot ?>grouper_lite_widget/js/page/GroupOptin.js<?= $suffix ?>';
import GroupOwner from '<?= $this->webroot ?>grouper_lite_widget/js/page/GroupOwner.js<?= $suffix ?>';
import UserManager from '<?= $this->webroot ?>grouper_lite_widget/js/page/UserManager.js<?= $suffix ?>';

<?php
$baseUrl = $vv_config['CoGrouperLiteWidget']['grouper_url'];
Expand All @@ -40,6 +41,10 @@
{
path: '/groupowner/co:co/glid:glid',
component: GroupOwner
},
{
path: '/usermanager/co:co/glid:glid',
component: UserManager
}
]
},
Expand Down Expand Up @@ -87,8 +92,8 @@
removeSubscriberError: "<?= _txt('pl.grouperlite.message.flash.remove-subscriber-failed') ?>",
removeSubscriberSuccess: "<?= _txt('pl.grouperlite.message.flash.remove-subscriber-success') ?>",
getSubscriberError: "<?= _txt('pl.grouperlite.message.flash.group-detail-members-failed') ?>",
searchTag: "<?= _txt('pl.grouperlite.search.tags.text') ?>",
peoplePickerPlaceHolder: "<?= _txt('op.grm.add.placeholder') ?>",
memberships: "<?= _txt('pl.grouperlite.action.memberships') ?>",
noaccess: "<?= _txt('pl.grouperlite.members.noaccess') ?>",
empty: "<?= _txt('pl.grouperlite.members.empty') ?>",
join: "<?= _txt('pl.grouperlite.action.join') ?>",
Expand All @@ -102,6 +107,7 @@
memberships: "<?= _txt('pl.grouperlite.nav.memberships') ?>",
optin: "<?= _txt('pl.grouperlite.nav.groups-can-join') ?>",
owner: "<?= _txt('pl.grouperlite.nav.groups-presided') ?>",
manager: "<?= _txt('pl.grouperlite.nav.users-presided') ?>",
},
columns: <?php print_r(json_encode(array(
'name' => _txt('pl.grouperlite.table.name'),
Expand All @@ -124,6 +130,7 @@
add: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/addSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
group: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupSubscribers/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
memberships: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupmemberapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
managing: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/usermanagerapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
optin: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupoptinapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
owner: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupownerapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
},
Expand Down
8 changes: 8 additions & 0 deletions webroot/css/co-grouper-plugin.css
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,12 @@ a.list-group-item-action:hover .fa {
right: 38px;
bottom: 10px;
margin-right: -26px;
}

.grouper_groups #co-loading span,
.grouper_groups #co-loading-redirect span,
.grouper_groups .co-loading-mini span {
animation: 1.2s linear infinite both loading;
background-color: var(--teal);
display: inline-block;
}
Loading