Compare commits

...

22 Commits

Author SHA1 Message Date
jf-cbd
9c5bef05ef Removing user counting from iTop (to put it in itop-system-information) 2026-06-12 09:14:14 +02:00
jf-cbd
20dc01ef15 Removing user counting from iTop (to put it in itop-system-information) 2026-06-12 09:14:14 +02:00
jf-cbd
644ac1cb9b Refactor 2026-06-12 09:14:14 +02:00
jf-cbd
422ca60964 Align dict key with the others 2026-06-12 09:14:14 +02:00
jf-cbd
81832202d5 Remove assertion in test 2026-06-12 09:14:14 +02:00
jf-cbd
950617733b Check if class UserToken exists 2026-06-12 09:14:13 +02:00
jf-cbd
5fdd1dad85 Check if class UserToken exists 2026-06-12 09:14:13 +02:00
jf-cbd
b61a836685 Check if class UserToken exists 2026-06-12 09:14:13 +02:00
jf-cbd
0d5bfb97ce Revert format 2026-06-12 09:14:13 +02:00
jf-cbd
286671d409 CS fixer 2026-06-12 09:14:13 +02:00
jf-cbd
c4c21964c0 Adapt test after test method signature changed (on rebase). 2026-06-12 09:14:13 +02:00
jf-cbd
a985504d92 Improve test readability 2026-06-12 09:14:13 +02:00
jf-cbd
38e4a12656 Add more unit tests 2026-06-12 09:14:13 +02:00
jf-cbd
c38ef99771 With business portal users 2026-06-12 09:14:12 +02:00
jf-cbd
75780bfc1f WIP 2026-06-12 09:14:12 +02:00
jf-cbd
9061f0317b Improve test method to be able to get login OR id of the created user 2026-06-12 09:14:12 +02:00
jf-cbd
ac276e8ae2 WIP 2026-06-12 09:14:12 +02:00
jf-cbd
55940cb2f1 WIP improving quota computing 2026-06-12 09:14:12 +02:00
jf-cbd
6ca0c927e4 Rollback 2026-06-12 09:14:12 +02:00
jf-cbd
0f290229e8 WIP 2026-06-12 09:14:12 +02:00
jf-cbd
5a0343fc80 Update profiles definition 2026-06-12 09:14:11 +02:00
jf-cbd
f374395d33 WIP on new user read-only profiles 2026-06-12 09:14:11 +02:00
3 changed files with 223 additions and 6 deletions

View File

@@ -85,6 +85,13 @@
<class id="Attachment"/>
</classes>
</group>
<group id="Ticket" _delta="define">
<classes>
<class id="Ticket"/>
<class id="WorkOrder"/>
<class id="Attachment"/>
</classes>
</group>
<group id="Portal" _delta="define">
<classes>
<class id="lnkFunctionalCIToTicket"/>
@@ -205,6 +212,60 @@
</group>
</groups>
<profiles>
<profile id="5500" _delta="define">
<name>Configuration ReadOnly</name>
<description>This read-only profile allows to see CIs objects.</description>
<groups>
<group id="Configuration">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="5501" _delta="define">
<name>Ticket ReadOnly</name>
<description>This read-only profile allows to see Ticket objects.</description>
<groups>
<group id="Ticket">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="5502" _delta="define">
<name>Service Catalog ReadOnly</name>
<description>This read-only profile allows to see Service Catalog objects.</description>
<groups>
<group id="Service">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="117" _delta="define">
<name>SuperUser</name>
<description>This profile allows all actions which are not Administrator restricted.</description>

View File

@@ -87,8 +87,6 @@ abstract class ItopDataTestCase extends ItopTestCase
*/
public const DEFAULT_TEST_ENVIRONMENT = 'production';
public const USE_TRANSACTION = true;
public const CREATE_TEST_ORG = false;
protected static $aURP_Profiles = [
'Administrator' => 1,
'Portal user' => 2,
@@ -102,9 +100,15 @@ abstract class ItopDataTestCase extends ItopTestCase
'Service Manager' => 10,
'Document author' => 11,
'Portal power user' => 12,
'Business partner user' => 40,
'REST Services User' => 1024,
'Configuration ReadOnly' => 5500,
'Ticket ReadOnly' => 5501,
'Service Catalog ReadOnly' => 5502,
];
public const CREATE_TEST_ORG = false;
/**
* This method is called before the first test of this test class is run (in the current process).
*/
@@ -1463,16 +1467,42 @@ abstract class ItopDataTestCase extends ItopTestCase
]);
}
/**
* @description To avoid adding finalclasses parameters to GivenUserInDB
* @param string $sPassword
* @param array $aProfiles Profile names Example: ['Administrator']
* @param bool $bReturnLogin
*
* @return string|int The unique login
* @throws \Exception
*/
protected function GivenTokenUserInDB(array $aProfiles, bool $bReturnLogin = true): string|int
{
$sLogin = 'demo_test_'.uniqid(__CLASS__, true);
$aProfileList = array_map(function ($sProfileId) {
return 'profileid:'.self::$aURP_Profiles[$sProfileId];
}, $aProfiles);
$iUser = $this->GivenObjectInDB('UserToken', [
'login' => $sLogin,
'language' => 'EN US',
'profile_list' => $aProfileList,
]);
return $bReturnLogin ? $sLogin : $iUser;
}
/**
* @param string $sPassword
* @param array $aProfiles Profile names Example: ['Administrator']
* @param string|null $sLogin
* @param string|null $sUserId
* @param bool $bReturnLogin
*
* @return string The unique login
* @throws \Exception
*/
protected function GivenUserInDB(string $sPassword, array $aProfiles, ?string $sLogin = null, ?string &$sUserId = null): string
protected function GivenUserInDB(string $sPassword, array $aProfiles, ?string $sLogin = null, ?string &$sUserId = null, bool $bReturnLogin = true): string
{
if (is_null($sLogin)) {
$sLogin = 'demo_test_'.uniqid(__CLASS__, true);
@@ -1489,7 +1519,7 @@ abstract class ItopDataTestCase extends ItopTestCase
'profile_list' => $aProfileList,
]);
return $sLogin;
return $bReturnLogin ? $sLogin : $sUserId;
}
/**

View File

@@ -29,11 +29,11 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreCannotSaveObjectException;
use CoreException;
use DBObject;
use DBObjectSearch;
use DBObjectSet;
use DeleteException;
use Dict;
use MetaModel;
use UserLocal;
use UserRights;
@@ -81,6 +81,54 @@ class UserRightsTest extends ItopDataTestCase
return $oUser;
}
/**
* @param array $aProfileIds
* @param array $aShouldBeAllowedToSeeClass
* @param array $aShouldBeAllowedToEditClass
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \DictExceptionUnknownLanguage
* @throws \MySQLException
* @throws \OQLException
* @dataProvider ReadOnlyProvider
*/
public function testReadOnlyUser(array $aProfileIds, array $aShouldBeAllowedToSeeClass, array $aShouldBeAllowedToEditClass): void
{
$oUser = $this->GivenUserWithProfiles('test1', $aProfileIds);
$oUser->DBInsert();
$_SESSION = [];
UserRights::Login($oUser->Get('login'));
$aClassesToTest = ['FunctionalCI', 'Ticket', 'ServiceFamily'];
foreach ($aClassesToTest as $sClass) {
$bShouldBeAllowedToSee = in_array($sClass, $aShouldBeAllowedToSeeClass);
$bIsAllowedReading = (bool)UserRights::IsActionAllowed($sClass, UR_ACTION_READ);
$this->assertSame(
$bShouldBeAllowedToSee,
$bIsAllowedReading,
"User with profiles ".implode(',', $aProfileIds)." should ".($bShouldBeAllowedToSee ? "" : "NOT ")."be allowed to see class $sClass"
);
$bShouldBeAllowedToEdit = in_array($sClass, $aShouldBeAllowedToEditClass);
$bIsAllowedEditing = (bool)UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY);
$this->assertSame(
$bIsAllowedEditing,
$bShouldBeAllowedToEdit,
"User with profiles ".implode(',', $aProfileIds)." should ".($bShouldBeAllowedToEdit ? "" : "NOT ")."be allowed to edit class $sClass"
);
}
}
protected function GivenUserWithProfiles(string $sLogin, array $aProfileIds): DBObject
{
$oProfiles = new \ormLinkSet(\UserLocal::class, 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
@@ -433,7 +481,7 @@ class UserRightsTest extends ItopDataTestCase
$oUser = $this->GivenUserWithProfiles('test1', [$iProfileId, 2]);
$this->expectException(CoreCannotSaveObjectException::class);
$this->expectExceptionMessage('Profile "Portal user" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)');
$this->expectExceptionMessage(Dict::Format('Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice', PORTAL_PROFILE_NAME));
$oUser->DBInsert();
}
@@ -572,4 +620,82 @@ class UserRightsTest extends ItopDataTestCase
$oUser = $this->InvokeNonPublicStaticMethod(UserRights::class, "FindUser", [$sLogin]);
static::assertNull($oUser, 'FindUser should return null when the login is unknown');
}
protected function ReadOnlyProvider(): array
{
return [
'CI' => [
'ProfilesId' => [
5500,
],
'ShouldBeAllowedToSeeClasses' => [
'FunctionalCI',
],
'ShouldBeAllowedToEditClasses' => [],
],
'Tickets' => [
'ProfilesId' => [
5501,
],
'ShouldBeAllowedToSeeClasses' => [
'Ticket',
],
'ShouldBeAllowedToEditClasses' => [],
],
'Catalog' => [
'ProfilesId' => [
5502,
],
'ShouldBeAllowedToSeeClasses' => [
'ServiceFamily',
],
'ShouldBeAllowedToEditClasses' => [],
],
'CI and Tickets' => [
'ProfilesId' => [
5500, 5501,
],
'ShouldBeAllowedToSeeClasses' => [
'FunctionalCI', 'Ticket',
],
'ShouldBeAllowedToEditClasses' => [],
],
'CI and Catalog' => [
'ProfilesId' => [
5500, 5502,
],
'ShouldBeAllowedToSeeClasses' => [
'FunctionalCI', 'ServiceFamily',
],
'ShouldBeAllowedToEditClasses' => [],
],
'Tickets and Catalog' => [
'ProfilesId' => [
5501, 5502,
],
'ShouldBeAllowedToSeeClasses' => [
'Ticket', 'ServiceFamily',
],
'ShouldBeAllowedToEditClasses' => [],
],
'Tickets and Catalog + profile Ccnfiguration Manager' => [
'ProfilesId' => [
5501, 5502, 3,
],
'ShouldBeAllowedToSeeClasses' => [
'FunctionalCI', 'Ticket', 'ServiceFamily',
],
'ShouldBeAllowedToEditClasses' => ['FunctionalCI'],
],
'CI, Tickets and Catalog' => [
'ProfilesId' => [
5500, 5501, 5502,
],
'ShouldBeAllowedToSeeClasses' => [
'FunctionalCI', 'Ticket', 'ServiceFamily',
],
'ShouldBeAllowedToEditClasses' => [],
],
];
}
}