Compare commits

...

3 Commits

Author SHA1 Message Date
lenaick.moreira
8842c5d5c2 N°8234 - Allow display of unauthorized objects in notifications and event queries 2026-03-24 16:43:45 +01:00
Lenaick
b3223eb9b6 N°8606 - Check user permissions in search operation of ajax.render.php (#836) 2026-03-24 08:52:22 +01:00
Benjamin DALSASS
458a996c29 N°8612 - force authentication for inline image endpoints
- ajax.render dict route needs to be reached without login authentication
2026-03-23 15:50:47 +01:00
12 changed files with 78 additions and 17 deletions

View File

@@ -810,6 +810,7 @@ HTML
foreach ($aNotificationClasses as $sNotifClass) {
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev JOIN Trigger AS T ON Ev.trigger_id = T.id WHERE T.id IN (:triggers) AND Ev.object_id = :id");
$aNotifSearches[$sNotifClass]->SetInternalParams($aParams);
$aNotifSearches[$sNotifClass]->AllowAllData();
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass], []);
$iNotifsCount += $oNotifSet->Count();
}
@@ -823,6 +824,7 @@ HTML
'menu' => false,
'panel_title' => MetaModel::GetName($sNotifClass),
'panel_icon' => MetaModel::GetClassIcon($sNotifClass, false),
'display_unauthorized_objects' => true,
]);
}
}

View File

@@ -724,6 +724,10 @@ class DisplayBlock
}
}
if (!$this->m_oFilter->IsAllDataAllowed() && ($aExtraParams['display_unauthorized_objects'] ?? false) === true) {
$this->m_oFilter->AllowAllData();
}
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
$this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
}
@@ -1381,7 +1385,10 @@ JS
// Check the classes that can be read (i.e authorized) by this user...
foreach ($aClasses as $sAlias => $sClassName) {
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) {
if (
(UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) !== UR_ALLOWED_NO)
|| ($aExtraParams['display_unauthorized_objects'] ?? false) === true
) {
$aAuthorizedClasses[$sAlias] = $sClassName;
}
}

View File

@@ -1455,6 +1455,12 @@ class utils
case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT:
/** @var \DBObjectSet $param */
// Check if the user has the right to read the objects of this list, otherwise do not propose any action (eg. configure this list, export, etc.)
if (UserRights::IsActionAllowed($param->GetFilter()->GetClass(), UR_ACTION_READ, $param) !== UR_ALLOWED_YES) {
break;
}
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink(true);
$sDataTableId = is_null($sDataTableId) ? '' : $sDataTableId;

View File

@@ -234,10 +234,11 @@ abstract class Action extends cmdbAbstractObject
}
$oActionFilter = DBObjectSearch::FromOQL($sActionQueryOql, $aActionQueryParams);
$oActionFilter->AllowAllData();
$oSet = new DBObjectSet($oActionFilter, ['date' => false]);
$sPanelTitle = Dict::Format('Action:last_executions_tab_panel_title', $sActionQueryLimit);
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle]);
$oExecutionsListBlock = DataTableUIBlockFactory::MakeForResult($oPage, 'action_executions_list', $oSet, ['panel_title' => $sPanelTitle, 'display_unauthorized_objects' => true]);
$oPage->AddUiBlock($oExecutionsListBlock);
}

View File

@@ -409,7 +409,7 @@
</php_parent>
<parent>cmdbAbstractObject</parent>
<properties>
<category>core/cmdb,view_in_gui</category>
<category>core/cmdb,grant_by_profile,silo</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>priv_event_newsroom</db_table>
@@ -888,7 +888,7 @@
<!-- Generated by toolkit/export-class-to-meta.php -->
<parent>Event</parent>
<properties>
<category>core/cmdb,view_in_gui</category>
<category>core/cmdb,grant_by_profile,silo</category>
</properties>
<fields>
<field id="message" xsi:type="AttributeText"/>

View File

@@ -26,7 +26,7 @@ class Event extends DBObject implements iDisplay
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -120,7 +120,7 @@ class EventNotification extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -154,7 +154,7 @@ class EventNotificationEmail extends EventNotification
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -190,7 +190,7 @@ class EventIssue extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -284,7 +284,7 @@ class EventWebService extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -319,7 +319,7 @@ class EventRestService extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -354,7 +354,7 @@ class EventLoginUsage extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
@@ -392,7 +392,7 @@ class EventOnObject extends Event
{
$aParams =
[
"category" => "core/cmdb,view_in_gui",
"category" => "core/cmdb,grant_by_profile,silo",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",

View File

@@ -195,6 +195,11 @@
<class id="RessourceHybridAuthMenu"/>
</classes>
</group>
<group id="Event" _delta="define">
<classes>
<class id="Event"/>
</classes>
</group>
</groups>
<profiles>
<profile id="117" _delta="define">
@@ -290,6 +295,16 @@
<action id="stimulus:ev_close">allow</action>
</actions>
</group>
<group id="Event">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
<action id="action:write">allow</action>
<action id="action:bulk write">allow</action>
<action id="action:delete">allow</action>
<action id="action:bulk delete">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="3" _delta="define">

View File

@@ -34,7 +34,6 @@ try {
require_once(APPROOT.'/application/startup.inc.php');
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
LoginWebPage::DoLoginEx();
IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST);
@@ -45,6 +44,7 @@ try {
switch ($operation) {
case 'download_document':
LoginWebPage::DoLoginEx();
$id = utils::ReadParam('id', '');
$sField = utils::ReadParam('field', '');
if ($sClass == 'Attachment') {
@@ -64,6 +64,7 @@ try {
break;
case 'download_inlineimage':
LoginWebPage::DoLoginEx();
$id = utils::ReadParam('id', '');
$sSecret = utils::ReadParam('s', '');
$iCacheSec = 31556926; // One year ahead: an inline image cannot change

View File

@@ -340,8 +340,10 @@ class DataTableUIBlockFactory extends AbstractUIBlockFactory
$aClassAliases = $oSet->GetFilter()->GetSelectedClasses();
$aAuthorizedClasses = [];
foreach ($aClassAliases as $sAlias => $sClassName) {
if ((UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) &&
((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases)))) {
if (
((UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) !== UR_ALLOWED_NO) || ($aExtraParams['display_unauthorized_objects'] ?? false) === true)
&& ((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases)))
) {
$aAuthorizedClasses[$sAlias] = $sClassName;
}
}
@@ -520,6 +522,14 @@ class DataTableUIBlockFactory extends AbstractUIBlockFactory
if ($aData['checked']) {
if ($sAttCode == '_key_') {
if ($bViewLink) {
$sRenderLink = "return row['".$sClassAlias."/hyperlink'];";
if (
($aExtraParams['display_unauthorized_objects'] ?? false) === true
&& UserRights::IsActionAllowed($sClassName, UR_ACTION_READ) !== UR_ALLOWED_YES
) {
$sRenderLink = "return row['".$sClassAlias."/friendlyname'];";
}
$aColumnDefinition[] = [
'description' => $aData['label'],
'object_class' => $sClassName,
@@ -527,7 +537,7 @@ class DataTableUIBlockFactory extends AbstractUIBlockFactory
'attribute_code' => $sAttCode,
'attribute_type' => '_key_',
'attribute_label' => MetaModel::GetName($sClassName),
'render' => "return row['".$sClassAlias."/hyperlink'];",
'render' => $sRenderLink,
];
}
@@ -972,6 +982,8 @@ JS;
/** Handler to call when trying to create a new object in modal */
'creation_disallowed',
/** Don't provide the standard object creation feature */
'display_unauthorized_objects',
/** bool Display objects for which the user has no read rights */
];
}
}

View File

@@ -42,6 +42,7 @@ use RunTimeEnvironment;
use ScalarExpression;
use SetupUtils;
use UILinksWidget;
use UserRights;
use utils;
use WizardHelper;
@@ -71,6 +72,12 @@ class AjaxRenderController
$bShowObsoleteData = utils::ShowObsoleteData();
}
$oSet->SetShowObsoleteData($bShowObsoleteData);
// N°8606 : Check user permissions on the main class
if (UserRights::IsActionAllowed($oSet->GetClass(), UR_ACTION_READ, $oSet) !== UR_ALLOWED_YES) {
throw new Exception(Dict::Format('UI:Error:ReadNotAllowedOn_Class', $oSet->GetClass()));
}
$aResult["draw"] = $iDrawNumber;
$aResult["recordsTotal"] = $oSet->Count();
$aResult["recordsFiltered"] = $aResult["recordsTotal"] ;
@@ -95,6 +102,11 @@ class AjaxRenderController
continue;
}
// N°8606 : Check user permissions on the current class
if (UserRights::IsActionAllowed($sClass, UR_ACTION_READ, $oSet) !== UR_ALLOWED_YES) {
throw new Exception(Dict::Format('UI:Error:ReadNotAllowedOn_Class', $sClass));
}
foreach ($aColumnsLoad[$sAlias] as $sAttCode) {
$aObj[$sAlias."/".$sAttCode] = $aObject[$sAlias]->GetAsHTML($sAttCode);
$bExcludeRawValue = false;

View File

@@ -26,6 +26,7 @@ use CoreException;
use DBObjectSearch;
use DBObjectSet;
use Dict;
use EventNotificationNewsroom;
use MetaModel;
use SecurityException;
use UserRights;
@@ -358,6 +359,7 @@ JS
// Search for all notifications for the current user
$oSearch = DBObjectSearch::FromOQL('SELECT EventNotificationNewsroom');
$oSearch->AddCondition('contact_id', UserRights::GetContactId(), '=');
$oSearch->AllowAllData();
$oSet = new DBObjectSet($oSearch, ['read' => true, 'date' => false], []);
// Add main content block
@@ -526,6 +528,7 @@ JS
if (utils::IsNotNullOrEmptyString($iContactId)) {
$oSearch = DBObjectSearch::FromOQL('SELECT EventNotificationNewsroom WHERE contact_id = :contact_id AND read = "no"');
$oSearch->AllowAllData();
$oSet = new DBObjectSet($oSearch, [], ['contact_id' => $iContactId]);
while ($oMessage = $oSet->Fetch()) {
@@ -576,6 +579,7 @@ HTML;
if (utils::IsNotNullOrEmptyString($iContactId)) {
$oSearch = DBObjectSearch::FromOQL('SELECT EventNotificationNewsroom WHERE contact_id = :contact_id AND read = "no"');
$oSearch->AllowAllData();
$oSet = new DBObjectSet($oSearch, [], ['contact_id' => $iContactId]);
while ($oEvent = $oSet->Fetch()) {
@@ -605,7 +609,7 @@ HTML;
$sEventId = utils::ReadParam('event_id', 0);
if ($sEventId > 0) {
try {
$oEvent = MetaModel::GetObject('EventNotificationNewsroom', $sEventId);
$oEvent = MetaModel::GetObject('EventNotificationNewsroom', $sEventId, true, true);
if ($oEvent !== null && $oEvent->Get('contact_id') === UserRights::GetContactId()) {
$oEvent->Set('read', 'yes');
$oEvent->SetCurrentDate('read_date');

View File

@@ -117,6 +117,7 @@ class NotificationsRepository
protected function PrepareSearchForNotificationsByContact(int $iContactId, array $aNotificationIds = []): DBSearch
{
$oSearch = DBObjectSearch::FromOQL("SELECT EventNotificationNewsroom WHERE contact_id = :contact_id");
$oSearch->AllowAllData();
$aParams = [
"contact_id" => $iContactId,
];