mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-03 08:04:17 +01:00
N°5324 - repair profiles by default or if configured for customer with multiple profiles + move dedicated test in UserProfilesEventListenerTest.php
This commit is contained in:
@@ -24,11 +24,20 @@ define('POWER_USER_PORTAL_PROFILE_NAME', 'Portal power user');
|
||||
*/
|
||||
class UserProfilesEventListener implements iEventServiceSetup
|
||||
{
|
||||
private $oUserPortalProfile;
|
||||
private $bIsRepairmentEnabled = false;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function RegisterEventsAndListeners()
|
||||
{
|
||||
$this->Init();
|
||||
|
||||
if (false === $this->bIsRepairmentEnabled){
|
||||
return;
|
||||
}
|
||||
|
||||
$callback = [$this, 'OnUserProfileLinkChange'];
|
||||
$aEventSource = [\User::class, \UserExternal::class, \UserInternal::class];
|
||||
|
||||
@@ -45,23 +54,82 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
);
|
||||
}
|
||||
|
||||
public function IsRepairmentEnabled() : bool
|
||||
{
|
||||
return $this->bIsRepairmentEnabled;
|
||||
}
|
||||
|
||||
public function OnUserProfileLinkChange(EventData $oEventData): void {
|
||||
/** @var \User $oObject */
|
||||
$oUser = $oEventData->Get('object');
|
||||
|
||||
try {
|
||||
self::RepairProfiles($oUser);
|
||||
} catch (Exception $oException) {
|
||||
IssueLog::Error('Exception occurred on OnUserProfileLinkChange', LogChannels::DM_CRUD, [
|
||||
$this->RepairProfiles($oUser);
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('Exception occurred on RepairProfiles', LogChannels::DM_CRUD, [
|
||||
'user_class' => get_class($oUser),
|
||||
'user_id' => $oUser->GetKey(),
|
||||
'exception_message' => $oException->getMessage(),
|
||||
'exception_stacktrace' => $oException->getTraceAsString(),
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function RepairProfiles(\User $oUser) : void
|
||||
/**
|
||||
* @param $aPortalDispatcherData: passed only for testing purpose
|
||||
*
|
||||
* @return void
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function Init($aPortalDispatcherData=null) : void {
|
||||
if (is_null($aPortalDispatcherData)){
|
||||
$aPortalDispatcherData = \PortalDispatcherData::GetData();
|
||||
}
|
||||
|
||||
$sRepairmentProfile = \utils::GetConfig()->GetModuleSetting('itop-profiles-itil', 'poweruserportal-repair-profile', null);
|
||||
|
||||
if (is_null($sRepairmentProfile) && sizeof($aPortalDispatcherData) > 2){
|
||||
//when there are further portals we dont want to force a specific portal by repairing the associated profiles to a user
|
||||
$this->bIsRepairmentEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null($sRepairmentProfile)){
|
||||
$sRepairmentProfile = PORTAL_PROFILE_NAME;
|
||||
}
|
||||
|
||||
try {
|
||||
$sOQL = sprintf("SELECT URP_Profiles WHERE name = '%s'", $sRepairmentProfile);
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new \DBObjectSet($oSearch);
|
||||
if ($oSet->Count() !== 1) {
|
||||
//user portal profile does not exist
|
||||
//current iTop is customized enough to disable repairment
|
||||
$this->bIsRepairmentEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->oUserPortalProfile = $oSet->Fetch();
|
||||
if (is_null($this->oUserPortalProfile)){
|
||||
//may be not required. preventive code to disable repairment
|
||||
$this->bIsRepairmentEnabled = false;
|
||||
return;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
IssueLog::Error('Exception when searching user portal profile', LogChannels::DM_CRUD, [
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
]);
|
||||
$this->bIsRepairmentEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->bIsRepairmentEnabled = true;
|
||||
}
|
||||
|
||||
public function RepairProfiles(\User $oUser) : void
|
||||
{
|
||||
if (!is_null($oUser))
|
||||
{
|
||||
@@ -72,17 +140,8 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
if (POWER_USER_PORTAL_PROFILE_NAME === $oProfile->Get('profile')){
|
||||
//add portal user
|
||||
// power portal user is not a standalone profile (it will break console UI)
|
||||
$sOQL = sprintf("SELECT URP_Profiles WHERE name = '%s'", PORTAL_PROFILE_NAME);
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new \DBObjectSet($oSearch);
|
||||
if ($oSet->Count() !==1){
|
||||
return;
|
||||
}
|
||||
|
||||
$oUserPortalProfile = $oSet->Fetch();
|
||||
$oUserProfile = new \URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $oUserPortalProfile->GetKey());
|
||||
$oUserProfile->Set('profileid', $this->oUserPortalProfile->GetKey());
|
||||
$oCurrentUserProfileSet->AddItem($oUserProfile);
|
||||
$oUser->Set('profile_list', $oCurrentUserProfileSet);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenuFactory;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use CoreCannotSaveObjectException;
|
||||
use CoreException;
|
||||
@@ -553,328 +552,4 @@ class UserRightsTest extends ItopDataTestCase
|
||||
['Person', 'team_list', false],
|
||||
];
|
||||
}
|
||||
|
||||
public function PortaPowerUserProvider(){
|
||||
return [
|
||||
'Portal power user only => user should be repaired by adding User portal profile' => [
|
||||
'aAssociatedProfilesBeforeUserCreation' => [
|
||||
'Portal power user'
|
||||
],
|
||||
'aExpectedAssociatedProfilesAfterUserCreation'=> [
|
||||
'Portal power user',
|
||||
'Portal user',
|
||||
]
|
||||
],
|
||||
'Portal power user + Support Agent => profiles untouched' => [
|
||||
'aAssociatedProfilesBeforeUserCreation' => [
|
||||
'Portal power user',
|
||||
'Support Agent',
|
||||
],
|
||||
'aExpectedAssociatedProfilesAfterUserCreation'=> [
|
||||
'Portal power user',
|
||||
'Support Agent',
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLocalCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLocal();
|
||||
$sLogin = 'testUserLocalCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$oUser->Set('password', 'ABCD1234@gabuzomeu');
|
||||
$oUser->Set('language', 'EN US');
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLocalUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLocal();
|
||||
$sLogin = 'testUserLocalUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$oUser->Set('password', 'ABCD1234@gabuzomeu');
|
||||
$oUser->Set('language', 'EN US');
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLDAPCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLDAP();
|
||||
$sLogin = 'testUserLDAPCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLDAPUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLDAP();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserExternalCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserExternalUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function CreateUserForProfileTesting(\User $oUserToCreate, array $aAssociatedProfilesBeforeUserCreation) : array
|
||||
{
|
||||
$aProfiles = [];
|
||||
$oSearch = \DBSearch::FromOQL("SELECT URP_Profiles");
|
||||
$oProfileSet = new DBObjectSet($oSearch);
|
||||
while (($oProfile = $oProfileSet->Fetch()) != null){
|
||||
$aProfiles[$oProfile->Get('name')] = $oProfile;
|
||||
}
|
||||
|
||||
$this->CreateTestOrganization();
|
||||
$oContact = $this->CreatePerson("1");
|
||||
$iContactid = $oContact->GetKey();
|
||||
|
||||
$oUserToCreate->Set('contactid', $iContactid);
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
|
||||
$oUserProfileList = $oUserToCreate->Get('profile_list');
|
||||
foreach ($aAssociatedProfilesBeforeUserCreation as $sProfileName){
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oUserProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oUserProfile->Set('reason', 'UNIT Tests');
|
||||
$oUserProfileList->AddItem($oUserProfile);
|
||||
}
|
||||
|
||||
$oUserToCreate->Set('profile_list', $oUserProfileList);
|
||||
$sId = $oUserToCreate->DBInsert();
|
||||
|
||||
return [ $sId, $aProfiles];
|
||||
}
|
||||
|
||||
public function commonUserCreation($oUserToCreate, $aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, $aAssociatedProfilesBeforeUserCreation);
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation){
|
||||
$oUser = \MetaModel::GetObject($sUserClass, $sId);
|
||||
$oUserProfileList = $oUser->Get('profile_list');
|
||||
$aProfilesAfterCreation=[];
|
||||
while (($oProfile = $oUserProfileList->Fetch()) != null){
|
||||
$aProfilesAfterCreation[] = $oProfile->Get('profile');
|
||||
}
|
||||
|
||||
foreach ($aExpectedAssociatedProfilesAfterUserCreation as $sExpectedProfileName){
|
||||
$this->assertTrue(in_array($sExpectedProfileName, $aProfilesAfterCreation),
|
||||
"profile \'$sExpectedProfileName\' should be asociated to user after creation. " . var_export($aProfilesAfterCreation, true) );
|
||||
}
|
||||
|
||||
$_SESSION = [];
|
||||
|
||||
//$this->expectException(\Exception::class);
|
||||
UserRights::Login($oUser->Get('login'));
|
||||
|
||||
if (! UserRights::IsPortalUser()) {
|
||||
//calling this API triggers Fatal Error on below OQL used by \User->GetContactObject() for a user with only 'portal power user' profile
|
||||
/**
|
||||
* Error: No result for the single row query: 'SELECT DISTINCT `Contact`.`id` AS `Contactid`, `Contact`.`name` AS `Contactname`, `Contact`.`status` AS `Contactstatus`, `Contact`.`org_id` AS `Contactorg_id`, `Organization_org_id`.`name` AS `Contactorg_name`, `Contact`.`email` AS `Contactemail`, `Contact`.`phone` AS `Contactphone`, `Contact`.`notify` AS `Contactnotify`, `Contact`.`function` AS `Contactfunction`, `Contact`.`finalclass` AS `Contactfinalclass`, IF((`Contact`.`finalclass` IN ('Team', 'Contact')), CAST(CONCAT(COALESCE(`Contact`.`name`, '')) AS CHAR), CAST(CONCAT(COALESCE(`Contact_poly_Person`.`first_name`, ''), COALESCE(' ', ''), COALESCE(`Contact`.`name`, '')) AS CHAR)) AS `Contactfriendlyname`, COALESCE((`Contact`.`status` = 'inactive'), 0) AS `Contactobsolescence_flag`, `Contact`.`obsolescence_date` AS `Contactobsolescence_date`, CAST(CONCAT(COALESCE(`Organization_org_id`.`name`, '')) AS CHAR) AS `Contactorg_id_friendlyname`, COALESCE((`Organization_org_id`.`status` = 'inactive'), 0) AS `Contactorg_id_obsolescence_flag` FROM `contact` AS `Contact` INNER JOIN `organization` AS `Organization_org_id` ON `Contact`.`org_id` = `Organization_org_id`.`id` LEFT JOIN `person` AS `Contact_poly_Person` ON `Contact`.`id` = `Contact_poly_Person`.`id` WHERE ((`Contact`.`id` = 40) AND 0) '.
|
||||
*/
|
||||
NavigationMenuFactory::MakeStandard();
|
||||
}
|
||||
|
||||
$this->assertTrue(true, 'after fix N°5324 no exception raised');
|
||||
// logout
|
||||
$_SESSION = [];
|
||||
}
|
||||
|
||||
public function commonUserUpdate($oUserToCreate, $aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, ["Administrator"]);
|
||||
|
||||
$oUserToUpdate = \MetaModel::GetObject($sUserClass, $sId);
|
||||
$oProfileList = $oUserToUpdate->Get('profile_list');
|
||||
while($oObj = $oProfileList->Fetch()){
|
||||
$oProfileList->RemoveItem($oObj->GetKey());
|
||||
}
|
||||
|
||||
foreach ($aAssociatedProfilesBeforeUserCreation as $sProfileName){
|
||||
$oAdminUrpProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oAdminUrpProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oAdminUrpProfile->Set('reason', 'UNIT Tests');
|
||||
$oProfileList->AddItem($oAdminUrpProfile);
|
||||
}
|
||||
|
||||
$oUserToUpdate->Set('profile_list', $oProfileList);
|
||||
$oUserToUpdate->DBWrite();
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function testUpdateUserExternalProfilesViaLinks(){
|
||||
$aInitialProfiles = [ "Administrator", "Portal power user"];
|
||||
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
|
||||
$sUserClass = get_class($oUser);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
|
||||
|
||||
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
|
||||
$aProfilesToRemove = ["Administrator"];
|
||||
foreach ($aProfilesToRemove as $sProfileName){
|
||||
if (array_key_exists($sProfileName, $aURPUserProfileByUser)){
|
||||
$oURPUserProfile = $aURPUserProfileByUser[$sProfileName];
|
||||
$oURPUserProfile->DBDelete();
|
||||
}
|
||||
}
|
||||
|
||||
$aExpectedProfilesAfterUpdate = ["Portal power user", "Portal user"];
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedProfilesAfterUpdate);
|
||||
}
|
||||
|
||||
public function BulkUpdateUserExternalProfilesViaLinksProvider(){
|
||||
return [
|
||||
'user profiles REPAIR 1' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'-Administrator',
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'user profiles REPAIR 2' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
'-Administrator',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'user profiles REPAIR 3' => [
|
||||
"aInitialProfiles" => [ "Administrator", "Portal power user"],
|
||||
"aOperation" => [
|
||||
'-Administrator',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'NOTHING DONE with 1 profile' => [
|
||||
"aInitialProfiles" => [ "Administrator", "Portal power user"],
|
||||
"aOperation" => [
|
||||
'-Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Administrator"],
|
||||
],
|
||||
'NOTHING DONE with 2 profiles including power...' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Administrator", "Portal power user"],
|
||||
],
|
||||
'NOTHING DONE with 2 profiles including power again ...' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal user", "Portal power user"],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider BulkUpdateUserExternalProfilesViaLinksProvider
|
||||
*/
|
||||
public function testBulkUpdateUserExternalProfilesViaLinks($aInitialProfiles, $aOperation, $aExpectedProfilesAfterUpdate){
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
|
||||
$sUserClass = get_class($oUser);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
|
||||
|
||||
\cmdbAbstractObject::SetEventDBLinksChangedBlocked(true);
|
||||
|
||||
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
|
||||
foreach ($aOperation as $sOperation){
|
||||
$sOp = substr($sOperation,0, 1);
|
||||
$sProfileName = substr($sOperation,1);
|
||||
|
||||
if ($sOp === "-"){
|
||||
if (array_key_exists($sProfileName, $aURPUserProfileByUser)){
|
||||
$oURPUserProfile = $aURPUserProfileByUser[$sProfileName];
|
||||
$oURPUserProfile->DBDelete();
|
||||
}
|
||||
} else {
|
||||
$oAdminUrpProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oAdminUrpProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oAdminUrpProfile->Set('userid', $sId);
|
||||
$oAdminUrpProfile->DBInsert();
|
||||
}
|
||||
}
|
||||
|
||||
\cmdbAbstractObject::SetEventDBLinksChangedBlocked(false);
|
||||
\cmdbAbstractObject::FireEventDbLinksChangedForAllObjects();
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedProfilesAfterUpdate);
|
||||
}
|
||||
|
||||
private function GetURPUserProfileByUser($iUserId) : array {
|
||||
$aRes = [];
|
||||
$oSearch = \DBSearch::FromOQL("SELECT URP_UserProfile WHERE userid=$iUserId");
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
while (($oURPUserProfile = $oSet->Fetch()) != null){
|
||||
$aRes[$oURPUserProfile->Get('profile')] = $oURPUserProfile;
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,448 @@
|
||||
<?php
|
||||
// Copyright (c) 2010-2023 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 25/01/2018
|
||||
* Time: 11:12
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Module\iTopProfilesItil;
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenuFactory;
|
||||
use Combodo\iTop\ItilProfiles\UserProfilesEventListener;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSet;
|
||||
use URP_UserProfile;
|
||||
use UserRights;
|
||||
|
||||
/**
|
||||
* @group itopRequestMgmt
|
||||
* @group userRights
|
||||
* @group defaultProfiles
|
||||
*
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class UserProfilesEventListenerTest extends ItopDataTestCase
|
||||
{
|
||||
public function PortaPowerUserProvider(){
|
||||
return [
|
||||
'Portal power user only => user should be repaired by adding User portal profile' => [
|
||||
'aAssociatedProfilesBeforeUserCreation' => [
|
||||
'Portal power user'
|
||||
],
|
||||
'aExpectedAssociatedProfilesAfterUserCreation'=> [
|
||||
'Portal power user',
|
||||
'Portal user',
|
||||
]
|
||||
],
|
||||
'Portal power user + Support Agent => profiles untouched' => [
|
||||
'aAssociatedProfilesBeforeUserCreation' => [
|
||||
'Portal power user',
|
||||
'Support Agent',
|
||||
],
|
||||
'aExpectedAssociatedProfilesAfterUserCreation'=> [
|
||||
'Portal power user',
|
||||
'Support Agent',
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLocalCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLocal();
|
||||
$sLogin = 'testUserLocalCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$oUser->Set('password', 'ABCD1234@gabuzomeu');
|
||||
$oUser->Set('language', 'EN US');
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLocalUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLocal();
|
||||
$sLogin = 'testUserLocalUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$oUser->Set('password', 'ABCD1234@gabuzomeu');
|
||||
$oUser->Set('language', 'EN US');
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLDAPCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLDAP();
|
||||
$sLogin = 'testUserLDAPCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserLDAPUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserLDAP();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserExternalCreation($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5324
|
||||
* @dataProvider PortaPowerUserProvider
|
||||
*/
|
||||
public function testUserExternalUpdate($aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$this->commonUserUpdate($oUser, $aAssociatedProfilesBeforeUserCreation, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function CreateUserForProfileTesting(\User $oUserToCreate, array $aAssociatedProfilesBeforeUserCreation, $bDbInsert=true) : array
|
||||
{
|
||||
$aProfiles = [];
|
||||
$oSearch = \DBSearch::FromOQL("SELECT URP_Profiles");
|
||||
$oProfileSet = new DBObjectSet($oSearch);
|
||||
while (($oProfile = $oProfileSet->Fetch()) != null){
|
||||
$aProfiles[$oProfile->Get('name')] = $oProfile;
|
||||
}
|
||||
|
||||
$this->CreateTestOrganization();
|
||||
$oContact = $this->CreatePerson("1");
|
||||
$iContactid = $oContact->GetKey();
|
||||
|
||||
$oUserToCreate->Set('contactid', $iContactid);
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
|
||||
$oUserProfileList = $oUserToCreate->Get('profile_list');
|
||||
foreach ($aAssociatedProfilesBeforeUserCreation as $sProfileName){
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oUserProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oUserProfile->Set('reason', 'UNIT Tests');
|
||||
$oUserProfileList->AddItem($oUserProfile);
|
||||
}
|
||||
|
||||
$oUserToCreate->Set('profile_list', $oUserProfileList);
|
||||
if ($bDbInsert){
|
||||
$sId = $oUserToCreate->DBInsert();
|
||||
} else {
|
||||
$sId = -1;
|
||||
}
|
||||
|
||||
return [ $sId, $aProfiles];
|
||||
}
|
||||
|
||||
public function commonUserCreation($oUserToCreate, $aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, $aAssociatedProfilesBeforeUserCreation);
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation){
|
||||
$oUser = \MetaModel::GetObject($sUserClass, $sId);
|
||||
$oUserProfileList = $oUser->Get('profile_list');
|
||||
$aProfilesAfterCreation=[];
|
||||
while (($oProfile = $oUserProfileList->Fetch()) != null){
|
||||
$aProfilesAfterCreation[] = $oProfile->Get('profile');
|
||||
}
|
||||
|
||||
foreach ($aExpectedAssociatedProfilesAfterUserCreation as $sExpectedProfileName){
|
||||
$this->assertTrue(in_array($sExpectedProfileName, $aProfilesAfterCreation),
|
||||
"profile \'$sExpectedProfileName\' should be asociated to user after creation. " . var_export($aProfilesAfterCreation, true) );
|
||||
}
|
||||
|
||||
$_SESSION = [];
|
||||
|
||||
//$this->expectException(\Exception::class);
|
||||
UserRights::Login($oUser->Get('login'));
|
||||
|
||||
if (! UserRights::IsPortalUser()) {
|
||||
//calling this API triggers Fatal Error on below OQL used by \User->GetContactObject() for a user with only 'portal power user' profile
|
||||
/**
|
||||
* Error: No result for the single row query: 'SELECT DISTINCT `Contact`.`id` AS `Contactid`, `Contact`.`name` AS `Contactname`, `Contact`.`status` AS `Contactstatus`, `Contact`.`org_id` AS `Contactorg_id`, `Organization_org_id`.`name` AS `Contactorg_name`, `Contact`.`email` AS `Contactemail`, `Contact`.`phone` AS `Contactphone`, `Contact`.`notify` AS `Contactnotify`, `Contact`.`function` AS `Contactfunction`, `Contact`.`finalclass` AS `Contactfinalclass`, IF((`Contact`.`finalclass` IN ('Team', 'Contact')), CAST(CONCAT(COALESCE(`Contact`.`name`, '')) AS CHAR), CAST(CONCAT(COALESCE(`Contact_poly_Person`.`first_name`, ''), COALESCE(' ', ''), COALESCE(`Contact`.`name`, '')) AS CHAR)) AS `Contactfriendlyname`, COALESCE((`Contact`.`status` = 'inactive'), 0) AS `Contactobsolescence_flag`, `Contact`.`obsolescence_date` AS `Contactobsolescence_date`, CAST(CONCAT(COALESCE(`Organization_org_id`.`name`, '')) AS CHAR) AS `Contactorg_id_friendlyname`, COALESCE((`Organization_org_id`.`status` = 'inactive'), 0) AS `Contactorg_id_obsolescence_flag` FROM `contact` AS `Contact` INNER JOIN `organization` AS `Organization_org_id` ON `Contact`.`org_id` = `Organization_org_id`.`id` LEFT JOIN `person` AS `Contact_poly_Person` ON `Contact`.`id` = `Contact_poly_Person`.`id` WHERE ((`Contact`.`id` = 40) AND 0) '.
|
||||
*/
|
||||
NavigationMenuFactory::MakeStandard();
|
||||
}
|
||||
|
||||
$this->assertTrue(true, 'after fix N°5324 no exception raised');
|
||||
// logout
|
||||
$_SESSION = [];
|
||||
}
|
||||
|
||||
public function commonUserUpdate($oUserToCreate, $aAssociatedProfilesBeforeUserCreation,
|
||||
$aExpectedAssociatedProfilesAfterUserCreation)
|
||||
{
|
||||
$sUserClass = get_class($oUserToCreate);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, ["Administrator"]);
|
||||
|
||||
$oUserToUpdate = \MetaModel::GetObject($sUserClass, $sId);
|
||||
$oProfileList = $oUserToUpdate->Get('profile_list');
|
||||
while($oObj = $oProfileList->Fetch()){
|
||||
$oProfileList->RemoveItem($oObj->GetKey());
|
||||
}
|
||||
|
||||
foreach ($aAssociatedProfilesBeforeUserCreation as $sProfileName){
|
||||
$oAdminUrpProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oAdminUrpProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oAdminUrpProfile->Set('reason', 'UNIT Tests');
|
||||
$oProfileList->AddItem($oAdminUrpProfile);
|
||||
}
|
||||
|
||||
$oUserToUpdate->Set('profile_list', $oProfileList);
|
||||
$oUserToUpdate->DBWrite();
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation);
|
||||
}
|
||||
|
||||
public function testUpdateUserExternalProfilesViaLinks(){
|
||||
$aInitialProfiles = [ "Administrator", "Portal power user"];
|
||||
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
|
||||
$sUserClass = get_class($oUser);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
|
||||
|
||||
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
|
||||
$sProfileNameToRemove = "Administrator";
|
||||
if (array_key_exists($sProfileNameToRemove, $aURPUserProfileByUser)){
|
||||
$oURPUserProfile = $aURPUserProfileByUser[$sProfileNameToRemove];
|
||||
$oURPUserProfile->DBDelete();
|
||||
}
|
||||
|
||||
$aExpectedProfilesAfterUpdate = ["Portal power user", "Portal user"];
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedProfilesAfterUpdate);
|
||||
}
|
||||
|
||||
public function BulkUpdateUserExternalProfilesViaLinksProvider(){
|
||||
return [
|
||||
'user profiles REPAIR 1' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'-Administrator',
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'user profiles REPAIR 2' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
'-Administrator',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'user profiles REPAIR 3' => [
|
||||
"aInitialProfiles" => [ "Administrator", "Portal power user"],
|
||||
"aOperation" => [
|
||||
'-Administrator',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal power user", "Portal user"],
|
||||
],
|
||||
'NOTHING DONE with 1 profile' => [
|
||||
"aInitialProfiles" => [ "Administrator", "Portal power user"],
|
||||
"aOperation" => [
|
||||
'-Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Administrator"],
|
||||
],
|
||||
'NOTHING DONE with 2 profiles including power...' => [
|
||||
"aInitialProfiles" => [ "Administrator"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Administrator", "Portal power user"],
|
||||
],
|
||||
'NOTHING DONE with 2 profiles including power again ...' => [
|
||||
"aInitialProfiles" => [ "Portal user"],
|
||||
"aOperation" => [
|
||||
'+Portal power user',
|
||||
],
|
||||
"aExpectedProfilesAfterUpdate" => ["Portal user", "Portal power user"],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider BulkUpdateUserExternalProfilesViaLinksProvider
|
||||
*/
|
||||
public function testBulkUpdateUserExternalProfilesViaLinks($aInitialProfiles, $aOperation, $aExpectedProfilesAfterUpdate){
|
||||
$oUser = new \UserExternal();
|
||||
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
|
||||
$sUserClass = get_class($oUser);
|
||||
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
|
||||
|
||||
\cmdbAbstractObject::SetEventDBLinksChangedBlocked(true);
|
||||
|
||||
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
|
||||
foreach ($aOperation as $sOperation){
|
||||
$sOp = substr($sOperation,0, 1);
|
||||
$sProfileName = substr($sOperation,1);
|
||||
|
||||
if ($sOp === "-"){
|
||||
if (array_key_exists($sProfileName, $aURPUserProfileByUser)){
|
||||
$oURPUserProfile = $aURPUserProfileByUser[$sProfileName];
|
||||
$oURPUserProfile->DBDelete();
|
||||
}
|
||||
} else {
|
||||
$oAdminUrpProfile = new URP_UserProfile();
|
||||
$oProfile = $aProfiles[$sProfileName];
|
||||
$oAdminUrpProfile->Set('profileid', $oProfile->GetKey());
|
||||
$oAdminUrpProfile->Set('userid', $sId);
|
||||
$oAdminUrpProfile->DBInsert();
|
||||
}
|
||||
}
|
||||
|
||||
\cmdbAbstractObject::SetEventDBLinksChangedBlocked(false);
|
||||
\cmdbAbstractObject::FireEventDbLinksChangedForAllObjects();
|
||||
|
||||
$this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedProfilesAfterUpdate);
|
||||
}
|
||||
|
||||
private function GetURPUserProfileByUser($iUserId) : array {
|
||||
$aRes = [];
|
||||
$oSearch = \DBSearch::FromOQL("SELECT URP_UserProfile WHERE userid=$iUserId");
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
while (($oURPUserProfile = $oSet->Fetch()) != null){
|
||||
$aRes[$oURPUserProfile->Get('profile')] = $oURPUserProfile;
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
public function testUserProfilesEventListenerInit_nominal(){
|
||||
$oUserProfilesEventListener = new UserProfilesEventListener();
|
||||
$oUserProfilesEventListener->Init();
|
||||
|
||||
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
|
||||
}
|
||||
|
||||
public function testUserProfilesEventListenerInit_furtherportals_norepairmentconfigured(){
|
||||
$aPortalDispatcherData = [
|
||||
'itop-portal',
|
||||
'customer-portal',
|
||||
'backoffice'
|
||||
];
|
||||
|
||||
$oUserProfilesEventListener = new UserProfilesEventListener();
|
||||
$oUserProfilesEventListener->Init($aPortalDispatcherData);
|
||||
|
||||
$this->assertFalse($oUserProfilesEventListener->IsRepairmentEnabled());
|
||||
}
|
||||
|
||||
public function testUserProfilesEventListenerInit_furtherportals_repairmentconfigured(){
|
||||
$aPortalDispatcherData = [
|
||||
'itop-portal',
|
||||
'customer-portal',
|
||||
'backoffice'
|
||||
];
|
||||
|
||||
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', 'poweruserportal-repair-profile', 'Portal user');
|
||||
|
||||
$oUserProfilesEventListener = new UserProfilesEventListener();
|
||||
$oUserProfilesEventListener->Init($aPortalDispatcherData);
|
||||
|
||||
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
|
||||
}
|
||||
|
||||
public function testUserProfilesEventListenerInit_with_unknownprofile(){
|
||||
$aPortalDispatcherData = [
|
||||
'itop-portal',
|
||||
'customer-portal',
|
||||
'backoffice'
|
||||
];
|
||||
|
||||
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', 'poweruserportal-repair-profile', 'Dummy Profile');
|
||||
|
||||
$oUserProfilesEventListener = new UserProfilesEventListener();
|
||||
$oUserProfilesEventListener->Init($aPortalDispatcherData);
|
||||
|
||||
$this->assertFalse($oUserProfilesEventListener->IsRepairmentEnabled());
|
||||
}
|
||||
|
||||
public function testRepairProfiles_WithAnotherFallbackProfile()
|
||||
{
|
||||
$oUser = new \UserLocal();
|
||||
$sLogin = 'testUserLocalCreationWithPortalPowerUserProfile-'.uniqid();
|
||||
$oUser->Set('login', $sLogin);
|
||||
$oUser->Set('password', 'ABCD1234@gabuzomeu');
|
||||
$oUser->Set('language', 'EN US');
|
||||
|
||||
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', 'poweruserportal-repair-profile', 'Change Supervisor');
|
||||
$oUserProfilesEventListener = new UserProfilesEventListener();
|
||||
$oUserProfilesEventListener->Init();
|
||||
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
|
||||
|
||||
$this->CreateUserForProfileTesting($oUser, ['Portal power user'], false);
|
||||
$oUserProfilesEventListener->RepairProfiles($oUser);
|
||||
|
||||
$oUserProfileList = $oUser->Get('profile_list');
|
||||
$aProfilesAfterCreation=[];
|
||||
while (($oProfile = $oUserProfileList->Fetch()) != null){
|
||||
$aProfilesAfterCreation[] = $oProfile->Get('profile');
|
||||
}
|
||||
|
||||
$this->assertContains('Change Supervisor', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true));
|
||||
$this->assertContains('Portal power user', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user