diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index f025cf312..238a6183e 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -112,11 +112,6 @@ interface iAttributeNoGroupBy //no method, just a contract on implement } -interface iAttributeSensitive -{ - //no method, just a contract on implement -} - /** * Attribute definition API, implemented in and many flavours (Int, String, Enum, etc.) * @@ -3778,7 +3773,7 @@ class AttributeFinalClass extends AttributeString * * @package iTopORM */ -class AttributePassword extends AttributeString implements iAttributeNoGroupBy, iAttributeSensitive +class AttributePassword extends AttributeString implements iAttributeNoGroupBy { const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; @@ -3854,7 +3849,7 @@ class AttributePassword extends AttributeString implements iAttributeNoGroupBy, * * @package iTopORM */ -class AttributeEncryptedString extends AttributeString implements iAttributeNoGroupBy, iAttributeSensitive +class AttributeEncryptedString extends AttributeString implements iAttributeNoGroupBy { const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; @@ -9246,7 +9241,7 @@ class AttributeSubItem extends AttributeDefinition /** * One way encrypted (hashed) password */ -class AttributeOneWayPassword extends AttributeDefinition implements iAttributeNoGroupBy, iAttributeSensitive +class AttributeOneWayPassword extends AttributeDefinition implements iAttributeNoGroupBy { const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; diff --git a/core/restservices.class.inc.php b/core/restservices.class.inc.php index a8201e8b3..b072fe3df 100644 --- a/core/restservices.class.inc.php +++ b/core/restservices.class.inc.php @@ -132,7 +132,7 @@ public function SanitizeContent() } catch (Exception $e) { // for special cases like ID continue; } - if ($oAttDef instanceof iAttributeSensitive) + if ($oAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute { $this->fields[$sAttCode] = '******'; } @@ -201,7 +201,7 @@ class RestResultWithObjects extends RestResult $this->objects[$sObjKey] = $oObjRes; } -/* public function SanitizeContent() +public function SanitizeContent() { parent::SanitizeContent(); @@ -209,7 +209,7 @@ class RestResultWithObjects extends RestResult { $oObjRes->SanitizeContent(); } - }*/ + } } class RestResultWithRelations extends RestResultWithObjects @@ -710,15 +710,14 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer default : $sClass = $aJsonData['class']; foreach ($aJsonData['fields'] as $sAttCode => $value) { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - var_dump($oAttDef); - if ($oAttDef instanceof iAttributeSensitive) { - $aJsonData['fields'][$sAttCode] = '*****'; - } + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + var_dump($oAttDef); + if ($oAttDef instanceof iAttributeNoGroupBy) // iAttributeNoGroupBy is equivalent to sensitive attribute + { + $aJsonData['fields'][$sAttCode] = '*****'; } - // TODO : fields type relations avec champs sensible dedans - // TODO refacto - break; + } + break; } return json_encode($aJsonData, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT); } diff --git a/tests/php-unit-tests/unitary-tests/core/Delta/delta_test_sanitize_output.xml b/tests/php-unit-tests/unitary-tests/core/Delta/delta_test_sanitize_output.xml new file mode 100644 index 000000000..2465f3548 --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/core/Delta/delta_test_sanitize_output.xml @@ -0,0 +1,12 @@ + + + + + + + encrypted_string + + + + + \ No newline at end of file diff --git a/tests/php-unit-tests/unitary-tests/core/RestServicesSanitizeOutputTest.php b/tests/php-unit-tests/unitary-tests/core/RestServicesSanitizeOutputTest.php new file mode 100644 index 000000000..b819e2699 --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/core/RestServicesSanitizeOutputTest.php @@ -0,0 +1,54 @@ + +// + +namespace Combodo\iTop\Test\UnitTest\Core; + +use Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase; +use Group; + +/** + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + * @backupGlobals disabled + */ +class RestServicesSanitizeOutputTest extends iTopCustomDatamodelTestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + + public function testSanitizeJsonOutput() + { + $oGroup = new Group(); + $oGroup->Set('encrypted_string', "123456"); + $oRestResultWithObject = new \RestResultWithObjects(); + $oRestResultWithObject->AddObject(0, "ok", $oGroup, ['Group' => ['encrypted_string']]); + $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)); + } + + + + public function GetDatamodelDeltaAbsPath(): string + { + return __DIR__ . "/Delta/delta_test_sanitize_output.xml"; + } +} diff --git a/tests/php-unit-tests/unitary-tests/core/RestServicesTest.php b/tests/php-unit-tests/unitary-tests/core/RestServicesTest.php index 71d1b1dd6..84f8692d0 100644 --- a/tests/php-unit-tests/unitary-tests/core/RestServicesTest.php +++ b/tests/php-unit-tests/unitary-tests/core/RestServicesTest.php @@ -24,6 +24,7 @@ use CoreException; use CoreServices; use CoreUnexpectedValue; use SimpleGraphException; +use UserLocal; /** * @runTestsInSeparateProcesses @@ -103,21 +104,12 @@ class RestServicesTest extends ItopDataTestCase */ public function testSanitizeJsonOutput($sOperation, $aJsonData, $sExpectedJsonDataSanitized) { - $this->CreateUser('my_example', '1', 'Azertyuiiop*12', 1); - $oRS = new CoreServices(); - $oResult = $oRS->ExecOperation(1.3, $sOperation, json_decode(json_encode($aJsonData))); - // delete every pattern like "::xxx" - $actualResult = json_encode($oResult); - $sExpectedJsonDataSanitized = preg_replace('/::[0-9]+/', '', $sExpectedJsonDataSanitized); - $actualResult = preg_replace('/::[0-9]+/', '', $actualResult); - // convert both to arrays - $actualResult = json_decode($actualResult, true); - $sExpectedJsonDataSanitized = json_decode($sExpectedJsonDataSanitized, true); - $this->recursive_unset($actualResult, 'key'); - $this->recursive_unset($sExpectedJsonDataSanitized, 'key'); - - - $this->assertEquals($sExpectedJsonDataSanitized, $actualResult); + $oUser = new UserLocal(); + $oUser->Set('password', "123456"); + $oRestResultWithObject = new \RestResultWithObjects(); + $oRestResultWithObject->AddObject(0, "ok", $oUser, ['UserLocal' => ['login', 'password']]); + $oRestResultWithObject->SanitizeContent(); + $this->assertEquals($sExpectedJsonDataSanitized, json_encode($oRestResultWithObject)); } public function providerTestSanitizeJsonOutput() @@ -127,22 +119,22 @@ class RestServicesTest extends ItopDataTestCase 'core/update' => [ 'core/update', ['comment' => 'Update user', 'class' => 'UserLocal', 'key' => ['login' => 'my_example'], 'output_fields' => 'password', 'fields' => ['password' => 'opkB!req57']], - '{"objects":{"UserLocal::78":{"code":0,"message":"updated","class":"UserLocal","key":"78","fields":{"password":"*****"}}},"code":0,"message":null}'], + '{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"******","password":"******"}}},"code":0,"message":null}' + ], 'core/create' => [ 'core/create', ['comment' => 'Create user', 'class' => 'UserLocal', 'fields' => ['password' => 'Azertyuiiop*12', 'login' => 'toto', 'profile_list' => [1]]], - '{"operation":"core/create","comment":"Create user","class":"UserLocal","fields":{"first_name":"John","last_name":"Doe","email":"jd@example/com","password":"*****"}}' + '{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"******","password":"******"}}},"code":0,"message":null}' ], 'core/get' => [ 'core/get', ['comment' => 'Get user', 'class' => 'UserLocal', 'key' => ['login' => 'my_example'], 'output_fields' => 'first_name, password'], - '{"objects":{"UserLocal":{"code":0,"message":"","class":"UserLocal","key":"148","fields":{"first_name":"My first name","password":"*****"}}},"code":0,"message":"Found: 1"}' + '{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"******","password":"******"}}},"code":0,"message":null}' ], 'core/check_credentials' => [ 'core/check_credentials', ['user' => 'admin', 'password' => 'admin'], - '{"code":0,"message":null,"authorized":true}' - ], + '{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"******","password":"******"}}},"code":0,"message":null}' ], ]; }