From 07eadb3ea7dffaf5ec42f0488a7eeeda24052814 Mon Sep 17 00:00:00 2001 From: odain Date: Wed, 28 Jun 2023 14:41:20 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B05324=20-rename=20and=20move=20conf=20par?= =?UTF-8?q?ameter=20to=20security.single-profile-completion=20+=20display?= =?UTF-8?q?=20warningmessage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/config.class.inc.php | 8 ++ .../datamodel.itop-profiles-itil.xml | 20 +++- .../src/UserProfilesEventListener.php | 6 +- .../UserProfilesEventListenerTest.php | 105 ++++++++++++++---- 4 files changed, 115 insertions(+), 24 deletions(-) diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 8d38d09be3..8443932cd2 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -1595,6 +1595,14 @@ class Config 'source_of_value' => '', 'show_in_conf_sample' => false, ], + 'security.single-profile-completion' => [ + 'type' => 'array', + 'description' => 'Non standalone profiles can be completed by other profiles via this configuration. default configuration is equivalent to [\'Portal power user\' => \'Portal user\'] configuration. unless you have specific portal customization.', + 'default' => null, + 'value' => false, + 'source_of_value' => '', + 'show_in_conf_sample' => false, + ], 'behind_reverse_proxy' => [ 'type' => 'bool', 'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)', diff --git a/datamodels/2.x/itop-profiles-itil/datamodel.itop-profiles-itil.xml b/datamodels/2.x/itop-profiles-itil/datamodel.itop-profiles-itil.xml index d4e83b713f..2bdacbfdd0 100755 --- a/datamodels/2.x/itop-profiles-itil/datamodel.itop-profiles-itil.xml +++ b/datamodels/2.x/itop-profiles-itil/datamodel.itop-profiles-itil.xml @@ -1,5 +1,5 @@ - + @@ -544,5 +544,23 @@ + + + English + English + + User profile %1$s cannot be standalone. You should add + other prrofiles otherwise you may encounter access issue with this user. + + + + French + Français + + Le profil %1$s ne peut être seul. Sans rajout d'autres profiles, + l'utilisateur peut rencontrer des problèmes dans iTop. + + + diff --git a/datamodels/2.x/itop-profiles-itil/src/UserProfilesEventListener.php b/datamodels/2.x/itop-profiles-itil/src/UserProfilesEventListener.php index a378836e33..d47da74fa8 100644 --- a/datamodels/2.x/itop-profiles-itil/src/UserProfilesEventListener.php +++ b/datamodels/2.x/itop-profiles-itil/src/UserProfilesEventListener.php @@ -24,7 +24,7 @@ define('POWER_USER_PORTAL_PROFILE_NAME', 'Portal power user'); */ class UserProfilesEventListener implements iEventServiceSetup { - const USERPROFILE_REPAIR_ITOP_PARAM_NAME = 'poweruserportal-repair-profile'; + const USERPROFILE_REPAIR_ITOP_PARAM_NAME = 'security.single-profile-completion'; private $bIsRepairmentEnabled = false; //map: non standalone profile name => repairing profile id @@ -90,7 +90,7 @@ class UserProfilesEventListener implements iEventServiceSetup $aPortalDispatcherData = \PortalDispatcherData::GetData(); } - $aNonStandaloneProfiles = \utils::GetConfig()->GetModuleSetting('itop-profiles-itil', self::USERPROFILE_REPAIR_ITOP_PARAM_NAME, null); + $aNonStandaloneProfiles = \utils::GetConfig()->Get(self::USERPROFILE_REPAIR_ITOP_PARAM_NAME, null); //When there are several customized portals on an itop, choosing a specific profile means choosing which portal user will access //In that case, itop administrator has to specify it via itop configuration. we dont use default profiles repairment otherwise @@ -190,6 +190,8 @@ class UserProfilesEventListener implements iEventServiceSetup if (is_null($sRepairingProfileId)){ //Notify current user via session messages that there will be an issue //Without preventing from commiting + $sMessage = \Dict::Format("Class:User/NonStandaloneProfileWarning", $sSingleProfileName); + $oUser::SetSessionMessage(get_class($oUser), $oUser->GetKey(), 1, $sMessage, 'WARNING', 1); } else { //Completing profiles profiles by adding repairing one : by default portal user to a power portal user $oUserProfile = new \URP_UserProfile(); diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-profiles-itil/UserProfilesEventListenerTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-profiles-itil/UserProfilesEventListenerTest.php index b88acd0e9a..a1e1e7e6bc 100644 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-profiles-itil/UserProfilesEventListenerTest.php +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-profiles-itil/UserProfilesEventListenerTest.php @@ -26,14 +26,17 @@ namespace Combodo\iTop\Test\UnitTest\Module\iTopProfilesItil; +use Combodo\iTop\Application\Helper\Session; use Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenuFactory; use Combodo\iTop\ItilProfiles\UserProfilesEventListener; +use Combodo\iTop\Service\Events\EventService; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; use DBObjectSet; use URP_UserProfile; use UserRights; /** + * @since 3.1.0 N°5324 * @group itopRequestMgmt * @group userRights * @group defaultProfiles @@ -44,6 +47,13 @@ use UserRights; */ class UserProfilesEventListenerTest extends ItopDataTestCase { + public function setUp(): void { + parent::setUp(); + + //reset conf to have nominal behaviour + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, null); + } + public function PortaPowerUserProvider(){ return [ 'Portal power user only => user should be repaired by adding User portal profile' => [ @@ -69,7 +79,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserLocalCreation($aAssociatedProfilesBeforeUserCreation, @@ -84,7 +93,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserLocalUpdate($aAssociatedProfilesBeforeUserCreation, @@ -99,7 +107,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserLDAPCreation($aAssociatedProfilesBeforeUserCreation, @@ -112,7 +119,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserLDAPUpdate($aAssociatedProfilesBeforeUserCreation, @@ -125,7 +131,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserExternalCreation($aAssociatedProfilesBeforeUserCreation, @@ -138,7 +143,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } /** - * @since 3.1.0 N°5324 * @dataProvider PortaPowerUserProvider */ public function testUserExternalUpdate($aAssociatedProfilesBeforeUserCreation, @@ -186,15 +190,15 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } public function commonUserCreation($oUserToCreate, $aAssociatedProfilesBeforeUserCreation, - $aExpectedAssociatedProfilesAfterUserCreation) + $aExpectedAssociatedProfilesAfterUserCreation, $bTestUserItopAccess=true) { $sUserClass = get_class($oUserToCreate); list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, $aAssociatedProfilesBeforeUserCreation); - $this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation); + $this->CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation, $bTestUserItopAccess); } - public function CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation){ + public function CheckProfilesAreOk($sUserClass, $sId, $aExpectedAssociatedProfilesAfterUserCreation, $bTestUserItopAccess=true){ $oUser = \MetaModel::GetObject($sUserClass, $sId); $oUserProfileList = $oUser->Get('profile_list'); $aProfilesAfterCreation=[]; @@ -207,6 +211,10 @@ class UserProfilesEventListenerTest extends ItopDataTestCase "profile \'$sExpectedProfileName\' should be asociated to user after creation. " . var_export($aProfilesAfterCreation, true) ); } + if (! $bTestUserItopAccess){ + return; + } + $_SESSION = []; //$this->expectException(\Exception::class); @@ -378,7 +386,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } public function testUserProfilesEventListenerInit_badlyconfigured(){ - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, "a string instead of an array"); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, "a string instead of an array"); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); @@ -387,7 +395,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } public function testUserProfilesEventListenerInit_specifically_disabled(){ - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, []); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, []); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); @@ -428,7 +436,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase 'backoffice' ]; - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, ['Portal power user' => 'Portal user']); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, ['Portal power user' => 'Portal user']); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init($aPortalDispatcherData); @@ -443,7 +451,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase 'backoffice' ]; - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, ['Portal power user' => 'Dummy Profile']); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, ['Portal power user' => 'Dummy Profile']); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init($aPortalDispatcherData); @@ -452,24 +460,27 @@ class UserProfilesEventListenerTest extends ItopDataTestCase } public function testInit_ConfWithOneWarningProfile() { - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, - ['Change Supervisor' => 'Administrator', 'Portal power user' => null]); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + ['Change Supervisor' => 'Administrator', 'Portal power user' => null] + ); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); } public function testInit_ConfWithFurtherWarningProfiles() { - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, - ['Change Supervisor' => null, 'Portal power user' => null]); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + ['Change Supervisor' => null, 'Portal power user' => null] + ); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); } public function testInit_ConfWithFurtherWarningProfilesAndOneRepairment() { - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, - ['Portal power user' => null, 'Change Supervisor' => null, 'Administrator' => "REST Services User"]); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + ['Portal power user' => null, 'Change Supervisor' => null, 'Administrator' => "REST Services User"] + ); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); @@ -483,7 +494,9 @@ class UserProfilesEventListenerTest extends ItopDataTestCase $oUser->Set('password', 'ABCD1234@gabuzomeu'); $oUser->Set('language', 'EN US'); - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, ['Portal power user' => 'Change Supervisor']); + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + ['Portal power user' => 'Change Supervisor'] + ); $oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener->Init(); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); @@ -503,7 +516,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase public function testRepairProfiles_MultiRepairmentConf() { - \MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, [ 'Administrator' => 'REST Services User', 'Portal power user' => 'Change Supervisor' @@ -548,4 +561,54 @@ class UserProfilesEventListenerTest extends ItopDataTestCase $this->assertContains('Administrator', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true)); $this->assertContains('REST Services User', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true)); } + + public function testUserCreationWithWarningMessageConf() + { + $_SESSION = []; + $oAdminUser = new \UserLocal(); + $sLogin = 'testUserCreationWithWarningMessageConf-Admin'.uniqid(); + $oAdminUser->Set('login', $sLogin); + $oAdminUser->Set('password', 'ABCD1234@gabuzomeu'); + $oAdminUser->Set('language', 'EN US'); + $aAssociatedProfilesBeforeUserCreation = ['Administrator']; + $this->commonUserCreation($oAdminUser, $aAssociatedProfilesBeforeUserCreation, $aAssociatedProfilesBeforeUserCreation, false); + UserRights::Login($oAdminUser->Get('login')); + + + + $aAssociatedProfilesBeforeUserCreation = [ + 'Portal power user' + ]; + + $oUser = new \UserLocal(); + $sLogin = 'testUserCreationWithWarningMessageConf-'.uniqid(); + $oUser->Set('login', $sLogin); + $oUser->Set('password', 'ABCD1234@gabuzomeu'); + $oUser->Set('language', 'EN US'); + + \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, + ['Portal power user' => null ] + ); + + $this->SetNonPublicStaticProperty(EventService::class, "aEventListeners", []); + $oUserProfilesEventListener = new UserProfilesEventListener(); + $oUserProfilesEventListener->RegisterEventsAndListeners(); + + $this->commonUserCreation($oUser, $aAssociatedProfilesBeforeUserCreation, $aAssociatedProfilesBeforeUserCreation, false); + $aObjMessages = Session::Get('obj_messages'); + $this->assertNotEmpty($aObjMessages); + $sKey = sprintf("%s::%s", get_class($oUser), $oUser->GetKey()); + $this->assertTrue(array_key_exists($sKey, $aObjMessages)); + + $aExpectedMessages = [ + [ + 'rank' => 1, + 'severity' => 'WARNING', + 'message' => \Dict::Format("Class:User/NonStandaloneProfileWarning", 'Portal power user') + ] + ]; + $this->assertEquals($aExpectedMessages, array_values($aObjMessages[$sKey]), var_export($aObjMessages[$sKey], true)); + + $_SESSION = []; + } }