mirror of
https://github.com/Combodo/iTop.git
synced 2026-10-17 22:08:55 +02:00
Compare commits
4 Commits
develop
...
issue/9641
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
389d95fec5 | ||
|
|
6536eeab1c | ||
|
|
ec8ec767d2 | ||
|
|
7ef28d1aea |
@@ -3936,6 +3936,18 @@ HTML;
|
||||
$iFlags = $iFlags & ~OPT_ATT_READONLY; // Mandatory fields cannot be read-only when creating an object
|
||||
}
|
||||
|
||||
if (!$this->IsNew()
|
||||
&& ($sAttCode === 'email')
|
||||
&& MetaModel::IsParentClass('Contact', get_class($this))
|
||||
&& UserRights::IsActionAllowedOnAttribute(
|
||||
get_class($this),
|
||||
$sAttCode,
|
||||
UR_ACTION_MODIFY,
|
||||
DBObjectSet::FromObject($this)
|
||||
) != UR_ALLOWED_YES) {
|
||||
$iFlags |= OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return $iFlags;
|
||||
}
|
||||
|
||||
|
||||
@@ -438,9 +438,21 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
|
||||
$oResult->message = "The current user does not have enough permissions for massively modifying data of class $sTargetClass";
|
||||
} else {
|
||||
$oObject = RestUtils::FindObjectFromKey($sClass, $key);
|
||||
RestUtils::UpdateObjectFromFields($oObject, $aFields);
|
||||
$oObject->DBUpdate();
|
||||
$oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput);
|
||||
if (MetaModel::IsParentClass('Contact', get_class($oObject))
|
||||
&& property_exists($aFields, 'email')
|
||||
&& UserRights::IsActionAllowedOnAttribute(
|
||||
get_class($oObject),
|
||||
'email',
|
||||
UR_ACTION_MODIFY,
|
||||
DBObjectSet::FromObject($oObject)
|
||||
) != UR_ALLOWED_YES) {
|
||||
$oResult->code = RestResult::UNAUTHORIZED;
|
||||
$oResult->message = "The current user does not have enough permissions for modifying the email of the contact of class $sTargetClass";
|
||||
} else {
|
||||
RestUtils::UpdateObjectFromFields($oObject, $aFields);
|
||||
$oObject->DBUpdate();
|
||||
$oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -1635,10 +1635,18 @@ class UserRights
|
||||
return UR_ALLOWED_YES;
|
||||
}
|
||||
|
||||
if (is_null($oUser)) {
|
||||
$oUser = self::$m_oUser;
|
||||
}
|
||||
|
||||
if (($sAttCode === 'email')
|
||||
&& in_array($iActionCode, [UR_ACTION_MODIFY, UR_ACTION_BULK_MODIFY], true)
|
||||
&& MetaModel::IsParentClass('Contact', $sClass)
|
||||
&& !self::IsContactEmailEditAllowed($oInstanceSet, $oUser)) {
|
||||
return UR_ALLOWED_NO;
|
||||
}
|
||||
|
||||
if (MetaModel::HasCategory($sClass, 'bizmodel') || MetaModel::HasCategory($sClass, 'grant_by_profile')) {
|
||||
if (is_null($oUser)) {
|
||||
$oUser = self::$m_oUser;
|
||||
}
|
||||
return self::$m_oAddOn->IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet);
|
||||
}
|
||||
|
||||
@@ -1652,6 +1660,30 @@ class UserRights
|
||||
|
||||
}
|
||||
|
||||
private static function IsContactEmailEditAllowed($oInstanceSet, $oUser): bool
|
||||
{
|
||||
if (self::HasProfile('SuperUser', $oUser) && self::IsAdministrator($oUser)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$oCurrentContact = is_null($oUser) ? null : $oUser->GetContactObject();
|
||||
if (is_null($oCurrentContact)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$oTargetContact = null;
|
||||
if ($oInstanceSet instanceof DBObject) {
|
||||
$oTargetContact = $oInstanceSet;
|
||||
} elseif (($oInstanceSet instanceof DBObjectSet) && ($oInstanceSet->Count() === 1)) {
|
||||
$aTargetObjects = $oInstanceSet->ToArray(false);
|
||||
$oTargetContact = $aTargetObjects[0] ?? null;
|
||||
}
|
||||
|
||||
return ($oTargetContact instanceof DBObject)
|
||||
&& MetaModel::IsParentClass('Contact', get_class($oTargetContact))
|
||||
&& ($oCurrentContact->GetKey() == $oTargetContact->GetKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \User|null $oUser
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@ use DBObject;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use DeleteException;
|
||||
use MetaModel;
|
||||
use URP_UserProfile;
|
||||
use UserRights;
|
||||
use utils;
|
||||
@@ -278,6 +279,71 @@ class UserRightsTest extends ItopDataTestCase
|
||||
];
|
||||
}
|
||||
|
||||
public function testLinkedUserCanUpdateOwnContactEmailViaDbUpdate(): void
|
||||
{
|
||||
$this->CreateTestOrganization();
|
||||
$oContact = $this->CreatePerson(201);
|
||||
$this->CreateAndLoginContactEmailTestUser('contact-email-linked-', 3, $oContact);
|
||||
|
||||
$oContact->Set('email', 'linked-user@example.com');
|
||||
$oContact->DBUpdate();
|
||||
|
||||
$this->assertSame('linked-user@example.com', MetaModel::GetObject('Contact', $oContact->GetKey(), false, true)->Get('email'));
|
||||
}
|
||||
|
||||
public function testAdministratorCanUpdateAnotherContactEmailViaDbUpdate(): void
|
||||
{
|
||||
$this->CreateTestOrganization();
|
||||
$oTargetContact = $this->CreatePerson(202);
|
||||
$oAdministratorContact = $this->CreatePerson(203);
|
||||
$this->CreateAndLoginContactEmailTestUser('contact-email-admin-', 1, $oAdministratorContact);
|
||||
|
||||
$oTargetContact->Set('email', 'administrator@example.com');
|
||||
$oTargetContact->DBUpdate();
|
||||
|
||||
$this->assertSame('administrator@example.com', MetaModel::GetObject('Contact', $oTargetContact->GetKey(), false, true)->Get('email'));
|
||||
}
|
||||
|
||||
public function testSuperUserCanUpdateAnotherContactEmailViaDbUpdate(): void
|
||||
{
|
||||
$this->CreateTestOrganization();
|
||||
$oTargetContact = $this->CreatePerson(204);
|
||||
$oSuperUserContact = $this->CreatePerson(205);
|
||||
$oSuperUserProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'SuperUser'], true);
|
||||
$this->assertNotNull($oSuperUserProfile, 'The SuperUser profile must be available for this test');
|
||||
$this->CreateAndLoginContactEmailTestUser('contact-email-superuser-', $oSuperUserProfile->GetKey(), $oSuperUserContact);
|
||||
|
||||
$oTargetContact->Set('email', 'superuser@example.com');
|
||||
$oTargetContact->DBUpdate();
|
||||
|
||||
$this->assertSame('superuser@example.com', MetaModel::GetObject('Contact', $oTargetContact->GetKey(), false, true)->Get('email'));
|
||||
}
|
||||
|
||||
public function testConfigurationManagerCannotUpdateAnotherContactEmailViaDbUpdate(): void
|
||||
{
|
||||
$this->CreateTestOrganization();
|
||||
$oTargetContact = $this->CreatePerson(206);
|
||||
$oConfigurationManagerContact = $this->CreatePerson(207);
|
||||
$this->CreateAndLoginContactEmailTestUser('contact-email-config-manager-', 3, $oConfigurationManagerContact);
|
||||
|
||||
$oTargetContact->Set('email', 'forbidden@example.com');
|
||||
try {
|
||||
$oTargetContact->DBUpdate();
|
||||
$this->fail('The object write check must reject an email change to another contact');
|
||||
} catch (CoreCannotSaveObjectException $e) {
|
||||
$this->assertNotEmpty($e->getIssues());
|
||||
}
|
||||
|
||||
$this->assertSame('', MetaModel::GetObject('Contact', $oTargetContact->GetKey(), false, true)->Get('email'));
|
||||
}
|
||||
|
||||
private function CreateAndLoginContactEmailTestUser(string $sLoginPrefix, int $iProfileId, DBObject $oContact): void
|
||||
{
|
||||
$_SESSION = [];
|
||||
$oUser = $this->CreateUser(uniqid($sLoginPrefix), $iProfileId, 'A1b!Passw0rd', $oContact->GetKey());
|
||||
UserRights::Login($oUser->Get('login'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ProfileDenyingConsoleProvider
|
||||
* @doesNotPerformAssertions
|
||||
|
||||
Reference in New Issue
Block a user