N°9614 - Add a specific route to display the icons for an EventNotificationNewsroom

This commit is contained in:
lenaick.moreira
2026-05-18 15:32:47 +02:00
parent 829857ec85
commit 50e45bfd25
3 changed files with 63 additions and 4 deletions

View File

@@ -340,13 +340,14 @@ class ormDocument
* @param string $sContentDisposition Either 'inline' or 'attachment' * @param string $sContentDisposition Either 'inline' or 'attachment'
* @param string $sSecretField The attcode of the field containing a "secret" to be provided in order to retrieve the file * @param string $sSecretField The attcode of the field containing a "secret" to be provided in order to retrieve the file
* @param string $sSecretValue The value of the secret to be compared with the value of the attribute $sSecretField * @param string $sSecretValue The value of the secret to be compared with the value of the attribute $sSecretField
* @param bool $bAllowAllData If true, no rights filtering is applied
* *
* @return void * @return void
*/ */
public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null) public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null, $bAllowAllData = false)
{ {
try { try {
$oObj = MetaModel::GetObject($sClass, $id, false, false); $oObj = MetaModel::GetObject($sClass, $id, false, $bAllowAllData);
if (!is_object($oObj)) { if (!is_object($oObj)) {
// If access to the document is not granted, check if the access to the host object is allowed // If access to the document is not granted, check if the access to the host object is allowed
$oObj = MetaModel::GetObject($sClass, $id, false, true); $oObj = MetaModel::GetObject($sClass, $id, false, true);

View File

@@ -16,6 +16,7 @@ use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary; use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock; use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
use Combodo\iTop\Application\WebPage\DownloadPage;
use Combodo\iTop\Application\WebPage\iTopWebPage; use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\JsonPage; use Combodo\iTop\Application\WebPage\JsonPage;
use Combodo\iTop\Application\WebPage\JsonPPage; use Combodo\iTop\Application\WebPage\JsonPPage;
@@ -28,6 +29,7 @@ use DBObjectSet;
use Dict; use Dict;
use EventNotificationNewsroom; use EventNotificationNewsroom;
use MetaModel; use MetaModel;
use ormDocument;
use SecurityException; use SecurityException;
use UserRights; use UserRights;
use utils; use utils;
@@ -376,9 +378,10 @@ JS
$oEventBlock->SetCSSColorClass($sReadColor); $oEventBlock->SetCSSColorClass($sReadColor);
$oEventBlock->SetSubTitle($sReadLabel); $oEventBlock->SetSubTitle($sReadLabel);
$oEventBlock->SetClassLabel(''); $oEventBlock->SetClassLabel('');
/** @var \ormDocument $oImage */
$oImage = $oEvent->Get('icon'); $oImage = $oEvent->Get('icon');
if (!$oImage->IsEmpty()) { if (!$oImage->IsEmpty()) {
$sIconUrl = $oImage->GetDisplayURL(get_class($oEvent), $iEventId, 'icon'); $sIconUrl = self::GetDisplayIconUrl($iEventId, $oImage->GetSignature());
$oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER, true); $oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER, true);
} }
@@ -542,7 +545,7 @@ $sMessage
HTML; HTML;
$sIcon = $oMessage->Get('icon') !== null ? $sIcon = $oMessage->Get('icon') !== null ?
$oMessage->Get('icon')->GetDisplayURL(EventNotificationNewsroom::class, $oMessage->GetKey(), 'icon') : $this->GetDisplayIconUrl($oMessage->GetKey(), $oMessage->Get('icon')->GetSignature()) :
Branding::GetCompactMainLogoAbsoluteUrl(); Branding::GetCompactMainLogoAbsoluteUrl();
$aMessages[] = [ $aMessages[] = [
'id' => $oMessage->GetKey(), 'id' => $oMessage->GetKey(),
@@ -689,6 +692,41 @@ HTML;
return $oPage; return $oPage;
} }
/**
* Display the icon of an EventNotificationNewsroom
* (copy of ajax.render.php?operation=display_document but with the bAllowAllData parameter set to true in order to bypass the data access restrictions since the icon is not a critical information)
* @return void
* @throws \ConfigException
* @throws \CoreException
*/
public function OperationViewIcon(): void
{
$sId = utils::ReadParam('id', '');
if (!empty($sId)) {
$oPage = new DownloadPage('');
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$iCacheSec = (int)utils::ReadParam('cache', 0);
$oPage->set_cache($iCacheSec);
// N°4129 - Prevent XSS attacks & other script executions
if (utils::GetConfig()->Get('security.disable_inline_documents_sandbox') === false) {
$oPage->add_header('Content-Security-Policy: sandbox;');
}
ormDocument::DownloadDocument(
$oPage,
EventNotificationNewsroom::class,
$sId,
'icon',
ormDocument::ENUM_CONTENT_DISPOSITION_INLINE,
bAllowAllData: true
);
$oPage->output();
}
}
/** /**
* @param string $sAction * @param string $sAction
* *
@@ -781,4 +819,9 @@ HTML;
return $aReturnData; return $aReturnData;
} }
protected function GetDisplayIconUrl(string $sId, string $sSignature): string
{
return utils::GetAbsoluteUrlAppRoot()."pages/UI.php?route=itopnewsroom.view_icon&id=$sId&s=$sSignature&cache=86400";
}
} }

View File

@@ -198,6 +198,21 @@ class ormDocumentTest extends ItopDataTestCase
$this->assertStringNotContainsString('the object does not exist or you are not allowed to view it', $sAllowedHtml, 'Unexpected error message when rights are sufficient.'); $this->assertStringNotContainsString('the object does not exist or you are not allowed to view it', $sAllowedHtml, 'Unexpected error message when rights are sufficient.');
} }
/**
* @dataProvider DownloadDocumentRightsProvider
*/
public function testAllowsDownloadingDocumentWhenBypassingRightsChecksWithAllowAllData(string $sTargetClass, string $sAttCode, string $sData, string $sFileName, ?string $sHostClass)
{
$iDeniedDocumentId = $this->CreateDownloadTargetInOrg($sTargetClass, $sAttCode, $this->iOrgDifferentFromUser, $sData, $sFileName, $sHostClass);
$oPageAllowed = new CaptureWebPage();
ormDocument::DownloadDocument($oPageAllowed, $sTargetClass, $iDeniedDocumentId, $sAttCode, ormDocument::ENUM_CONTENT_DISPOSITION_INLINE, bAllowAllData: true);
$sAllowedHtml = $oPageAllowed->GetHtml();
$this->assertStringContainsString($sData, $sAllowedHtml, 'Expected file data present when bypassing rights checks.');
$this->assertStringNotContainsString("Invalid id ($iDeniedDocumentId) for class '$sTargetClass' - the object does not exist or you are not allowed to view it", $sAllowedHtml, 'Unexpected invalid id error message when bypassing rights checks.');
}
public function DownloadDocumentRightsProvider(): array public function DownloadDocumentRightsProvider(): array
{ {
return [ return [