N°5324 -rename and move conf parameter to security.single-profile-completion + display warningmessage

This commit is contained in:
odain
2023-06-28 14:41:20 +02:00
parent 97f4818076
commit 07eadb3ea7
4 changed files with 115 additions and 24 deletions

View File

@@ -1595,6 +1595,14 @@ class Config
'source_of_value' => '', 'source_of_value' => '',
'show_in_conf_sample' => false, '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' => [ 'behind_reverse_proxy' => [
'type' => 'bool', '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)', '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)',

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1"> <itop_design version="3.1">
<classes/> <classes/>
<user_rights> <user_rights>
<groups> <groups>
@@ -544,5 +544,23 @@
<groups/> <groups/>
</profile> </profile>
</profiles> </profiles>
<dictionaries>
<dictionary id="EN US" _alteration="added">
<english_description>English</english_description>
<localized_description>English</localized_description>
<entries>
<entry id="Class:User/NonStandaloneProfileWarning" _alteration="added">User profile %1$s cannot be standalone. You should add
other prrofiles otherwise you may encounter access issue with this user.</entry>
</entries>
</dictionary>
<dictionary id="FR FR" _alteration="added">
<english_description>French</english_description>
<localized_description>Français</localized_description>
<entries>
<entry id="Core:DeletedObjectLabel" _alteration="added">Le profil %1$s ne peut être seul. Sans rajout d'autres profiles,
l'utilisateur peut rencontrer des problèmes dans iTop.</entry>
</entries>
</dictionary>
</dictionaries>
</user_rights> </user_rights>
</itop_design> </itop_design>

View File

@@ -24,7 +24,7 @@ define('POWER_USER_PORTAL_PROFILE_NAME', 'Portal power user');
*/ */
class UserProfilesEventListener implements iEventServiceSetup 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; private $bIsRepairmentEnabled = false;
//map: non standalone profile name => repairing profile id //map: non standalone profile name => repairing profile id
@@ -90,7 +90,7 @@ class UserProfilesEventListener implements iEventServiceSetup
$aPortalDispatcherData = \PortalDispatcherData::GetData(); $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 //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 //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)){ if (is_null($sRepairingProfileId)){
//Notify current user via session messages that there will be an issue //Notify current user via session messages that there will be an issue
//Without preventing from commiting //Without preventing from commiting
$sMessage = \Dict::Format("Class:User/NonStandaloneProfileWarning", $sSingleProfileName);
$oUser::SetSessionMessage(get_class($oUser), $oUser->GetKey(), 1, $sMessage, 'WARNING', 1);
} else { } else {
//Completing profiles profiles by adding repairing one : by default portal user to a power portal user //Completing profiles profiles by adding repairing one : by default portal user to a power portal user
$oUserProfile = new \URP_UserProfile(); $oUserProfile = new \URP_UserProfile();

View File

@@ -26,14 +26,17 @@
namespace Combodo\iTop\Test\UnitTest\Module\iTopProfilesItil; 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\Application\UI\Base\Layout\NavigationMenu\NavigationMenuFactory;
use Combodo\iTop\ItilProfiles\UserProfilesEventListener; use Combodo\iTop\ItilProfiles\UserProfilesEventListener;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase; use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use DBObjectSet; use DBObjectSet;
use URP_UserProfile; use URP_UserProfile;
use UserRights; use UserRights;
/** /**
* @since 3.1.0 N°5324
* @group itopRequestMgmt * @group itopRequestMgmt
* @group userRights * @group userRights
* @group defaultProfiles * @group defaultProfiles
@@ -44,6 +47,13 @@ use UserRights;
*/ */
class UserProfilesEventListenerTest extends ItopDataTestCase 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(){ public function PortaPowerUserProvider(){
return [ return [
'Portal power user only => user should be repaired by adding User portal profile' => [ '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 * @dataProvider PortaPowerUserProvider
*/ */
public function testUserLocalCreation($aAssociatedProfilesBeforeUserCreation, public function testUserLocalCreation($aAssociatedProfilesBeforeUserCreation,
@@ -84,7 +93,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
/** /**
* @since 3.1.0 N°5324
* @dataProvider PortaPowerUserProvider * @dataProvider PortaPowerUserProvider
*/ */
public function testUserLocalUpdate($aAssociatedProfilesBeforeUserCreation, public function testUserLocalUpdate($aAssociatedProfilesBeforeUserCreation,
@@ -99,7 +107,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
/** /**
* @since 3.1.0 N°5324
* @dataProvider PortaPowerUserProvider * @dataProvider PortaPowerUserProvider
*/ */
public function testUserLDAPCreation($aAssociatedProfilesBeforeUserCreation, public function testUserLDAPCreation($aAssociatedProfilesBeforeUserCreation,
@@ -112,7 +119,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
/** /**
* @since 3.1.0 N°5324
* @dataProvider PortaPowerUserProvider * @dataProvider PortaPowerUserProvider
*/ */
public function testUserLDAPUpdate($aAssociatedProfilesBeforeUserCreation, public function testUserLDAPUpdate($aAssociatedProfilesBeforeUserCreation,
@@ -125,7 +131,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
/** /**
* @since 3.1.0 N°5324
* @dataProvider PortaPowerUserProvider * @dataProvider PortaPowerUserProvider
*/ */
public function testUserExternalCreation($aAssociatedProfilesBeforeUserCreation, public function testUserExternalCreation($aAssociatedProfilesBeforeUserCreation,
@@ -138,7 +143,6 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
/** /**
* @since 3.1.0 N°5324
* @dataProvider PortaPowerUserProvider * @dataProvider PortaPowerUserProvider
*/ */
public function testUserExternalUpdate($aAssociatedProfilesBeforeUserCreation, public function testUserExternalUpdate($aAssociatedProfilesBeforeUserCreation,
@@ -186,15 +190,15 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
public function commonUserCreation($oUserToCreate, $aAssociatedProfilesBeforeUserCreation, public function commonUserCreation($oUserToCreate, $aAssociatedProfilesBeforeUserCreation,
$aExpectedAssociatedProfilesAfterUserCreation) $aExpectedAssociatedProfilesAfterUserCreation, $bTestUserItopAccess=true)
{ {
$sUserClass = get_class($oUserToCreate); $sUserClass = get_class($oUserToCreate);
list ($sId, $aProfiles) = $this->CreateUserForProfileTesting($oUserToCreate, $aAssociatedProfilesBeforeUserCreation); 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); $oUser = \MetaModel::GetObject($sUserClass, $sId);
$oUserProfileList = $oUser->Get('profile_list'); $oUserProfileList = $oUser->Get('profile_list');
$aProfilesAfterCreation=[]; $aProfilesAfterCreation=[];
@@ -207,6 +211,10 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
"profile \'$sExpectedProfileName\' should be asociated to user after creation. " . var_export($aProfilesAfterCreation, true) ); "profile \'$sExpectedProfileName\' should be asociated to user after creation. " . var_export($aProfilesAfterCreation, true) );
} }
if (! $bTestUserItopAccess){
return;
}
$_SESSION = []; $_SESSION = [];
//$this->expectException(\Exception::class); //$this->expectException(\Exception::class);
@@ -378,7 +386,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
public function testUserProfilesEventListenerInit_badlyconfigured(){ 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 = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
@@ -387,7 +395,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
public function testUserProfilesEventListenerInit_specifically_disabled(){ 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 = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
@@ -428,7 +436,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
'backoffice' '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 = new UserProfilesEventListener();
$oUserProfilesEventListener->Init($aPortalDispatcherData); $oUserProfilesEventListener->Init($aPortalDispatcherData);
@@ -443,7 +451,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
'backoffice' '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 = new UserProfilesEventListener();
$oUserProfilesEventListener->Init($aPortalDispatcherData); $oUserProfilesEventListener->Init($aPortalDispatcherData);
@@ -452,24 +460,27 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
} }
public function testInit_ConfWithOneWarningProfile() { public function testInit_ConfWithOneWarningProfile() {
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME,
['Change Supervisor' => 'Administrator', 'Portal power user' => null]); ['Change Supervisor' => 'Administrator', 'Portal power user' => null]
);
$oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
} }
public function testInit_ConfWithFurtherWarningProfiles() { public function testInit_ConfWithFurtherWarningProfiles() {
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME,
['Change Supervisor' => null, 'Portal power user' => null]); ['Change Supervisor' => null, 'Portal power user' => null]
);
$oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
} }
public function testInit_ConfWithFurtherWarningProfilesAndOneRepairment() { public function testInit_ConfWithFurtherWarningProfilesAndOneRepairment() {
\MetaModel::GetConfig()->SetModuleSetting('itop-profiles-itil', UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME, \MetaModel::GetConfig()->Set(UserProfilesEventListener::USERPROFILE_REPAIR_ITOP_PARAM_NAME,
['Portal power user' => null, 'Change Supervisor' => null, 'Administrator' => "REST Services User"]); ['Portal power user' => null, 'Change Supervisor' => null, 'Administrator' => "REST Services User"]
);
$oUserProfilesEventListener = new UserProfilesEventListener(); $oUserProfilesEventListener = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
@@ -483,7 +494,9 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
$oUser->Set('password', 'ABCD1234@gabuzomeu'); $oUser->Set('password', 'ABCD1234@gabuzomeu');
$oUser->Set('language', 'EN US'); $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 = new UserProfilesEventListener();
$oUserProfilesEventListener->Init(); $oUserProfilesEventListener->Init();
$this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled()); $this->assertTrue($oUserProfilesEventListener->IsRepairmentEnabled());
@@ -503,7 +516,7 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
public function testRepairProfiles_MultiRepairmentConf() 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', 'Administrator' => 'REST Services User',
'Portal power user' => 'Change Supervisor' 'Portal power user' => 'Change Supervisor'
@@ -548,4 +561,54 @@ class UserProfilesEventListenerTest extends ItopDataTestCase
$this->assertContains('Administrator', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true)); $this->assertContains('Administrator', $aProfilesAfterCreation, var_export($aProfilesAfterCreation, true));
$this->assertContains('REST Services User', $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 = [];
}
} }