Compare commits

...

6 Commits

Author SHA1 Message Date
Benjamin DALSASS
bb31415dd3 Merge remote-tracking branch 'origin/support/3.3' into develop 2026-11-02 11:17:36 +01:00
Benjamin DALSASS
fb55aa442e Merge remote-tracking branch 'origin/support/3.2' into support/3.3
# Conflicts:
#	tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
2026-11-02 11:17:01 +01:00
Benjamin DALSASS
c63f3e650d N°9392 - wizard helper linkset data validation improvement (#1100)
- fix cs fixer
2026-11-02 11:08:06 +01:00
Benjamin Dalsass
c5a4433d0e N°9392 - wizard helper linkset data validation improvement (#1100) 2026-11-02 10:46:24 +01:00
Benjamin DALSASS
d8b9533697 N°9556 - backup restore improvement
- CI fix
2026-11-02 10:39:59 +01:00
odain
cd469d401c Cherry-pick from 51f0eea8: enhance test sdk: add GetTemporaryFilePath
# Conflicts:
#	tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
2026-10-30 18:16:53 +01:00
3 changed files with 129 additions and 58 deletions

View File

@@ -35,10 +35,14 @@ class WizardHelper
public function __construct()
{
}
/**
* Constructs the PHP target object from the parameters sent to the web page by the wizard
*
* @param boolean $bReadUploadedFiles True to also read any uploaded file (for blob/document fields)
*
* @return object
* @throws CoreException
*/
public function GetTargetObject($bReadUploadedFiles = false)
{
@@ -57,7 +61,14 @@ class WizardHelper
// assumes this is handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
if (!is_array($value)) {
$aData = json_decode($value, true); // true means decode as a hash array (not an object)
try {
$aData = json_decode($value, associative: true, flags: JSON_THROW_ON_ERROR); // true means decode as a hash array (not an object)
} catch (JsonException $e) {
throw new CoreException('WizardHelper GetTargetObject: invalid data for linked set attribute '.$sAttCode.' of class '.$this->m_aData['m_sClass'], [
'att_code' => $sAttCode,
'linked_class' => $this->m_aData['m_sClass'],
], 'Invalid JSON data', $e);
}
} else {
$aData = $value;
}
@@ -66,9 +77,6 @@ class WizardHelper
$aFields = $this->GetLinkedWizardStructure($oAttDef);
$sLinkedClass = $oAttDef->GetLinkedClass();
$aLinkedObjectsArray = [];
if (!is_array($aData)) {
echo("aData: '$aData' (value: '$value')\n");
}
foreach ($aData as $aLinkedObject) {
$oLinkedObj = MetaModel::NewObject($sLinkedClass);
foreach ($aFields as $sLinkedAttCode) {

View File

@@ -0,0 +1,44 @@
<?php
/**
* Copyright (C) 2018 Dennis Lassiter
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Combodo\iTop\Test\UnitTest\Application;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use WizardHelper;
use CoreException;
/**
* @covers WizardHelper
*/
class wizardHelperTest extends ItopDataTestCase
{
public function testGetTargetObjectWithInvalidLinkSetDataValue()
{
// test case from N°9392 - [SECU] Stored XSS in subnets_list Parameter
$sWizardHelperJSON = '{"m_sClass":"VLAN","m_oFieldsMap":{"vlan_tag":"2_vlan_tag","org_id":"2_org_id","description":"2_description","subnets_list":"2_subnets_list","physicalinterfaces_list":"2_physicalinterfaces_list"},"m_oCurrentValues":{"vlan_tag":null,"org_id":null,"description":null,"subnets_list":"[]oszzt<img src=a onerror=alert(1)>l053a","physicalinterfaces_list":"[]"},"m_aDefaultValueRequested":[],"m_aAllowedValuesRequested":[],"m_oDefaultValue":{},"m_oAllowedValues":{},"m_aStaticValues":[],"m_iFieldsCount":5,"m_sFormPrefix":"","m_sState":"","m_bReturnNotEditableFields":false,"m_sWizHelperJsVarName":null}';
$this->expectException(CoreException::class);
$this->expectExceptionMessageMatches('/^WizardHelper GetTargetObject: invalid data for linked set attribute/');
$oWizardHelper = WizardHelper::FromJSON($sWizardHelperJSON);
$oWizardHelper->GetTargetObject();
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Combodo\iTop\Test\UnitTest\Module\ItopBackup;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
use UserRights;
use utils;
@@ -21,31 +22,31 @@ class BackupAjaxEndpointTest extends ItopDataTestCase
$this->AddLoginModeAndSaveConfiguration('url');
}
// public function testDownloadInvalidDownloadPathReturnsHttp500(): void
// {
// $sLogin = 'test-backup-endpoint-'.uniqid();
// $this->CreateUser($sLogin, self::$aURP_Profiles['Administrator'], self::AUTHENTICATION_PASSWORD);
//
// UserRights::Login($sLogin);
//
// $this->CallItopUri(
// 'env-production/itop-backup/ajax.backup.php?'.http_build_query([
// 'operation' => 'download',
// 'file' => 'missing-'.uniqid().'.zip',
// 'auth_user' => $sLogin,
// 'auth_pwd' => self::AUTHENTICATION_PASSWORD,
// 'transaction_id' => utils::GetNewTransactionId(),
// ]),
// [],
// [
// CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
// CURLOPT_POST => 0,
// ],
// true
// );
//
// $this->assertSame(422, $this->aLastCurlGetInfo['http_code']);
// }
public function testDownloadInvalidDownloadPathReturnsHttp500(): void
{
$sLogin = 'test-backup-endpoint-'.uniqid();
$this->CreateUser($sLogin, self::$aURP_Profiles['Administrator'], self::AUTHENTICATION_PASSWORD);
UserRights::Login($sLogin);
$sData = $this->CallItopUri(
'env-production/itop-backup/ajax.backup.php?'.http_build_query([
'operation' => 'download',
'file' => 'missing-'.uniqid().'.zip',
'auth_user' => $sLogin,
'auth_pwd' => self::AUTHENTICATION_PASSWORD,
'transaction_id' => utils::GetNewTransactionId(),
]),
[],
[
CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
CURLOPT_POST => 0,
],
true
);
$this->assertSame(422, $this->aLastCurlGetInfo['http_code'], __METHOD__.':'.$sData);
}
public function testRestoreGetTokenInvalidTransactionIdReturnsHttp500(): void
{
@@ -54,7 +55,7 @@ class BackupAjaxEndpointTest extends ItopDataTestCase
UserRights::Login($sLogin);
$this->CallItopUri(
$sData = $this->CallItopUri(
'env-production/itop-backup/ajax.backup.php?'.http_build_query([
'operation' => 'restore_get_token',
'auth_user' => $sLogin,
@@ -69,34 +70,52 @@ class BackupAjaxEndpointTest extends ItopDataTestCase
true
);
$this->assertSame(500, $this->aLastCurlGetInfo['http_code']);
$this->assertSame(500, $this->aLastCurlGetInfo['http_code'], __METHOD__.':'.$sData);
}
// public function testRestoreGetToken(): void
// {
// $sLogin = 'test-backup-endpoint-'.uniqid();
// $this->CreateUser($sLogin, self::$aURP_Profiles['Administrator'], self::AUTHENTICATION_PASSWORD);
//
// UserRights::Login($sLogin);
//
// $sData = $this->CallItopUri(
// 'env-production/itop-backup/ajax.backup.php?'.http_build_query([
// 'operation' => 'restore_get_token',
// 'auth_user' => $sLogin,
// 'auth_pwd' => self::AUTHENTICATION_PASSWORD,
// 'transaction_id' => utils::GetNewTransactionId(),
// ]),
// [],
// [
// CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
// CURLOPT_POST => 0,
// ],
// true
// );
//
// $aData = json_decode($sData, true);
//
// $this->assertSame(200, $this->aLastCurlGetInfo['http_code']);
// $this->assertArrayHasKey('token', $aData);
// }
public function testRestoreGetToken(): void
{
$sLogin = 'test-backup-endpoint-'.uniqid();
$this->CreateUser($sLogin, self::$aURP_Profiles['Administrator'], self::AUTHENTICATION_PASSWORD);
UserRights::Login($sLogin);
$sBackupDirectory = APPROOT.'data/backups/';
if (!is_dir($sBackupDirectory)) {
$this->assertTrue(mkdir($sBackupDirectory, 0770, true) || is_dir($sBackupDirectory));
}
$sBackupFile = 'backup-'.uniqid().'.zip';
$sBackupPath = $sBackupDirectory.$sBackupFile;
$oArchive = new \ZipArchive();
$bArchiveOpen = $oArchive->open($sBackupPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
$this->assertTrue($bArchiveOpen);
$this->assertTrue($oArchive->addFromString('itop-dump.sql', '-- Test backup'));
$sConfigContents = file_get_contents(MetaModel::GetConfig()->GetLoadedFile());
$this->assertNotFalse($sConfigContents);
$this->assertTrue($oArchive->addFromString('config-itop.php', $sConfigContents));
$this->assertTrue($oArchive->close());
$this->aFileToClean[] = $sBackupPath;
$sData = $this->CallItopUri(
'env-production/itop-backup/ajax.backup.php?'.http_build_query([
'operation' => 'restore_get_token',
'auth_user' => $sLogin,
'auth_pwd' => self::AUTHENTICATION_PASSWORD,
'file' => $sBackupFile,
'transaction_id' => utils::GetNewTransactionId(),
]),
[],
[
CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
CURLOPT_POST => 0,
],
true
);
$aData = json_decode($sData, true);
$this->assertSame(200, $this->aLastCurlGetInfo['http_code'], __METHOD__.':'.$sData);
$this->assertArrayHasKey('token', $aData);
}
}