mirror of
https://github.com/Combodo/iTop.git
synced 2026-09-15 10:38:20 +02:00
N°10006 - Incorrect display of audit errors in iTOP (#1037)
* N°10006 - Incorrect display of audit errors in iTOP - fix export-v2 from audit * N°10006 - Incorrect display of audit errors in iTOP - fix export-v2 from audit * N°10006 - handle no class allowed in read corner case * N°1006 - fix export-v2 with OQLRequest and without fields
This commit is contained in:
@@ -325,7 +325,7 @@ EOF
|
||||
$sQueryId = utils::ReadParam('query', null, true);
|
||||
$sFields = utils::ReadParam('fields', null, true, 'raw_data');
|
||||
if ((($sFields === null) || ($sFields === '')) && ($sQueryId === null)) {
|
||||
throw new BulkExportMissingParameterException('fields');
|
||||
$sFields = $this->GetFieldsFromQuery();
|
||||
} else {
|
||||
if (($sQueryId !== null) && ($sQueryId !== null)) {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', ['query_id' => $sQueryId]);
|
||||
@@ -336,11 +336,11 @@ EOF
|
||||
// No 'fields' parameter supplied, take the fields from the query phrasebook definition
|
||||
$sFields = trim($oQuery->Get('fields'));
|
||||
if ($sFields === '') {
|
||||
throw new BulkExportMissingParameterException('fields');
|
||||
$sFields = $this->GetFieldsFromQuery();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = '.$sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
|
||||
throw new BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = '.$sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,6 +348,39 @@ EOF
|
||||
$this->SetFields($sFields);
|
||||
}
|
||||
|
||||
public function GetFieldsFromQuery(): string
|
||||
{
|
||||
if (is_null($this->oSearch)) {
|
||||
throw new BulkExportMissingParameterException("fields");
|
||||
}
|
||||
|
||||
$aSelectedClasses = $this->oSearch->GetSelectedClasses();
|
||||
$aAuthorizedClasses = [];
|
||||
$aFields = [];
|
||||
foreach ($aSelectedClasses as $sAlias => $sClassName) {
|
||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ) == UR_ALLOWED_YES) {
|
||||
$aAuthorizedClasses[$sAlias] = $sClassName;
|
||||
}
|
||||
}
|
||||
foreach ($aAuthorizedClasses as $sAlias => $sClassName) {
|
||||
foreach (MetaModel::GetZListItems($sClassName, 'details') as $sAttCode) {
|
||||
//$oAttDef = Metamodel::GetAttributeDef($sClassName, $sAttCode);
|
||||
if (utils::IsNullOrEmptyString($sAlias)) {
|
||||
$aFields[] = "$sAttCode";
|
||||
} else {
|
||||
$aFields[] = "$sAlias.$sAttCode";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($aFields) === 0) {
|
||||
IssueLog::Error("User is not allowed to see any field for exported OQL");
|
||||
throw new BulkExportMissingParameterException("fields");
|
||||
}
|
||||
|
||||
return implode(',', $aFields);
|
||||
}
|
||||
|
||||
public function SetFields($sFields)
|
||||
{
|
||||
// Interpret (and check) the list of fields
|
||||
|
||||
184
tests/php-unit-tests/unitary-tests/webservices/ExportTest.php
Normal file
184
tests/php-unit-tests/unitary-tests/webservices/ExportTest.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Webservices;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use MetaModel;
|
||||
use QueryOQL;
|
||||
|
||||
class ExportTest extends ItopDataTestCase
|
||||
{
|
||||
public const USE_TRANSACTION = false;
|
||||
private $sPassword = "abcDEF12345##";
|
||||
private $sLogin;
|
||||
private $sPortalLogin;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
$sUid = date('dmYHis');
|
||||
$this->sLogin = "import-".$sUid;
|
||||
$this->CreateContactlessUser($this->sLogin, self::$aURP_Profiles['Administrator'], $this->sPassword);
|
||||
$this->sPortalLogin = "import-portaluser-".$sUid;
|
||||
$this->CreateContactlessUser($this->sPortalLogin, self::$aURP_Profiles['Portal user'], $this->sPassword);
|
||||
}
|
||||
|
||||
public function testExportWithExpressionAndFields()
|
||||
{
|
||||
$aParams = [
|
||||
'expression' => 'SELECT User',
|
||||
'fields' => 'login',
|
||||
'format' => 'csv',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
$sOutput = $this->performExportTesting($aParams, $this->sLogin);
|
||||
|
||||
$sExpectedHeader = <<<HEADER
|
||||
"Login"
|
||||
|
||||
HEADER;
|
||||
|
||||
$this->assertStringContainsString($sExpectedHeader, $sOutput, "Header ($sExpectedHeader)\n should be in export-v2 answer: \n$sOutput");
|
||||
$this->assertStringContainsString($this->sLogin, $sOutput, "Login ({$this->sLogin})\n should be in export-v2 answer: \n$sOutput");
|
||||
}
|
||||
|
||||
public function testExportWithExpressionAndWithoutFields()
|
||||
{
|
||||
$aParams = [
|
||||
'expression' => 'SELECT User',
|
||||
'format' => 'csv',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
$sOutput = $this->performExportTesting($aParams, $this->sLogin);
|
||||
|
||||
$sExpectedHeader = <<<HEADER
|
||||
"Person","Organization","Email","Login","Language","Status","Profiles","Allowed Organizations","log"
|
||||
|
||||
HEADER;
|
||||
|
||||
$this->assertStringContainsString($sExpectedHeader, $sOutput, "Header ($sExpectedHeader)\n should be in export-v2 answer: \n$sOutput");
|
||||
$this->assertTrue(false !== strpos($sOutput, $this->sLogin), "Login ({$this->sLogin})\n should be in export-v2 answer: \n$sOutput");
|
||||
}
|
||||
|
||||
public function testExportWithOQLRequestAndWithoutFields()
|
||||
{
|
||||
$oOuery = $this->createObject(
|
||||
QueryOQL::class,
|
||||
[
|
||||
'name' => "TestExport-".uniqid(),
|
||||
'description' => "blabla",
|
||||
"oql" => "SELECT User",
|
||||
]
|
||||
);
|
||||
|
||||
$aParams = [
|
||||
'query' => $oOuery->GetKey(),
|
||||
'format' => 'spreadsheet',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
$sOutput = $this->performExportTesting($aParams, $this->sLogin);
|
||||
|
||||
$sExpectedHeader = <<<HEADER
|
||||
<td>Person</td>
|
||||
<td>Organization</td>
|
||||
<td>Email</td>
|
||||
<td>Login</td>
|
||||
<td>Language</td>
|
||||
<td>Status</td>
|
||||
<td>Profiles</td>
|
||||
<td>Allowed Organizations</td>
|
||||
<td>log</td>
|
||||
HEADER;
|
||||
$this->assertStringContainsString("$sExpectedHeader", $sOutput, "Header ($sExpectedHeader)\n should be in export-v2 answer: \n$sOutput");
|
||||
|
||||
$this->assertStringContainsString($this->sLogin, $sOutput, "Login ({$this->sLogin})\n should be in export-v2 answer: \n$sOutput");
|
||||
}
|
||||
|
||||
public function testExportWithOqlRequestAndWithoutFieldsButNoReadRights()
|
||||
{
|
||||
$oOuery = $this->createObject(
|
||||
QueryOQL::class,
|
||||
[
|
||||
'name' => "TestExport-".uniqid(),
|
||||
'description' => "blabla",
|
||||
"oql" => "SELECT User",
|
||||
]
|
||||
);
|
||||
|
||||
$aParams = [
|
||||
'query' => $oOuery->GetKey(),
|
||||
'format' => 'csv',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
|
||||
try {
|
||||
$this->performExportTesting($aParams, $this->sPortalLogin);
|
||||
} catch (\Exception $e) {
|
||||
$this->assertStringContainsString("PHP Error (parsing, or runtime) ", $e->getMessage());
|
||||
$this->assertStringContainsString("ERROR: Missing parameter: fields", $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testExportWithOQLRequestAndFields()
|
||||
{
|
||||
$oOuery = $this->createObject(
|
||||
QueryOQL::class,
|
||||
[
|
||||
'name' => "TestExport-".uniqid(),
|
||||
'description' => "blabla",
|
||||
"fields" => "login, status",
|
||||
"oql" => "SELECT User",
|
||||
]
|
||||
);
|
||||
|
||||
$aParams = [
|
||||
'query' => $oOuery->GetKey(),
|
||||
'fields' => 'login',
|
||||
'format' => 'spreadsheet',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
$sOutput = $this->performExportTesting($aParams, $this->sLogin);
|
||||
|
||||
$sExpectedHeader = <<<HEADER
|
||||
<td>Login</td>
|
||||
HEADER;
|
||||
$this->assertStringContainsString("$sExpectedHeader", $sOutput, "Header ($sExpectedHeader)\n should be in export-v2 answer: \n$sOutput");
|
||||
|
||||
$this->assertStringContainsString($this->sLogin, $sOutput, "Login ({$this->sLogin})\n should be in export-v2 answer: \n$sOutput");
|
||||
}
|
||||
|
||||
public function testExportWithExpressionAndWithoutFieldsButNoReadRights()
|
||||
{
|
||||
$aParams = [
|
||||
'expression' => 'SELECT User',
|
||||
'format' => 'csv',
|
||||
'filename' => 'toto.csv',
|
||||
'charset' => 'UTF-8',
|
||||
];
|
||||
|
||||
try {
|
||||
$this->performExportTesting($aParams, $this->sPortalLogin);
|
||||
} catch (\Exception $e) {
|
||||
$this->assertStringContainsString("PHP Error (parsing, or runtime) ", $e->getMessage());
|
||||
$this->assertStringContainsString("ERROR: Missing parameter: fields", $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function performExportTesting(array $aParams, $sLogin, $iExpectedExitCode = 0)
|
||||
{
|
||||
$aRes = \utils::ExecITopScript('webservices/export-v2.php', $aParams, $sLogin, $this->sPassword);
|
||||
$aOutput = $aRes[1];
|
||||
$sOutput = implode("\n", $aOutput);
|
||||
$iRes = $aRes[0];
|
||||
$this->assertEquals($iExpectedExitCode, $iRes, "exit code: $iRes | $sOutput");
|
||||
return $sOutput;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user