This commit is contained in:
jf-cbd
2025-03-05 14:35:51 +01:00
parent 755ac3a15c
commit 2fedfa1b4c
3 changed files with 176 additions and 25 deletions

View File

@@ -134,10 +134,7 @@ public function SanitizeContent()
} catch (Exception $e) { // for special cases like ID
continue;
}
if ($oAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$this->SanitizeFieldIfSensitive($this->fields, $sFieldAttCode, $fieldValue, $oAttDef);
}
}
}
}
@@ -870,11 +867,13 @@ trait SanitizeTrait
*/
private function SanitizeFieldIfSensitive(array &$fields, string $sFieldAttCode, $fieldValue, $oAttDef): void
{
// for simple attribute
if ($oAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$fields[$sFieldAttCode] = '*****';
}
if ($oAttDef instanceof AttributeLinkedSet) { // for 1-n relations
// for 1-n relations
if ($oAttDef instanceof AttributeLinkedSet) {
foreach ($fieldValue as $i => $aLnkValues) {
foreach ($aLnkValues as $sLnkAttCode => $sLnkValue) {
$oLnkAttDef = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $sLnkAttCode);
@@ -885,20 +884,32 @@ trait SanitizeTrait
}
}
}
if ($oAttDef instanceof AttributeLinkedSetIndirect) { // for n-n relations
// for n-n relations
if ($oAttDef instanceof AttributeLinkedSetIndirect) {
$extKeyToRemote = $oAttDef->GetExtKeyToRemote();
foreach ($fieldValue as $i => $aLnkValues) {
foreach ($aLnkValues as $sLnkAttCode => $sLnkValue) {
$oLnkAttDef = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $sLnkAttCode);
if ($oLnkAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$fields[$sFieldAttCode][$i][$sLnkAttCode] = '*****';
if ($sLnkAttCode == $extKeyToRemote) {
$oExtKeyAttDef = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $oAttDef->GetExtKeyToRemote());
if ($oExtKeyAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$fields[$sFieldAttCode][$i][$sLnkAttCode] = '*****';
}
}
}
}
}
// for external key
if ($oAttDef instanceof AttributeExternalKey) {
$oExtKeyAttDef = MetaModel::GetAttributeDef($oAttDef->GetTargetClass(), $oAttDef->GetCode());
$oExtKeyAttDef = MetaModel::GetAttributeDef($oAttDef->GetTargetClass(), $oAttDef->GetKeyAttCode());
if ($oExtKeyAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$fields[$sFieldAttCode] = '*****';
}
}
// for external field
if ($oAttDef instanceof AttributeExternalField) {
$oExtKeyAttDef = MetaModel::GetAttributeDef($oAttDef->GetTargetClass(), $oAttDef->GetExtAttCode());
if ($oExtKeyAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute
{
$fields[$sFieldAttCode] = '*****';

View File

@@ -1,10 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<classes>
<class id="Group">
<class id="TestServer" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>bizmodel</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>test_server</db_table>
<db_key_field>id</db_key_field>
</properties> <presentation></presentation>
<methods></methods>
<fields>
<field id="encrypted_string" xsi:type="AttributeEncryptedString" _delta="define">
<sql>encrypted_string</sql>
<field id="contact_list" xsi:type="AttributeLinkedSetIndirect">
<linked_class>lnkContactTestToServer</linked_class>
<ext_key_to_me>testserver_id</ext_key_to_me>
<ext_key_to_remote>contact_test_id</ext_key_to_remote>
<is_null_allowed>true</is_null_allowed>
</field>
<field id="password_list" xsi:type="AttributeLinkedSet">
<linked_class>PasswordTest</linked_class>
<ext_key_to_me>server_test_id</ext_key_to_me>
<is_null_allowed>true</is_null_allowed>
</field>
<field id="name" xsi:type="AttributeString">
<sql>name</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
</class>
<class id="ContactTest" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>bizmodel</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>contact_test</db_table>
<db_key_field>id</db_key_field>
</properties>
<presentation></presentation>
<methods></methods>
<fields>
<field id="password" xsi:type="AttributeEncryptedString">
<sql>password</sql>
</field>
</fields>
</class>
<class id="lnkContactTestToServer" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>bizmodel</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>lnk_contact_server_test</db_table>
<db_key_field>id</db_key_field>
</properties> <presentation></presentation>
<methods></methods>
<fields>
<field id="contact_test_password" xsi:type="AttributeExternalField" _delta="define">
<extkey_attcode>contact_test_id</extkey_attcode>
<target_attcode>password</target_attcode>
</field>
<field id="testserver_id" xsi:type="AttributeExternalKey" _delta="define">
<target_class>TestServer</target_class>
<on_target_delete>DEL_MANUAL</on_target_delete>
<sql>test_server</sql>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="contact_test_id" xsi:type="AttributeExternalKey" _delta="define">
<target_class>ContactTest</target_class>
<on_target_delete>DEL_MANUAL</on_target_delete>
<sql>contact_test</sql>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
</class>
<class id="PasswordTest" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>bizmodel</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>password_test</db_table>
<db_key_field>id</db_key_field>
</properties> <presentation></presentation>
<methods></methods>
<fields>
<field id="server_test_id" xsi:type="AttributeExternalKey" _delta="define">
<target_class>TestServer</target_class>
<sql>server_test_id</sql>
<on_target_delete>DEL_MANUAL</on_target_delete>
</field>
<field id="password" xsi:type="AttributeEncryptedString" _delta="define">
<sql>password</sql>
</field>
</fields>
</class>

View File

@@ -20,7 +20,8 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase;
use Group;
use MetaModel;
use PasswordTest;
/**
* @runTestsInSeparateProcesses
@@ -29,23 +30,67 @@ use Group;
*/
class RestServicesSanitizeOutputTest extends iTopCustomDatamodelTestCase
{
public function setUp(): void
public function testSanitizeJsonOutputOnSimpleAttribute()
{
parent::setUp();
}
public function testSanitizeJsonOutput()
{
$oGroup = new Group();
$oGroup->Set('encrypted_string', "123456");
// inserer en base ?
// insererer contact list ?
// requeter des champs qui ne s'affichent pas
$oContactTest = MetaModel::NewObject('ContactTest', array(
'password' => '123456'));
$oRestResultWithObject = new \RestResultWithObjects();
$oRestResultWithObject->AddObject(0, "ok", $oGroup, ['Group' => ['encrypted_string']]);
$oRestResultWithObject->AddObject(0, "ok", $oContactTest, ['ContactTest' => ['password']]);
$oRestResultWithObject->SanitizeContent();
$this->assertEquals('{"objects":{"Group::-1":{"code":0,"message":"ok","class":"Group","key":-1,"fields":{"encrypted_string":"*****"}}},"code":0,"message":null}', json_encode($oRestResultWithObject));
$this->assertEquals(
'{"objects":{"ContactTest::-1":{"code":0,"message":"ok","class":"ContactTest","key":-1,"fields":{"password":"*****"}}},"code":0,"message":null}',
json_encode($oRestResultWithObject));
}
public function testSanitizeJsonOutputAttributeExternalKeyOnNNRelation()
{
$oContactTest = $this->CreateObject('ContactTest', array(
'password' => '123456'));
$oTestServer = $this->CreateObject('TestServer', [
'name' => 'testserver',
]);
// create lnkContactTestToServer
$oLnkContactTestToServer = $this->CreateObject('lnkContactTestToServer', array(
'contact_test_id' => $oContactTest->GetKey(),
'testserver_id' => $oTestServer->GetKey()
));
$oRestResultWithObject = new \RestResultWithObjects();
$oRestResultWithObject->AddObject(0, "ok", $oLnkContactTestToServer,
['lnkContactTestToServer' => ['contact_test_password']]);
$oRestResultWithObject->SanitizeContent();
$this->assertEquals(
'{"objects":{"}',
json_encode($oRestResultWithObject));
}
public function testSanitizeJsonOutputOn1NRelation()
{
// Impossible to query the class
$oTestServer = $this->CreateObject('TestServer', [
'name' => 'my_server',
]);
$oPassword = new PasswordTest();
$oPassword->Set('password', "123456");
$oPassword->Set('server_test_id', $oTestServer->GetKey());
$oRestResultWithObject = new \RestResultWithObjects();
$oRestResultWithObject->AddObject(0, "ok", $oTestServer, ['TestServer' => ['id', 'password_list']]);
$oRestResultWithObject->SanitizeContent();
$this->assertEquals(
'{"objects":{"TestServer::-1":{"code":0,"message":"ok","class":"TestServer","key":-1,"fields":{"password_list":["*****"]}}},"code":0,"message":null}',
json_encode($oRestResultWithObject));
}
public function GetDatamodelDeltaAbsPath(): string
{