コード例 #1
0
 function &getAllocationsForFolderAndRole($iFolderId, $iRoleId)
 {
     // FIXME the query we use here is ... not very pleasant.
     // NBM: is this the "right" way to do this?
     $raTable = KTUtil::getTableName('role_allocations');
     $fTable = Folder::_table();
     $oFolder =& Folder::get($iFolderId);
     // if its an invalid folder, we simply return null, since this is undefined anyway.
     if (PEAR::isError($oFolder)) {
         return null;
     }
     $parents = Folder::generateFolderIds($iFolderId);
     // FIXME what (if anything) do we need to do to check that this can't be used as an attack?
     $folders = '(' . $parents . ')';
     $sQuery = "SELECT ra.id as `id` FROM " . $raTable . " AS ra " . ' LEFT JOIN ' . $fTable . ' AS f ON (f.id = ra.folder_id) ' . ' WHERE f.id IN ' . $folders . ' AND ra.role_id = ?' . ' ORDER BY CHAR_LENGTH(f.parent_folder_ids) desc, f.parent_folder_ids DESC';
     $aParams = array($iRoleId);
     $aRoleAllocIds = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'id');
     if (false) {
         print '<pre>';
         var_dump($aRoleAllocIds);
         print '';
         print $sQuery;
         print '</pre>';
     }
     if (empty($aRoleAllocIds)) {
         return null;
     }
     $iAllocId = $aRoleAllocIds[0];
     // array pop?
     return RoleAllocation::get($iAllocId);
 }
コード例 #2
0
 function updatePersonalFolderRoleAllocation($oPersonalFolder)
 {
     //Assign user to the WorkSpaceOwner role
     $personalFolderID = $oPersonalFolder->getId();
     $tempWorkSpaceOwnerRoleID = $this->getRoleIdByName('WorkSpaceOwner');
     $WorkSpaceOwnerRoleID = $tempWorkSpaceOwnerRoleID[0]['id'];
     $oRoleAllocation = new RoleAllocation();
     if ($oRoleAllocation == null) {
         $this->session->logout();
         return _kt('Error: Cannot create WorkSpaceOwner role allocation on personal folder');
     }
     $oRoleAllocation->setFolderId($personalFolderID);
     $oRoleAllocation->setRoleId($WorkSpaceOwnerRoleID);
     $aRoleAllowed = array();
     $oRoleAllocation->setAllowed($aRoleAllowed);
     //It might be a problem that i'm not doing a "start transaction" here.
     //Unable to roll back in event of db failure
     $res = $oRoleAllocation->create();
     if (!$res === true) {
         $this->session->logout();
         return _kt('Error: cannot create role allocation');
     }
     //The role is first created and then the current user is allocated to the role below
     $oPD = $oRoleAllocation->getPermissionDescriptor();
     $aRoleAssignAllowed = $oPD->getAllowed();
     $aUserId[] = $this->oUser->getId();
     $aRoleAssignAllowed['user'] = $aUserId;
     $oRoleAllocation->setAllowed($aRoleAssignAllowed);
     $res = $oRoleAllocation->update();
     $this->renegeratePermissionsForRole($oRoleAllocation->getRoleId(), $personalFolderID);
 }
コード例 #3
0
 /**
  * Update's the permission lookup on one folder or document,
  * non-recursively.
  */
 function updatePermissionLookup(&$oFolderOrDocument, $aOptions = null)
 {
     $is_a_folder = is_a($oFolderOrDocument, 'Folder');
     $is_a_document = is_a($oFolderOrDocument, 'Document') || is_a($oFolderOrDocument, 'KTDocumentCore');
     //ensure that the document shortcut is being updated.
     if ($is_a_document && $oFolderOrDocument->isSymbolicLink()) {
         $oFolderOrDocument->switchToRealCore();
     }
     $oChannel = null;
     $aMapPermAllowed = null;
     $oPermLookup = null;
     if (!is_null($aOptions)) {
         $oChannel = $aOptions['channel'];
         $aMapPermAllowed = $aOptions['map_allowed'];
         $oPermLookup = $aOptions['perm_lookup'];
     }
     if (!$is_a_folder && !$is_a_document) {
         return;
         // we occasionally get handed a PEAR::raiseError.  Just ignore it.
     }
     if (is_null($oChannel)) {
         $oChannel =& KTPermissionChannel::getSingleton();
     }
     if ($is_a_folder) {
         $msg = sprintf("Updating folder %s", join('/', $oFolderOrDocument->getPathArray()));
     } else {
         if (is_a($oFolderOrDocument, 'Document')) {
             //modify the message to reflect that a shortcut is begin updated
             if ($oFolderOrDocument->isSymbolicLink()) {
                 $msg = sprintf("Updating shortcut to %s", $oFolderOrDocument->getName());
             } else {
                 $msg = sprintf("Updating document %s", $oFolderOrDocument->getName());
             }
         } else {
             $msg = sprintf("Updating document %d", $oFolderOrDocument->getId());
         }
     }
     $oChannel->sendMessage(new KTPermissionGenericMessage($msg));
     //var_dump($msg);
     $iPermissionObjectId = $oFolderOrDocument->getPermissionObjectID();
     if (empty($iPermissionObjectId)) {
         return;
     }
     $oPO = KTPermissionObject::get($iPermissionObjectId);
     if (is_null($aMapPermAllowed)) {
         $aPAs = KTPermissionAssignment::getByObjectMulti($oPO);
         $aMapPermAllowed = array();
         foreach ($aPAs as $oPA) {
             $oPD = KTPermissionDescriptor::get($oPA->getPermissionDescriptorID());
             $aGroupIDs = $oPD->getGroups();
             $aUserIDs = array();
             $aRoleIDs = $oPD->getRoles();
             $aAllowed = array('group' => $aGroupIDs, 'user' => $aUserIDs, 'role' => $aRoleIDs);
             $aMapPermAllowed[$oPA->getPermissionID()] = $aAllowed;
         }
     }
     if (!$is_a_folder) {
         $aDynamicConditions = KTPermissionDynamicCondition::getByPermissionObject($oPO);
         if (!PEAR::isError($aDynamicConditions)) {
             foreach ($aDynamicConditions as $oDynamicCondition) {
                 $iConditionId = $oDynamicCondition->getConditionId();
                 if (KTSearchUtil::testConditionOnDocument($iConditionId, $oFolderOrDocument)) {
                     $iGroupId = $oDynamicCondition->getGroupId();
                     $aPermissionIds = $oDynamicCondition->getAssignment();
                     foreach ($aPermissionIds as $iPermissionId) {
                         $aCurrentAllowed = KTUtil::arrayGet($aMapPermAllowed, $iPermissionId, array());
                         $aCurrentAllowed['group'][] = $iGroupId;
                         $aMapPermAllowed[$iPermissionId] = $aCurrentAllowed;
                     }
                 }
             }
         }
     }
     if (!$is_a_folder) {
         $oState = KTWorkflowUtil::getWorkflowStateForDocument($oFolderOrDocument);
         if (!(PEAR::isError($oState) || is_null($oState) || $oState == false)) {
             $aWorkflowStatePermissionAssignments = KTWorkflowStatePermissionAssignment::getByState($oState);
             foreach ($aWorkflowStatePermissionAssignments as $oAssignment) {
                 $iPermissionId = $oAssignment->getPermissionId();
                 $iPermissionDescriptorId = $oAssignment->getDescriptorId();
                 $oPD = KTPermissionDescriptor::get($iPermissionDescriptorId);
                 $aGroupIDs = $oPD->getGroups();
                 $aUserIDs = array();
                 $aRoleIDs = $oPD->getRoles();
                 $aAllowed = array('group' => $aGroupIDs, 'user' => $aUserIDs, 'role' => $aRoleIDs);
                 $aMapPermAllowed[$iPermissionId] = $aAllowed;
             }
         }
     }
     // if we have roles:  nearest folder.
     $iRoleSourceFolder = null;
     if ($is_a_document) {
         $iRoleSourceFolder = $oFolderOrDocument->getFolderID();
     } else {
         $iRoleSourceFolder = $oFolderOrDocument->getId();
     }
     // very minor perf win:  map role_id (in context) to PD.
     $_roleCache = array();
     foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
         $aAfterRoles = array();
         if (array_key_exists('role', $aAllowed)) {
             foreach ($aAllowed['role'] as $k => $iRoleId) {
                 // store the PD <-> RoleId map
                 // special-case "all" or "authenticated".
                 if ($iRoleId == -3 || $iRoleId == -4) {
                     $aAfterRoles[] = $iRoleId;
                     continue;
                 }
                 if (!array_key_exists($iRoleId, $_roleCache)) {
                     $oRoleAllocation = null;
                     if ($is_a_document) {
                         $oRoleAllocation =& DocumentRoleAllocation::getAllocationsForDocumentAndRole($oFolderOrDocument->getId(), $iRoleId);
                         if (PEAR::isError($oRoleAllocation)) {
                             $oRoleAllocation = null;
                         }
                     }
                     // if that's null - not set _on_ the document, then
                     if (is_null($oRoleAllocation)) {
                         $oRoleAllocation =& RoleAllocation::getAllocationsForFolderAndRole($iRoleSourceFolder, $iRoleId);
                     }
                     $_roleCache[$iRoleId] = $oRoleAllocation;
                 }
                 // roles are _not_ always assigned (can be null at root)
                 if (!is_null($_roleCache[$iRoleId])) {
                     $aMapPermAllowed[$iPermissionId]['user'] = kt_array_merge($aMapPermAllowed[$iPermissionId]['user'], $_roleCache[$iRoleId]->getUserIds());
                     $aMapPermAllowed[$iPermissionId]['group'] = kt_array_merge($aMapPermAllowed[$iPermissionId]['group'], $_roleCache[$iRoleId]->getGroupIds());
                     // naturally, roles cannot be assigned roles, or madness follows.
                 }
                 unset($aAllowed['role'][$k]);
             }
         }
         unset($aMapPermAllowed[$iPermissionId]['role']);
         if (!empty($aAfterRoles)) {
             $aMapPermAllowed[$iPermissionId]['role'] = $aAfterRoles;
         }
     }
     /*
     print '<pre>';
     print '=======' . $oFolderOrDocument->getName();
     print '<br />';
     var_dump($aMapPermAllowed);
     print '</pre>';
     */
     //if (is_null($oPermLookup)) {
     $aMapPermDesc = array();
     foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
         $oLookupPD = KTPermissionUtil::getOrCreateDescriptor($aAllowed);
         $aMapPermDesc[$iPermissionId] = $oLookupPD->getID();
     }
     $oPermLookup = KTPermissionLookupAssignment::findOrCreateLookupByPermissionDescriptorMap($aMapPermDesc);
     //}
     $oFolderOrDocument->setPermissionLookupID($oPermLookup->getID());
     $oFolderOrDocument->update();
 }
コード例 #4
0
 function allowTransition($oDocument, $oUser)
 {
     if (!$this->isLoaded()) {
         return true;
     }
     $iRoleId = $this->aConfig['role_id'];
     $oRole = Role::get($this->aConfig['role_id']);
     if (PEAR::isError($oRole)) {
         return true;
         // fail safe for cases where the role is deleted.
     }
     $bHaveRole = true;
     if ($iRoleId) {
         $bHaveRole = false;
         // handle the magic roles
         if ($iRoleId == -3) {
             // everyone:  just accept
             $bHaveRole = true;
         } else {
             if ($iRoleId == -4 && !$oUser->isAnonymous()) {
                 // authenticated
                 $bHaveRole = true;
             } else {
                 $bHaveRole = true;
                 $oRoleAllocation = DocumentRoleAllocation::getAllocationsForDocumentAndRole($oDocument->getId(), $iRoleId);
                 if ($oRoleAllocation == null) {
                     // no role allocation on the doc - check the folder.
                     $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($oDocument->getParentID(), $iRoleId);
                 }
                 // if that's -also- null
                 if ($oRoleAllocation == null) {
                     // no role allocation, no fulfillment.
                     $bHaveRole = false;
                 } else {
                     if (!$oRoleAllocation->hasMember($oUser)) {
                         $bHaveRole = false;
                     }
                 }
             }
         }
     }
     return $bHaveRole;
 }
コード例 #5
0
 function informUsersForState($oState, $aInformed, $oDocument, $oUser, $sComments)
 {
     // say no to duplicates.
     KTWorkflowNotification::clearNotificationsForDocument($oDocument);
     $aUsers = array();
     $aGroups = array();
     $aRoles = array();
     foreach (KTUtil::arrayGet($aInformed, 'user', array()) as $iUserId) {
         $oU = User::get($iUserId);
         if (PEAR::isError($oU) || $oU == false) {
             continue;
         } else {
             $aUsers[$oU->getId()] = $oU;
         }
     }
     foreach (KTUtil::arrayGet($aInformed, 'group', array()) as $iGroupId) {
         $oG = Group::get($iGroupId);
         if (PEAR::isError($oG) || $oG == false) {
             continue;
         } else {
             $aGroups[$oG->getId()] = $oG;
         }
     }
     foreach (KTUtil::arrayGet($aInformed, 'role', array()) as $iRoleId) {
         $oR = Role::get($iRoleId);
         if (PEAR::isError($oR) || $oR == false) {
             continue;
         } else {
             $aRoles[] = $oR;
         }
     }
     // FIXME extract this into a util - I see us using this again and again.
     // start with roles ... roles _only_ ever contain groups.
     foreach ($aRoles as $oRole) {
         // do NOT alert anonymous or Everyone roles - that would be very scary.
         $iRoleId = KTUtil::getId($oRole);
         if ($iRoleId == -3 || $iRoleId == -4) {
             continue;
         }
         // first try on the document, then the folder above it.
         $oRoleAllocation = DocumentRoleAllocation::getAllocationsForDocumentAndRole($oDocument->getId(), $iRoleId);
         if (is_null($oRoleAllocation)) {
             // if we don't get a document role, try folder role.
             $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($oDocument->getFolderID(), $oRole->getId());
         }
         if (is_null($oRoleAllocation) || PEAR::isError($oRoleAllocation)) {
             continue;
         }
         $aRoleUsers = $oRoleAllocation->getUsers();
         $aRoleGroups = $oRoleAllocation->getGroups();
         foreach ($aRoleUsers as $id => $oU) {
             $aUsers[$id] = $oU;
         }
         foreach ($aRoleGroups as $id => $oGroup) {
             $aGroups[$id] = $oGroup;
         }
     }
     // we now have a (potentially overlapping) set of groups, which may
     // have subgroups.
     //
     // what we need to do _now_ is build a canonical set of groups, and then
     // generate the singular user-base.
     $aGroupMembershipSet = GroupUtil::buildGroupArray();
     $aAllIds = array_keys($aGroups);
     foreach ($aGroups as $id => $oGroup) {
         $aAllIds = kt_array_merge($aGroupMembershipSet[$id], $aAllIds);
     }
     foreach ($aAllIds as $id) {
         if (!array_key_exists($id, $aGroups)) {
             $aGroups[$id] = Group::get($id);
         }
     }
     // now, merge this (again) into the user-set.
     foreach ($aGroups as $oGroup) {
         $aNewUsers = $oGroup->getMembers();
         foreach ($aNewUsers as $oU) {
             $id = $oU->getId();
             if (!array_key_exists($id, $aUsers)) {
                 $aUsers[$id] = $oU;
             }
         }
     }
     // and done.
     foreach ($aUsers as $oU) {
         if (!PEAR::isError($oU)) {
             KTWorkflowNotification::newNotificationForDocument($oDocument, $oU, $oState, $oUser, $sComments);
         }
     }
 }
コード例 #6
0
ファイル: KTAPIAcl.inc.php プロジェクト: 5haman/knowledgetree
 /**
  * Save's the role allocation
  *
  * @author KnowledgeTree Team
  * @access public
  */
 public function save()
 {
     if (!$this->changed) {
         // we don't have to do anything if nothing has changed.
         return;
     }
     $map =& $this->map;
     $folderId = $this->folderItem->getObject()->getId();
     foreach ($map['role']['role'] as $roleId => $roleName) {
         $roleAllocation = RoleAllocation::getAllocationsForFolderAndRole($folderId, $roleId);
         $allowed = array();
         $userIds = array();
         $groupIds = array();
         if (array_key_exists($roleId, $map['role']['userAllocation'])) {
             foreach ($map['role']['userAllocation'][$roleId] as $userId) {
                 $userIds[] = $userId;
             }
         }
         if (array_key_exists($roleId, $map['role']['groupAllocation'])) {
             foreach ($map['role']['groupAllocation'][$roleId] as $groupId) {
                 $groupIds[] = $groupId;
             }
         }
         $allowed['user'] = $userIds;
         $allowed['group'] = $groupIds;
         if (is_null($roleAllocation)) {
             $roleAllocation = $this->overrideRoleAllocation(KTAPI_Role::getById($roleId));
         }
         $roleAllocation->setAllowed($allowed);
         $roleAllocation->update();
     }
 }
コード例 #7
0
 function getAllowed()
 {
     if (!is_null($this->iPermissionDescriptorId)) {
         $oDescriptor = KTPermissionDescriptor::get($this->iPermissionDescriptorId);
         // fully done, etc.
         $aAllowed = $oDescriptor->getAllowed();
     } else {
         $aAllowed = array();
     }
     // special case "document owner".
     if ($this->iRoleId == -2) {
         $oDoc = KTDocumentCore::get($this->iDocumentId);
         /* ! NBM Please Review
          *
          * This should never be an error - we were called by PermissionUtil 
          * to get the details for a document, but it _is_ be a DocumentCore
          * object during _add.
          *
          * When we try to grab the Document, it blows up on the MetadataVersion,
          * so we have to use a DocumentCore to avoid a fail-out on the initial 
          * on-add permission check.
          *
          * Is this bad/evil/not appropriate in some way?  I can't see a major
          * issue with it...
          *
          */
         if (PEAR::isError($oDoc)) {
             return $aAllowed;
         }
         // ! NBM Please review
         // we cascade "owner" from the folder (if, for some _bizarre_ reason the
         // owner role is allocated to users/groups/etc.  this can be disabled
         // with the CRACK_IS_BAD flag, or removed entirely.  I am undecided.
         //
         // There is some argument to be made for the consistency, but it may not be
         // that big.  I think it _may_ lead to easily misconfigured setups, but I
         // really don't know.
         $CRACK_IS_BAD = false;
         if (!$CRACK_IS_BAD && is_null($this->iPermissionDescriptorId)) {
             $oDerivedAlloc = RoleAllocation::getAllocationsForFolderAndRole($oDoc->getFolderID(), $this->iRoleId);
             if (!(PEAR::isError($oDerivedAlloc) || is_null($oDerivedAlloc))) {
                 $aAllowed = $oDerivedAlloc->getAllowed();
             }
         }
         $owner_id = $oDoc->getOwnerId();
         if (is_null($aAllowed['user'])) {
             $aAllowed['user'] = array($owner_id);
         } else {
             if (array_search($owner_id, $aAllowed['user']) === false) {
                 $aAllowed['user'][] = $owner_id;
             }
         }
     }
     return $aAllowed;
 }
コード例 #8
0
ファイル: KTAssist.php プロジェクト: 5haman/knowledgetree
 function do_assistance()
 {
     $sSubject = $this->oValidator->validateString($_REQUEST['subject']);
     $sDetails = $this->oValidator->validateString($_REQUEST['details']);
     $aUsers = array();
     $aGroups = array();
     $aRoles = array();
     foreach (Group::getAdministratorGroups() as $oGroup) {
         $aGroups[$oGroup->getId()] =& $oGroup;
     }
     foreach (Unit::getUnitsForFolder($this->oDocument->getFolderId()) as $oUnit) {
         foreach (Group::getUnitAdministratorGroupsByUnit($oUnit) as $oGroup) {
             $aGroups[$oGroup->getId()] =& $oGroup;
         }
     }
     $aRoles[-2] = Role::get(-2);
     $oDocument =& $this->oDocument;
     foreach ($aRoles as $oRole) {
         // Ignore anonymous or Everyone roles
         $iRoleId = KTUtil::getId($oRole);
         if ($iRoleId == -3 || $iRoleId == -4) {
             continue;
         }
         // first try on the document, then the folder above it.
         $oRoleAllocation = DocumentRoleAllocation::getAllocationsForDocumentAndRole($oDocument->getId(), $iRoleId);
         if (is_null($oRoleAllocation)) {
             // if we don't get a document role, try folder role.
             $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($oDocument->getFolderID(), $oRole->getId());
         }
         if (is_null($oRoleAllocation) || PEAR::isError($oRoleAllocation)) {
             continue;
         }
         $aRoleUsers = $oRoleAllocation->getUsers();
         $aRoleGroups = $oRoleAllocation->getGroups();
         foreach ($aRoleUsers as $id => $oU) {
             $aUsers[$id] = $oU;
         }
         foreach ($aRoleGroups as $id => $oGroup) {
             $aGroups[$id] = $oGroup;
         }
     }
     $aGroupMembershipSet = GroupUtil::buildGroupArray();
     $aAllIds = array_keys($aGroups);
     foreach ($aGroups as $id => $oGroup) {
         $aAllIds = kt_array_merge($aGroupMembershipSet[$id], $aAllIds);
     }
     foreach ($aAllIds as $id) {
         if (!array_key_exists($id, $aGroups)) {
             $aGroups[$id] = Group::get($id);
         }
     }
     // now, merge this (again) into the user-set.
     foreach ($aGroups as $oGroup) {
         $aNewUsers = $oGroup->getMembers();
         foreach ($aNewUsers as $oU) {
             $id = $oU->getId();
             if (!array_key_exists($id, $aUsers)) {
                 $aUsers[$id] = $oU;
             }
         }
     }
     foreach ($aUsers as $oU) {
         if (!PEAR::isError($oU)) {
             KTAssistNotification::newNotificationForDocument($this->oDocument, $oU, $this->oUser, $sSubject, $sDetails);
         }
     }
     $this->commitTransaction();
     $params = 'fDocumentId=' . $oDocument->getId();
     $url = generateControllerLink('viewDocument', $params);
     exit(redirect($url));
 }
コード例 #9
0
 function do_main()
 {
     $this->oPage->setTitle(_kt("View Roles"));
     $this->oPage->setBreadcrumbDetails(_kt("View Roles"));
     $oTemplating = new KTTemplating();
     $oTemplate = $oTemplating->loadTemplate("ktcore/action/view_roles");
     // we need to have:
     //   - a list of roles
     //   - with their users / groups
     //   - and that allocation id
     $aRoles = array();
     // stores data for display.
     $aRoleList = Role::getList();
     foreach ($aRoleList as $oRole) {
         $iRoleId = $oRole->getId();
         $aRoles[$iRoleId] = array("name" => $oRole->getName());
         $oRoleAllocation = DocumentRoleAllocation::getAllocationsForDocumentAndRole($this->oDocument->getId(), $iRoleId);
         if (is_null($oRoleAllocation)) {
             $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($this->oDocument->getFolderID(), $iRoleId);
         }
         $u = array();
         $g = array();
         $aid = null;
         $raid = null;
         if (is_null($oRoleAllocation)) {
             // nothing.
         } else {
             //var_dump($oRoleAllocation);
             $raid = $oRoleAllocation->getId();
             // real_alloc_id
             $aAllowed = $oRoleAllocation->getAllowed();
             if (!empty($aAllowed['user'])) {
                 $u = $aAllowed['user'];
             }
             if (!empty($aAllowed['group'])) {
                 $g = $aAllowed['group'];
             }
         }
         $aRoles[$iRoleId]['users'] = $u;
         $aRoles[$iRoleId]['groups'] = $g;
         $aRoles[$iRoleId]['real_allocation_id'] = $raid;
     }
     // final step.
     // map to users, groups.
     foreach ($aRoles as $key => $role) {
         $_users = array();
         foreach ($aRoles[$key]['users'] as $iUserId) {
             $oUser = User::get($iUserId);
             if (!(PEAR::isError($oUser) || $oUser == false)) {
                 $_users[] = $oUser->getName();
             }
         }
         if (empty($_users)) {
             $aRoles[$key]['users'] = '<span class="descriptiveText"> ' . _kt('no users') . '</span>';
         } else {
             $aRoles[$key]['users'] = implode(', ', $_users);
         }
         $_groups = array();
         foreach ($aRoles[$key]['groups'] as $iGroupId) {
             $oGroup = Group::get($iGroupId);
             if (!(PEAR::isError($oGroup) || $oGroup == false)) {
                 $_groups[] = $oGroup->getName();
             }
         }
         if (empty($_groups)) {
             $aRoles[$key]['groups'] = '<span class="descriptiveText"> ' . _kt('no groups') . '</span>';
         } else {
             $aRoles[$key]['groups'] = implode(', ', $_groups);
         }
     }
     $aTemplateData = array('context' => &$this, 'roles' => $aRoles);
     return $oTemplate->render($aTemplateData);
 }