#888 Security on the portal incompatible with customizations (regression introduced in 2.0.2), now requires to define PORTAL_USERREQUEST_DISPLAY_QUERY and PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY

SVN:trunk[3086]
This commit is contained in:
Romain Quetiez
2014-02-24 15:52:04 +00:00
parent d36a03bfc3
commit 5f11c97aef
5 changed files with 51 additions and 18 deletions

View File

@@ -793,24 +793,7 @@ EOF
}
}
$sOQL = "SELECT $sClass WHERE org_id = :org_id";
$oSearch = DBObjectSearch::FromOQL($sOQL);
$iUser = UserRights::GetContactId();
if ($iUser > 0 && !IsPowerUser())
{
$oSearch->AddCondition('caller_id', $iUser);
}
$oSearch->AddCondition('id', $iId);
$oContact = MetaModel::GetObject('Contact', $iUser, false); // false => Can fail
if (!is_object($oContact))
{
throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser'));
}
$oSet = new DBObjectSet($oSearch, array(), array('org_id' => $oContact->Get('org_id')));
$oObj = $oSet->Fetch();
$oObj = MetaModel::GetObject($sClass, $iId, false);
if (!is_object($oObj))
{
throw new Exception("Could not find the object $sClass/$iId");

View File

@@ -17,6 +17,8 @@
<constant id="PORTAL_USERREQUEST_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
<constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
<constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
<constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
<constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
<constant id="PORTAL_INCIDENT_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
<constant id="PORTAL_INCIDENT_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
<constant id="PORTAL_INCIDENT_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
@@ -24,6 +26,8 @@
<constant id="PORTAL_INCIDENT_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
<constant id="PORTAL_INCIDENT_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
<constant id="PORTAL_INCIDENT_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
<constant id="PORTAL_INCIDENT_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
<constant id="PORTAL_INCIDENT_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id]]></constant>
<constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
<constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
</constants>

View File

@@ -17,6 +17,8 @@
<constant id="PORTAL_TICKETS_SEARCH_CRITERIA" xsi:type="string" _delta="define"><![CDATA[ref,start_date,close_date,service_id,caller_id]]></constant>
<constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
<constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
<constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
<constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
<constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
<constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
</constants>

View File

@@ -50,6 +50,46 @@ function GetTicketClasses()
return $aClasses;
}
/**
* Helper to protect the portal against malicious usages
* Throws an exception if the current user is not allowed to view the object details
*/
function ValidateObject($oObject)
{
if (IsPowerUser())
{
$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_POWERUSER_QUERY';
}
else
{
$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_QUERY';
}
if (defined($sValidationDefine))
{
$sValidationOql = constant($sValidationDefine);
$oSearch = DBObjectSearch::FromOQL($sValidationOql);
$oSearch->AddCondition('id', $oObject->GetKey());
if ($iUser = UserRights::GetContactId())
{
$oContact = MetaModel::GetObject('Contact', $iUser);
$aArgs = $oContact->ToArgs('contact');
}
else
{
$aArgs = array();
}
$oSet = new DBObjectSet($oSearch, array(), $aArgs);
if ($oSet->Count() == 0)
{
throw new SecurityException('You are not allowed to access the object '.get_class($oObject).'::'.$oObject->GetKey());
}
}
}
/**
* Helper to get the relevant constant
*/
@@ -1249,6 +1289,7 @@ try
$oP->set_title(Dict::S('Portal:TitleDetailsFor_Request'));
DisplayMainMenu($oP);
$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
ValidateObject($oObj);
DisplayObject($oP, $oObj, $oUserOrg);
break;
@@ -1258,6 +1299,7 @@ try
if (!MetaModel::DBIsReadOnly())
{
$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
ValidateObject($oObj);
$aAttList = array(
GetConstant(get_class($oObj), 'PUBLIC_LOG'),
'user_satisfaction',

View File

@@ -41,6 +41,8 @@ PORTAL_<TICKET-CLASS>_TYPE: optional attribute to be set with the value of "requ
PORTAL_<TICKET-CLASS>_LIST_ZLIST: list of attribute displayed in the lists (opened and resolved)
PORTAL_<TICKET-CLASS>_CLOSED_ZLIST: list of attribute displayed in the list of closed tickets
PORTAL_<TICKET-CLASS>_DETAILS_ZLIST: selection and presentation of attributes in the page that shows their details
PORTAL_<TICKET-CLASS>_DISPLAY_QUERY: selection of displayable objects (use parameters contact->attcode to check things against the user/contact)
PORTAL_<TICKET-CLASS>_DISPLAY_POWERUSER_QUERY: selection of displayable objects for power users (use parameters contact->attcode to check things against the user/contact)
How to add a type of ticket (example: Incident)