N°6228 - CheckToWrite() propagation to target objects based on with_php_constraint property

This commit is contained in:
Pierre Goiffon
2023-11-14 12:02:45 +01:00
committed by Eric Espie
parent 9a59bc7890
commit ea845dc6eb
17 changed files with 703 additions and 465 deletions

View File

@@ -1,82 +1,16 @@
<?php
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class cmdbAbstractObjectTest extends ItopDataTestCase {
const USE_TRANSACTION = true;
const CREATE_TEST_ORG = true;
// Count the events by name
private static array $aEventCalls = [];
private static int $iEventCalls = 0;
protected function setUp(): void
{
static::$aEventCalls = [];
static::$iEventCalls = 0;
parent::setUp();
}
public static function IncrementCallCount(string $sEvent)
{
self::$aEventCalls[$sEvent] = (self::$aEventCalls[$sEvent] ?? 0) + 1;
self::$iEventCalls++;
}
public function testCheckLinkModifications() {
$aLinkModificationsStack = $this->GetObjectsAwaitingFireEventDbLinksChanged();
$this->assertSame([], $aLinkModificationsStack);
// retain events
cmdbAbstractObject::SetEventDBLinksChangedBlocked(true);
// Create the person
$oPerson = $this->CreatePerson(1);
$this->assertIsObject($oPerson);
// Create the team
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
// contact types
$oContactType1 = MetaModel::NewObject(ContactType::class, ['name' => 'test_'.rand(10000, 99999)]);
$oContactType1->DBInsert();
$oContactType2 = MetaModel::NewObject(ContactType::class, ['name' => 'test_'.rand(10000, 99999)]);
$oContactType2->DBInsert();
// Prepare the link for the insertion with the team
$aValues = [
'person_id' => $oPerson->GetKey(),
'role_id' => $oContactType1->GetKey(),
'team_id' => $oTeam->GetKey(),
];
$oLinkPersonToTeam1 = MetaModel::NewObject(lnkPersonToTeam::class, $aValues);
$oLinkPersonToTeam1->DBInsert();
$aLinkModificationsStack = $this->GetObjectsAwaitingFireEventDbLinksChanged();
self::assertCount(3, $aLinkModificationsStack);
$aExpectedLinkStack = [
'Team' => [$oTeam->GetKey() => 1],
'Person' => [$oPerson->GetKey() => 1],
'ContactType' => [$oContactType1->GetKey() => 1],
];
self::assertSame($aExpectedLinkStack, $aLinkModificationsStack);
$oLinkPersonToTeam1->Set('role_id', $oContactType2->GetKey());
$oLinkPersonToTeam1->DBWrite();
$aLinkModificationsStack = $this->GetObjectsAwaitingFireEventDbLinksChanged();
self::assertCount(3, $aLinkModificationsStack);
$aExpectedLinkStack = [
'Team' => [$oTeam->GetKey() => 2],
'Person' => [$oPerson->GetKey() => 2],
'ContactType' => [
$oContactType1->GetKey() => 2,
$oContactType2->GetKey() => 1,
],
];
self::assertSame($aExpectedLinkStack, $aLinkModificationsStack);
}
public function testProcessClassIdDeferredUpdate()
{
// Create the team
@@ -152,288 +86,4 @@ class cmdbAbstractObjectTest extends ItopDataTestCase {
{
$this->SetNonPublicStaticProperty(cmdbAbstractObject::class, 'aObjectsAwaitingEventDbLinksChanged', $aObjects);
}
/**
* Check that EVENT_DB_LINKS_CHANGED events are not sent to the current updated/created object (Team)
* the events are sent to the other side (Person)
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function testDBInsertTeam()
{
// Prepare the link set
$sLinkedClass = lnkPersonToTeam::class;
$aLinkedObjectsArray = [];
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
$oLinkSet = new ormLinkSet(Team::class, 'persons_list', $oSet);
// Create the 3 persons
for ($i = 0; $i < 3; $i++) {
$oPerson = $this->CreatePerson($i);
$this->assertIsObject($oPerson);
// Add the person to the link
$oLink = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson->GetKey()]);
$oLinkSet->AddItem($oLink);
}
$this->debug("\n-------------> Test Starts HERE\n");
$oEventReceiver = new LinksEventReceiver($this);
$oEventReceiver->RegisterCRUDListeners();
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'persons_list' => $oLinkSet, 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
$this->assertIsObject($oTeam);
// 3 links added to person + 1 for the Team
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
}
/**
* Check that EVENT_DB_LINKS_CHANGED events are sent to all the linked objects when creating a new lnk object
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function testAddLinkToTeam()
{
// Create a person
$oPerson = $this->CreatePerson(1);
$this->assertIsObject($oPerson);
// Create a Team
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
$this->assertIsObject($oTeam);
$this->debug("\n-------------> Test Starts HERE\n");
$oEventReceiver = new LinksEventReceiver($this);
$oEventReceiver->RegisterCRUDListeners();
// The link creation will signal both the Person an the Team
$oLink = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson->GetKey(), 'team_id' => $oTeam->GetKey()]);
$oLink->DBInsert();
// 2 events one for Person and One for Team
$this->assertEquals(2, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
}
/**
* Check that EVENT_DB_LINKS_CHANGED events are sent to all the linked objects when updating an existing lnk object
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function testUpdateLinkRole()
{
// Create a person
$oPerson = $this->CreatePerson(1);
$this->assertIsObject($oPerson);
// Create a Team
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
$this->assertIsObject($oTeam);
// Create the link
$oLink = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson->GetKey(), 'team_id' => $oTeam->GetKey()]);
$oLink->DBInsert();
$this->debug("\n-------------> Test Starts HERE\n");
$oEventReceiver = new LinksEventReceiver($this);
$oEventReceiver->RegisterCRUDListeners();
// The link update will signal both the Person, the Team and the ContactType
// Change the role
$oContactType = MetaModel::NewObject(ContactType::class, ['name' => 'test_'.$oLink->GetKey()]);
$oContactType->DBInsert();
$oLink->Set('role_id', $oContactType->GetKey());
$oLink->DBUpdate();
// 3 events one for Person, one for Team and one for ContactType
$this->assertEquals(3, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
}
/**
* Check that when a link changes from an object to another, then both objects are notified
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function testUpdateLinkPerson()
{
// Create 2 person
$oPerson1 = $this->CreatePerson(1);
$this->assertIsObject($oPerson1);
$oPerson2 = $this->CreatePerson(2);
$this->assertIsObject($oPerson2);
// Create a Team
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
$this->assertIsObject($oTeam);
// Create the link between Person1 and Team
$oLink = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson1->GetKey(), 'team_id' => $oTeam->GetKey()]);
$oLink->DBInsert();
$this->debug("\n-------------> Test Starts HERE\n");
$oEventReceiver = new LinksEventReceiver($this);
$oEventReceiver->RegisterCRUDListeners();
// The link update will signal both the Persons and the Team
// Change the person
$oLink->Set('person_id', $oPerson2->GetKey());
$oLink->DBUpdate();
// 3 events 2 for Person, one for Team
$this->assertEquals(3, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
}
/**
* Check that EVENT_DB_LINKS_CHANGED events are sent to all the linked objects when deleting an existing lnk object
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function testDeleteLink()
{
// Create a person
$oPerson = $this->CreatePerson(1);
$this->assertIsObject($oPerson);
// Create a Team
$oTeam = MetaModel::NewObject(Team::class, ['name' => 'TestTeam1', 'org_id' => $this->getTestOrgId()]);
$oTeam->DBInsert();
$this->assertIsObject($oTeam);
// Create the link
$oLink = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson->GetKey(), 'team_id' => $oTeam->GetKey()]);
$oLink->DBInsert();
$this->debug("\n-------------> Test Starts HERE\n");
$oEventReceiver = new LinksEventReceiver($this);
$oEventReceiver->RegisterCRUDListeners();
// The link delete will signal both the Person an the Team
$oLink->DBDelete();
// 3 events one for Person, one for Team
$this->assertEquals(2, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
}
/**
* Debug called by event receivers
*
* @param $sMsg
*
* @return void
*/
public static function DebugStatic($sMsg)
{
if (static::$DEBUG_UNIT_TEST) {
if (is_string($sMsg)) {
echo "$sMsg\n";
} else {
print_r($sMsg);
}
}
}
}
/**
* Count events received
* And allow callbacks on events
*/
class LinksEventReceiver
{
private $oTestCase;
private $aCallbacks = [];
public static $bIsObjectInCrudStack;
public function __construct(ItopDataTestCase $oTestCase)
{
$this->oTestCase = $oTestCase;
}
public function AddCallback(string $sEvent, string $sClass, string $sFct, int $iCount = 1): void
{
$this->aCallbacks[$sEvent][$sClass] = [
'callback' => [$this, $sFct],
'count' => $iCount,
];
}
public function CleanCallbacks()
{
$this->aCallbacks = [];
}
// Event callbacks
public function OnEvent(EventData $oData)
{
$sEvent = $oData->GetEvent();
$oObject = $oData->Get('object');
$sClass = get_class($oObject);
$iKey = $oObject->GetKey();
$this->Debug(__METHOD__.": received event '$sEvent' for $sClass::$iKey");
cmdbAbstractObjectTest::IncrementCallCount($sEvent);
if (isset($this->aCallbacks[$sEvent][$sClass])) {
$aCallBack = $this->aCallbacks[$sEvent][$sClass];
if ($aCallBack['count'] > 0) {
$this->aCallbacks[$sEvent][$sClass]['count']--;
call_user_func($this->aCallbacks[$sEvent][$sClass]['callback'], $oObject);
}
}
}
public function RegisterCRUDListeners(string $sEvent = null, $mEventSource = null)
{
$this->Debug('Registering Test event listeners');
if (is_null($sEvent)) {
$this->oTestCase->EventService_RegisterListener(EVENT_DB_LINKS_CHANGED, [$this, 'OnEvent']);
return;
}
$this->oTestCase->EventService_RegisterListener($sEvent, [$this, 'OnEvent'], $mEventSource);
}
private function Debug($msg)
{
cmdbAbstractObjectTest::DebugStatic($msg);
}
}

View File

@@ -82,6 +82,7 @@ class QueryTest extends ItopDataTestCase
}
$oQuery->DBInsert();
$this->assertFalse($oQuery->IsNew());
return $oQuery;
}

View File

@@ -208,4 +208,33 @@ PHP
$oFormFieldNoTouchedAtt = $oAttDef->MakeFormField($oPerson);
$this->assertTrue($oFormFieldNoTouchedAtt->IsValidationDisabled(), 'email wasn\'t modified, we must not validate the corresponding field');
}
/**
* @dataProvider WithConstraintParameterProvider
*
* @param string $sClass
* @param string $sAttCode
* @param bool $bConstraintExpected
* @param bool $bComputationExpected
*
* @return void
* @throws \Exception
*/
public function testWithConstraintAndComputationParameters(string $sClass, string $sAttCode, bool $bConstraintExpected, bool $bComputationExpected)
{
$oAttDef = \MetaModel::GetAttributeDef($sClass, $sAttCode);
$this->assertTrue(method_exists($oAttDef, 'GetHasConstraint'));
$this->assertEquals($bConstraintExpected, $oAttDef->GetHasConstraint());
$this->assertEquals($bComputationExpected, $oAttDef->GetHasComputation());
}
public function WithConstraintParameterProvider()
{
return [
['User', 'profile_list', true, false],
['User', 'allowed_org_list', true, false],
['Person', 'team_list', false, false],
['Ticket', 'functionalcis_list', false, true],
];
}
}

View File

@@ -7,7 +7,6 @@
namespace Combodo\iTop\Test\UnitTest\Core\CRUD;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use ContactType;
use CoreException;
@@ -21,6 +20,7 @@ use ormLinkSet;
use Person;
use Team;
use utils;
use const EVENT_DB_LINKS_CHANGED;
class CRUDEventTest extends ItopDataTestCase
{
@@ -339,8 +339,8 @@ class CRUDEventTest extends ItopDataTestCase
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_CHECK_TO_WRITE]);
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_BEFORE_WRITE]);
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_AFTER_WRITE]);
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
$this->assertEquals(20, self::$iEventCalls);
$this->assertArrayNotHasKey(EVENT_DB_LINKS_CHANGED, self::$aEventCalls, 'no relation with the with_php_compute attribute !');
$this->assertEquals(16, self::$iEventCalls);
}
/**
@@ -388,8 +388,8 @@ class CRUDEventTest extends ItopDataTestCase
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_CHECK_TO_WRITE]);
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_BEFORE_WRITE]);
$this->assertEquals(4, self::$aEventCalls[EVENT_DB_AFTER_WRITE]);
$this->assertEquals(3, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
$this->assertEquals(19, self::$iEventCalls);
$this->assertArrayNotHasKey(EVENT_DB_LINKS_CHANGED, self::$aEventCalls, 'no relation with the with_php_compute attribute !');
$this->assertEquals(16, self::$iEventCalls);
// Read the object explicitly from the DB to check that the role has been set
$oSet = new DBObjectSet(DBSearch::FromOQL('SELECT Team WHERE id=:id'), [], ['id' => $oTeam->GetKey()]);
@@ -495,7 +495,7 @@ class CRUDEventTest extends ItopDataTestCase
$oLnk = MetaModel::NewObject(lnkPersonToTeam::class, ['person_id' => $oPerson->GetKey(), 'team_id' => $oTeam->GetKey()]);
$oLnk->DBInsert();
$this->assertEquals(2, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
$this->assertArrayNotHasKey(EVENT_DB_LINKS_CHANGED, self::$aEventCalls, 'no relation with the with_php_compute attribute !');
}
public function testLinksDeleted()
@@ -517,7 +517,7 @@ class CRUDEventTest extends ItopDataTestCase
$oLnk->DBDelete();
$this->assertEquals(2, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]);
$this->assertArrayNotHasKey(EVENT_DB_LINKS_CHANGED, self::$aEventCalls, 'no relation with the with_php_compute attribute !');
}
// Tests with MockDBObject

View File

@@ -0,0 +1,359 @@
<?php
/**
* @copyright Copyright (C) 2010-2023 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* Created by PhpStorm.
* Date: 25/01/2018
* Time: 11:12
*/
namespace Combodo\iTop\Test\UnitTest\Core\DBObject;
use Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenuFactory;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreCannotSaveObjectException;
use DBObjectSet;
use DBSearch;
use DeleteException;
use MetaModel;
use URP_UserProfile;
use User;
use UserExternal;
use UserLocal;
use UserRights;
/**
* @group itopRequestMgmt
* @group userRights
* @group defaultProfiles
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
* @backupGlobals disabled
*/
class CheckToWritePropagationTest extends ItopDataTestCase
{
public function PortaPowerUserProvider()
{
return [
'No profile' => [
'aProfilesBeforeUserCreation' => [
],
'bWaitForException' => 'CoreCannotSaveObjectException',
],
'Portal power user' => [
'aProfilesBeforeUserCreation' => [
'Portal power user',
],
'bWaitForException' => 'CoreCannotSaveObjectException',
],
'Portal power user + Configuration Manager' => [
'aProfilesBeforeUserCreation' => [
'Portal power user',
'Configuration Manager',
],
'bWaitForException' => false,
],
'Portal power user + Configuration Manager + Admin' => [
'aProfilesBeforeUserCreation' => [
'Portal power user',
'Configuration Manager',
'Administrator',
],
'bWaitForException' => false,
],
];
}
/**
* @dataProvider PortaPowerUserProvider
* @covers User::CheckPortalProfiles
*/
public function testUserLocalCreation($aProfilesBeforeUserCreation, $sWaitForException)
{
$oUser = new UserLocal();
$sLogin = 'testUserLocalCreationWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin);
$oUser->Set('password', 'ABCD1234@gabuzomeu');
$oUser->Set('language', 'EN US');
if (false !== $sWaitForException) {
$this->expectException($sWaitForException);
}
$this->commonUserCreationTest($oUser, $aProfilesBeforeUserCreation);
}
/**
* @dataProvider PortaPowerUserProvider
* @covers User::CheckPortalProfiles
*/
public function testUserLocalDelete($aProfilesBeforeUserCreation, $sWaitForException)
{
$oUser = new UserLocal();
$sLogin = 'testUserLocalCreationWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin);
$oUser->Set('password', 'ABCD1234@gabuzomeu');
$oUser->Set('language', 'EN US');
if (false !== $sWaitForException) {
$this->expectException($sWaitForException);
}
$this->commonUserCreationTest($oUser, $aProfilesBeforeUserCreation, false);
$oUser->DBDelete();
}
/**
* @dataProvider PortaPowerUserProvider
* @covers User::CheckPortalProfiles
*/
public function testUserLocalUpdate($aProfilesBeforeUserCreation, $sWaitForException)
{
$oUser = new UserLocal();
$sLogin = 'testUserLocalUpdateWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin);
$oUser->Set('password', 'ABCD1234@gabuzomeu');
$oUser->Set('language', 'EN US');
if (false !== $sWaitForException) {
$this->expectException($sWaitForException);
}
$this->commonUserUpdateTest($oUser, $aProfilesBeforeUserCreation);
}
private function commonUserCreationTest($oUserToCreate, $aProfilesBeforeUserCreation, $bTestUserItopAccess = true)
{
$sUserClass = get_class($oUserToCreate);
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, $aProfilesBeforeUserCreation);
$this->CheckProfilesAreOkAndThenConnectToITop($sUserClass, $sId, $aProfilesBeforeUserCreation, $bTestUserItopAccess);
}
private function commonUserUpdateTest($oUserToCreate, $aProfilesBeforeUserCreation)
{
$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 ($aProfilesBeforeUserCreation 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->CheckProfilesAreOkAndThenConnectToITop($sUserClass, $sId, $aProfilesBeforeUserCreation);
}
private function CreateUserForProfileTesting(User $oUserToCreate, array $aProfilesBeforeUserCreation, $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);
$oUserProfileList = $oUserToCreate->Get('profile_list');
foreach ($aProfilesBeforeUserCreation 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];
}
private function CheckProfilesAreOkAndThenConnectToITop($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation, $bTestItopConnection = true)
{
$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));
}
if (!$bTestItopConnection) {
return;
}
$_SESSION = [];
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 = [];
}
/**
* @dataProvider ProfilesLinksProvider
*/
public function testProfilesLinksDBDelete(string $sProfileNameToRemove, $bRaiseException = false)
{
$aInitialProfiles = [$sProfileNameToRemove, 'Portal power user'];
$oUser = new UserExternal();
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin);
[$sId, $aProfiles] = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
if ($bRaiseException) {
$this->expectException(DeleteException::class);
}
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
if (array_key_exists($sProfileNameToRemove, $aURPUserProfileByUser)) {
$oURPUserProfile = $aURPUserProfileByUser[$sProfileNameToRemove];
$oURPUserProfile->DBDelete();
}
}
/**
* @dataProvider ProfilesLinksProvider
*/
public function testProfilesLinksEdit_ChangeProfileId(string $sInitialProfile, $bRaiseException = false)
{
$oUser = new UserExternal();
$sLogin = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin);
$sUserClass = get_class($oUser);
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, [$sInitialProfile]);
$oURP_Profile = MetaModel::GetObjectByColumn('URP_Profiles', 'name', 'Portal power user');
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
if ($bRaiseException) {
$this->expectException(CoreCannotSaveObjectException::class);
}
if (array_key_exists($sInitialProfile, $aURPUserProfileByUser)) {
$oURPUserProfile = $aURPUserProfileByUser[$sInitialProfile];
$oURPUserProfile->Set('profileid', $oURP_Profile->GetKey());
$oURPUserProfile->DBWrite();
}
if (!$bRaiseException) {
$aExpectedProfilesAfterUpdate = ['Portal power user', 'Portal user'];
$this->CheckProfilesAreOkAndThenConnectToITop($sUserClass, $sId, $aExpectedProfilesAfterUpdate);
}
}
public function ProfilesLinksProvider()
{
return [
'Administrator' => ['sProfileNameToMove' => 'Administrator', 'bRaiseException' => true],
'Portal user' => ['sProfileNameToMove' => 'Portal user', 'bRaiseException' => true],
];
}
/**
* @dataProvider ProfilesLinksProvider
*/
public function testProfilesLinksEdit_ChangeUserId($sProfileNameToMove, $bRaiseException = false)
{
$aInitialProfiles = [$sProfileNameToMove, 'Portal power user'];
$oUser = new UserExternal();
$sLogin1 = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin1);
$sUserClass = get_class($oUser);
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, $aInitialProfiles);
$oUser = new UserExternal();
$sLogin2 = 'testUserLDAPUpdateWithPortalPowerUserProfile-'.uniqid('', true);
$oUser->Set('login', $sLogin2);
list ($sAnotherUserId, $aProfiles) = $this->CreateUserForProfileTesting($oUser, ['Configuration Manager']);
if ($bRaiseException) {
$this->expectException(CoreCannotSaveObjectException::class);
}
$aURPUserProfileByUser = $this->GetURPUserProfileByUser($sId);
if (array_key_exists($sProfileNameToMove, $aURPUserProfileByUser)) {
$oURPUserProfile = $aURPUserProfileByUser[$sProfileNameToMove];
$oURPUserProfile->Set('userid', $sAnotherUserId);
$oURPUserProfile->DBWrite();
}
if (!$bRaiseException) {
$aExpectedProfilesAfterUpdate = [$sProfileNameToMove, 'Configuration Manager'];
$this->CheckProfilesAreOkAndThenConnectToITop($sUserClass, $sAnotherUserId, $aExpectedProfilesAfterUpdate);
$aExpectedProfilesAfterUpdate = ['Portal power user', 'Portal user'];
$this->CheckProfilesAreOkAndThenConnectToITop($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 CustomizedPortalsProvider()
{
return [
'console + customized portal' => [
'aPortalDispatcherData' => [
'customer-portal',
'backoffice',
],
],
'console + itop portal + customized portal' => [
'aPortalDispatcherData' => [
'itop-portal',
'customer-portal',
'backoffice',
],
],
];
}
}

View File

@@ -488,29 +488,4 @@ class UserRightsTest extends ItopDataTestCase
'with Admins hidden' => [true, 0],
];
}
/**
* @dataProvider WithConstraintParameterProvider
* @param string $sClass
* @param string $sAttCode
* @param bool $bExpected
*
* @return void
* @throws \Exception
*/
public function testWithConstraintParameter(string $sClass, string $sAttCode, bool $bExpected)
{
$oAttDef = \MetaModel::GetAttributeDef($sClass, $sAttCode);
$this->assertTrue(method_exists($oAttDef, "GetHasConstraint"));
$this->assertEquals($bExpected, $oAttDef->GetHasConstraint());
}
public function WithConstraintParameterProvider()
{
return [
['User', 'profile_list', true],
['User', 'allowed_org_list', true],
['Person', 'team_list', false],
];
}
}