diff --git a/addons/userrights/userrightsmatrix.class.inc.php b/addons/userrights/userrightsmatrix.class.inc.php index 2198f7e54..d7e7578d7 100644 --- a/addons/userrights/userrightsmatrix.class.inc.php +++ b/addons/userrights/userrightsmatrix.class.inc.php @@ -274,6 +274,12 @@ class UserRightsMatrix extends UserRightsAddOnAPI return $oNullFilter; } + public function GetSelectFilter($oUser, $sClass) + { + $oNullFilter = new DBObjectSearch($sClass); + return $oNullFilter; + } + public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null) { if (!array_key_exists($iActionCode, self::$m_aActionCodes)) diff --git a/addons/userrights/userrightsnull.class.inc.php b/addons/userrights/userrightsnull.class.inc.php index 495832149..44fe4e305 100644 --- a/addons/userrights/userrightsnull.class.inc.php +++ b/addons/userrights/userrightsnull.class.inc.php @@ -53,6 +53,12 @@ class UserRightsNull extends UserRightsAddOnAPI return $oNullFilter; } + public function GetSelectFilter($oUser, $sClass) + { + $oNullFilter = new DBObjectSearch($sClass); + return $oNullFilter; + } + public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null) { return UR_ALLOWED_YES; diff --git a/addons/userrights/userrightsprofile.class.inc.php b/addons/userrights/userrightsprofile.class.inc.php index 0971c27a6..3941cfb5f 100644 --- a/addons/userrights/userrightsprofile.class.inc.php +++ b/addons/userrights/userrightsprofile.class.inc.php @@ -228,7 +228,7 @@ class URP_Dimensions extends UserRightsBaseClass // Evaluate wether it is a constant or not try { - $oObjectSearch = DBObjectSearch::FromOQL($sExpression); + $oObjectSearch = DBObjectSearch::FromOQL_AllData($sExpression); $sTargetClass = $oObjectSearch->GetClass(); } @@ -366,7 +366,7 @@ class URP_ProfileProjection extends UserRightsBaseClass } } - elseif ($sExpr == '') + elseif (($sExpr == '') || ($sExpr == '')) { $aRes = null; } @@ -374,7 +374,7 @@ class URP_ProfileProjection extends UserRightsBaseClass { $sColumn = $this->Get('attribute'); // SELECT... - $oValueSetDef = new ValueSetObjects($sExpr, $sColumn); + $oValueSetDef = new ValueSetObjects($sExpr, $sColumn, array(), true /*allow all data*/); $aRes = $oValueSetDef->GetValues(array('user' => $oUser), ''); } else @@ -437,7 +437,7 @@ class URP_ClassProjection extends UserRightsBaseClass } } - elseif ($sExpr == '') + elseif (($sExpr == '') || ($sExpr == '')) { $aRes = null; } @@ -445,13 +445,9 @@ class URP_ClassProjection extends UserRightsBaseClass { $sColumn = $this->Get('attribute'); // SELECT... - $oValueSetDef = new ValueSetObjects($sExpr, $sColumn); + $oValueSetDef = new ValueSetObjects($sExpr, $sColumn, array(), true /*allow all data*/); $aRes = $oValueSetDef->GetValues(array('this' => $oObject), ''); } - elseif ($sExpr == '') - { - $aRes = null; - } else { // Constant value(s) @@ -459,6 +455,7 @@ class URP_ClassProjection extends UserRightsBaseClass } return $aRes; } + } @@ -678,28 +675,28 @@ class UserRightsProfile extends UserRightsAddOnAPI { // Could be loaded in a shared memory (?) - $oDimensionSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_Dimensions")); + $oDimensionSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_Dimensions")); $this->m_aDimensions = array(); while ($oDimension = $oDimensionSet->Fetch()) { $this->m_aDimensions[$oDimension->GetKey()] = $oDimension; } - $oClassProjSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_ClassProjection")); + $oClassProjSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_ClassProjection")); $this->m_aClassProjs = array(); while ($oClassProj = $oClassProjSet->Fetch()) { $this->m_aClassProjs[$oClassProj->Get('class')][$oClassProj->Get('dimensionid')] = $oClassProj; } - $oProfileSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_Profiles")); + $oProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_Profiles")); $this->m_aProfiles = array(); while ($oProfile = $oProfileSet->Fetch()) { $this->m_aProfiles[$oProfile->GetKey()] = $oProfile; } - $oUserProfileSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_UserProfile")); + $oUserProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_UserProfile")); $this->m_aUserProfiles = array(); $this->m_aAdmins = array(); while ($oUserProfile = $oUserProfileSet->Fetch()) @@ -711,7 +708,7 @@ class UserRightsProfile extends UserRightsAddOnAPI } } - $oProProSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_ProfileProjection")); + $oProProSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_ProfileProjection")); $this->m_aProPros = array(); while ($oProPro = $oProProSet->Fetch()) { @@ -738,6 +735,90 @@ exit; return $oNullFilter; } + public function GetSelectFilter($oUser, $sClass) + { + $aConditions = array(); + foreach ($this->m_aDimensions as $iDimension => $oDimension) + { + $oClassProj = @$this->m_aClassProjs[$sClass][$iDimension]; + if (is_null($oClassProj)) + { + // Authorize any for this dimension, then no additional criteria is required + continue; + } + + // 1 - Get class projection info + // + $oExpression = null; + $sExpr = $oClassProj->Get('value'); + if ($sExpr == '') + { + $sColumn = $oClassProj->Get('attribute'); + if (empty($sColumn)) + { + $oExpression = new FieldExpression('id', $sClass); + } + else + { + $oExpression = new FieldExpression($sColumn, $sClass); + } + } + elseif (($sExpr == '') || ($sExpr == '')) + { + // Authorize any for this dimension, then no additional criteria is required + continue; + } + elseif (strtolower(substr($sExpr, 0, 6)) == 'select') + { + throw new CoreException('Sorry, projections by the mean of OQL are not supported currently, please specify an attribute instead', array('class' => $sClass, 'expression' => $sExpr)); + } + else + { + // Constant value(s) + // unsupported + throw new CoreException('Sorry, constant projections are not supported currently, please specify an attribute instead', array('class' => $sClass, 'expression' => $sExpr)); +// $aRes = explode(';', trim($sExpr)); + } + + // 2 - Get profile projection info and use it if needed + // + $aProjections = self::GetReadableProjectionsByDim($oUser, $sClass, $oDimension); + if (is_null($aProjections)) + { + // Authorize any for this dimension, then no additional criteria is required + continue; + } + elseif (count($aProjections) == 0) + { + // Authorize none, then exit as quickly as possible + return false; + } + else + { + // Authorize the given set of values + $oListExpr = ListExpression::FromScalars($aProjections); + $oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr); + $aConditions[] = $oCondition; + } + } + + if (count($aConditions) == 0) + { + // allow all + return true; + } + else + { + $oFilter = new DBObjectSearch($sClass); + foreach($aConditions as $oCondition) + { + $oFilter->AddConditionExpression($oCondition); + } + //return true; + return $oFilter; + } + } + // This verb has been made public to allow the development of an accurate feedback for the current configuration public function GetClassActionGrant($iProfile, $sClass, $sAction) { @@ -747,7 +828,7 @@ exit; } // Get the permission for this profile/class/action - $oSearch = DBObjectSearch::FromOQL("SELECT URP_ActionGrant WHERE class = :class AND action = :action AND profileid = :profile AND permission = 'yes'"); + $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_ActionGrant WHERE class = :class AND action = :action AND profileid = :profile AND permission = 'yes'"); $oSet = new DBObjectSet($oSearch, array(), array('class'=>$sClass, 'action'=>$sAction, 'profile'=>$iProfile)); if ($oSet->Count() >= 1) { @@ -802,7 +883,7 @@ exit; // update the list of attributes with those allowed for this profile // - $oSearch = DBObjectSearch::FromOQL("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid"); + $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid"); $oSet = new DBObjectSet($oSearch, array(), array('actiongrantid' => $oGrantRecord->GetKey())); $aProfileAttributes = $oSet->GetColumnAsArray('attcode', false); if (count($aProfileAttributes) == 0) @@ -928,7 +1009,7 @@ exit; } // Get the permission for this profile/class/stimulus - $oSearch = DBObjectSearch::FromOQL("SELECT URP_StimulusGrant WHERE class = :class AND stimulus = :stimulus AND profileid = :profile AND permission = 'yes'"); + $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_StimulusGrant WHERE class = :class AND stimulus = :stimulus AND profileid = :profile AND permission = 'yes'"); $oSet = new DBObjectSet($oSearch, array(), array('class'=>$sClass, 'stimulus'=>$sStimulusCode, 'profile'=>$iProfile)); if ($oSet->Count() >= 1) { @@ -999,6 +1080,44 @@ exit; } } + // Copied from GetMatchingProfilesByDim() + // adapted to the optimized implementation of GetSelectFilter() + // Note: shares the cache m_aProPros with GetMatchingProfilesByDim() + // Returns null if any object is readable + // an array of allowed projections otherwise (could be an empty array if none is allowed) + protected function GetReadableProjectionsByDim($oUser, $sClass, $oDimension) + { + // + // Given a dimension, lists the values for which the user will be allowed to read the objects + // + $iUser = $oUser->GetKey(); + $iDimension = $oDimension->GetKey(); + + $aRes = array(); + if (array_key_exists($iUser, $this->m_aUserProfiles)) + { + foreach ($this->m_aUserProfiles[$iUser] as $iProfile => $oProfile) + { + // user projection to be cached on a given page ! + if (!array_key_exists($iDimension, $this->m_aProPros[$iProfile])) + { + // No projection for a given profile: default to 'any' + return null; + } + + $aUserProjection = $this->m_aProPros[$iProfile][$iDimension]->ProjectUser($oUser); + if (is_null($aUserProjection)) + { + // No projection for a given profile: default to 'any' + return null; + } + $aRes = array_merge($aRes, $aUserProjection); + } + } + return $aRes; + } + + // Note: shares the cache m_aProPros with GetReadableProjectionsByDim() protected function GetMatchingProfilesByDim($oUser, $oObject, $oDimension) { // @@ -1245,7 +1364,7 @@ class SetupProfiles // Project in every dimension // - $oDimensionSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_Dimensions")); + $oDimensionSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_Dimensions")); while ($oDimension = $oDimensionSet->Fetch()) { $iDimension = $oDimension->GetKey(); @@ -1393,7 +1512,7 @@ class SetupProfiles 'Problem' => MetaModel::GetClasses('problemmgmt'), 'Change' => MetaModel::GetClasses('changemgmt'), 'Service' => MetaModel::GetClasses('servicemgmt'), - 'Call' => MetaModel::GetClasses('callmgmt'), + 'Call' => MetaModel::GetClasses('requestmgmt'), 'KnownError' => MetaModel::GetClasses('knownerrormgmt'), ); diff --git a/application/user.preferences.class.inc.php b/application/user.preferences.class.inc.php index cc7de9975..14a7ed1e4 100644 --- a/application/user.preferences.class.inc.php +++ b/application/user.preferences.class.inc.php @@ -143,7 +143,7 @@ class appUserPreferences extends DBObject { $aParams = array ( - "category" => "gui", + "category" => "gui,alwaysreadable", "key_type" => "autoincrement", "name_attcode" => "userid", "state_attcode" => "", diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index 9ea745129..68cc4230b 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -34,6 +34,10 @@ class DBObjectSearch private $m_aReferencedBy; private $m_aRelatedTo; + // By default, some information may be hidden to the current user + // But it may happen that we need to disable that feature + private $m_bAllowAllData = false; + public function __construct($sClass, $sClassAlias = null) { if (is_null($sClassAlias)) $sClassAlias = $sClass; @@ -51,6 +55,9 @@ class DBObjectSearch $this->m_aRelatedTo = array(); } + public function AllowAllData() {$this->m_bAllowAllData = true;} + public function IsAllDataAllowed() {return $this->m_bAllowAllData;} + public function GetClassName($sAlias) {return $this->m_aClasses[$sAlias];} public function GetJoinedClasses() {return $this->m_aClasses;} @@ -681,8 +688,25 @@ class DBObjectSearch } } + // Create a search definition that leads to 0 result, still a valid search object + static public function FromEmptySet($sClass) + { + $oResultFilter = new DBObjectSearch($sClass); + $oResultFilter->m_oSearchCondition = new FalseExpression; + return $oResultFilter; + } + static protected $m_aOQLQueries = array(); + // Do not filter out depending on user rights + // In particular when we are currently in the process of evaluating the user rights... + static public function FromOQL_AllData($sQuery) + { + $oRes = self::FromOQL($sQuery); + $oRes->AllowAllData(); + return $oRes; + } + static public function FromOQL($sQuery) { if (empty($sQuery)) return null; diff --git a/core/expression.class.inc.php b/core/expression.class.inc.php index 2cb0f2513..dc16464f2 100644 --- a/core/expression.class.inc.php +++ b/core/expression.class.inc.php @@ -230,6 +230,19 @@ class TrueExpression extends ScalarExpression } } +class FalseExpression extends ScalarExpression +{ + public function __construct() + { + parent::__construct(0); + } + + public function IsTrue() + { + return false; + } +} + class FieldExpression extends UnaryExpression { protected $m_sParent; @@ -348,6 +361,16 @@ class ListExpression extends Expression $this->m_aExpressions = $aExpressions; } + public static function FromScalars($aScalars) + { + $aExpressions = array(); + foreach($aScalars as $value) + { + $aExpressions[] = new ScalarExpression($value); + } + return new ListExpression($aExpressions); + } + public function IsTrue() { // return true if we are certain that it will be true diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 4bf3e7234..05089c1fd 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -1509,6 +1509,27 @@ abstract class MetaModel public static function MakeSelectQuery(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array()) { + // Hide objects that are not visible to the current user + // + if (!$oFilter->IsAllDataAllowed()) + { + $oVisibleObjects = UserRights::GetSelectFilter($oFilter->GetClass()); + if ($oVisibleObjects === false) + { + // Make sure this is a valid search object, saying NO for all + $oVisibleObjects = DBObjectSearch::FromEmptySet($oFilter->GetClass()); + } + if (is_object($oVisibleObjects)) + { + $oFilter->MergeWith($oVisibleObjects); + } + else + { + // should be true at this point, meaning that no additional filtering + // is required + } + } + // Query caching // $bQueryCacheEnabled = true; diff --git a/core/userrights.class.inc.php b/core/userrights.class.inc.php index fcb39e522..7f9c60cc1 100644 --- a/core/userrights.class.inc.php +++ b/core/userrights.class.inc.php @@ -57,6 +57,8 @@ abstract class UserRightsAddOnAPI // Cf UserContext... abstract public function GetFilter($sLogin, $sClass); // returns a filter object + // Used to build select queries showing only objects visible for the given user + abstract public function GetSelectFilter($sLogin, $sClass); // returns a filter object abstract public function IsActionAllowed($oUser, $sClass, $iActionCode, /*dbObjectSet*/ $oInstanceSet = null); abstract public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, /*dbObjectSet*/ $oInstanceSet = null); @@ -494,6 +496,9 @@ class UserRights public static function GetFilter($sClass) { + // #@# to cleanup ! + return new DBObjectSearch($sClass); + if (!self::CheckLogin()) return false; if (self::IsAdministrator()) return new DBObjectSearch($sClass); @@ -506,11 +511,35 @@ class UserRights return self::$m_oAddOn->GetFilter(self::$m_oUser->GetKey(), $sClass); } + public static function GetSelectFilter($sClass) + { + // Need to load some records before the login is performed (user preferences) + if (MetaModel::HasCategory($sClass, 'alwaysreadable')) return true; + + // ne marche pas... pourquoi? + //if (!self::CheckLogin()) return false; + + if (self::IsAdministrator()) return true; + + // this module is forbidden for non admins.... BUT I NEED IT HERE TO DETERMINE USER RIGHTS + if (MetaModel::HasCategory($sClass, 'addon/userrights')) return true; + + // the rest is allowed (#@# to be improved) + if (!MetaModel::HasCategory($sClass, 'bizmodel')) return true; + + return self::$m_oAddOn->GetSelectFilter(self::$m_oUser, $sClass); + } + public static function IsActionAllowed($sClass, $iActionCode, /*dbObjectSet*/ $oInstanceSet = null, $oUser = null) { if (!self::CheckLogin()) return false; if (self::IsAdministrator($oUser)) return true; + + // #@# Temporary????? + // The read access is controlled in MetaModel::MakeSelectQuery() + if ($iActionCode == UR_ACTION_READ) return true; + // this module is forbidden for non admins if (MetaModel::HasCategory($sClass, 'addon/userrights')) return false; diff --git a/core/valuesetdef.class.inc.php b/core/valuesetdef.class.inc.php index 44f08c3e7..0b0fade6c 100644 --- a/core/valuesetdef.class.inc.php +++ b/core/valuesetdef.class.inc.php @@ -93,19 +93,28 @@ class ValueSetObjects extends ValueSetDefinition protected $m_sFilterExpr; // in OQL protected $m_sValueAttCode; protected $m_aOrderBy; + private $m_bAllowAllData; - public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array()) + public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false) { $this->m_sFilterExpr = $sFilterExp; $this->m_sValueAttCode = $sValueAttCode; $this->m_aOrderBy = $aOrderBy; + $this->m_bAllowAllData = $bAllowAllData; } protected function LoadValues($aArgs) { $this->m_aValues = array(); - $oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr, $aArgs); + if ($this->m_bAllowAllData) + { + $oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr, $aArgs); + } + else + { + $oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr, $aArgs); + } if (!$oFilter) return false; $oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs); diff --git a/pages/usermanagement_profileproj.php b/pages/usermanagement_profileproj.php index ef42dd1cc..24cda4f70 100644 --- a/pages/usermanagement_profileproj.php +++ b/pages/usermanagement_profileproj.php @@ -72,7 +72,7 @@ function ComputeProjections($oPage) // Load users, and create a record per couple user/profile // $aDisplayData = array(); - $oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_Users")); + $oUserSet = new DBObjectSet(DBObjectSearch::FromOQL("User")); while ($oUser = $oUserSet->Fetch()) { $oUserProfileSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_UserProfile WHERE userid = :user->id"), array(), array('user' => $oUser)); diff --git a/pages/usermanagement_userstatus.php b/pages/usermanagement_userstatus.php index 5a175aca3..6ba64e54d 100644 --- a/pages/usermanagement_userstatus.php +++ b/pages/usermanagement_userstatus.php @@ -305,7 +305,7 @@ else $oPage->p('

If one profile says YES, then the answer is YES

'); - $oUser = MetaModel::GetObject('URP_Users', $iUser); + $oUser = MetaModel::GetObject('User', $iUser); $oPage->p('

Projections for user '.$oUser->GetName().'

'); ComputeUserProjections($oPage, $oUser); diff --git a/setup/benchmark.php b/setup/benchmark.php index 10469c605..2fc2e55c5 100644 --- a/setup/benchmark.php +++ b/setup/benchmark.php @@ -33,13 +33,16 @@ require_once('./setuppage.class.inc.php'); class BenchmarkDataCreation { + var $m_iIfByServer; + var $m_iIfByNWDevice; var $m_aRequested; var $m_aPlanned; - var $m_aCreated = array(); + var $m_aCreatedByClass = array(); + var $m_aCreatedByDesc = array(); var $m_aStatsByClass = array(); - public function __construct($iPlannedCIs, $iPlannedContacts, $iPlannedContracts) + public function __construct($iPlannedCIs = 0, $iPlannedContacts = 0, $iPlannedContracts = 0) { $this->m_aRequested = array( 'CIs' => $iPlannedCIs, @@ -47,10 +50,27 @@ class BenchmarkDataCreation 'Contracts' => $iPlannedContracts, ); + $this->m_iIfByServer = 2; + $this->m_iIfByNWDevice = 10; + + $iServers = ceil($iPlannedCIs * 9 / 10); + $iNWDevices = ceil($iPlannedCIs / 10); + $iBigTicketCIs = ceil($iPlannedCIs / 10); + $iInterfaces = $iServers * $this->m_iIfByServer + $iNWDevices * $this->m_iIfByNWDevice; + $iApplications = $iServers * 10; + $iSolutions = $iApplications; + $iProcesses = $iSolutions * 2; + $this->m_aPlanned = array( - 'Network devices' => ceil($iPlannedCIs / 2), - 'Servers' => ceil($iPlannedCIs / 2), - 'Interfaces' => 10 * $iPlannedCIs, + 'Network devices' => $iNWDevices, + 'Servers' => $iServers, + 'Big ticket: CIs' => $iBigTicketCIs, + 'Interfaces' => $iInterfaces, + 'Application SW' => 2, + 'Applications' => $iApplications, + 'Solutions' => $iSolutions, + 'Processes' => $iProcesses, + 'Contacts' => $iPlannedContacts, 'Contracts' => $iPlannedContracts, 'Incidents' => 2 * 12 * $iPlannedCIs, @@ -70,7 +90,7 @@ class BenchmarkDataCreation return $this->m_aRequested; } - protected function CreateObject($sClass, $aData, $oChange) + protected function CreateObject($sClass, $aData, $oChange, $sClassDesc = '') { $mu_t1 = MyHelpers::getmicrotime(); @@ -82,7 +102,9 @@ class BenchmarkDataCreation $iId = $oMyObject->DBInsertTrackedNoReload($oChange); - $this->m_aCreated[$sClass][] = $iId; + $sClassId = "$sClass ($sClassDesc)"; + $this->m_aCreatedByDesc[$sClassId][] = $iId; + $this->m_aCreatedByClass[$sClass][] = $iId; $mu_t2 = MyHelpers::getmicrotime(); $this->m_aStatsByClass[$sClass][] = $mu_t2 - $mu_t1; @@ -90,9 +112,10 @@ class BenchmarkDataCreation return $iId; } - protected function RandomId($sClass) + protected function RandomId($sClass, $sClassDesc = '') { - return $this->m_aCreated[$sClass][array_rand($this->m_aCreated[$sClass])]; + $sClassId = "$sClass ($sClassDesc)"; + return $this->m_aCreatedByDesc[$sClassId][array_rand($this->m_aCreatedByDesc[$sClassId])]; } static protected function FindId($sClass) @@ -121,7 +144,7 @@ class BenchmarkDataCreation protected function MakeFeedback($oP, $sClass) { - $iSample = reset($this->m_aCreated[$sClass]); + $iSample = reset($this->m_aCreatedByClass[$sClass]); $sSample = "sample"; $iDuration = number_format(array_sum($this->m_aStatsByClass[$sClass]), 3); @@ -131,13 +154,156 @@ class BenchmarkDataCreation $oP->add("
    "); $oP->add("
  • "); - $oP->add("$sClass: ".count($this->m_aCreated[$sClass])." - $sSample
    "); + $oP->add("$sClass: ".count($this->m_aStatsByClass[$sClass])." - $sSample
    "); $oP->add("Duration: $fDurationMin => $fDurationMax; Avg:$fDurationAverage; Total: $iDuration"); $oP->add("
  • "); $oP->add("
"); } - public function GoProjections(WebPage $oP, $oChange) + public function GoProjectionsOrganization(WebPage $oP, $oChange) + { + $aClasses = MetaModel::GetClasses(); + $aActions = array('Read', 'Bulk Read', 'Delete', 'Bulk Delete', 'Modify', 'Bulk Modify'); + $aStdProfiles = array(2, 3, 4, 5, 6, 7, 8, 9); + + //////////////////////////////////////// + // Dimension: Organization + // + $aData = array( + 'name' => 'organization', + 'description' => '', + 'type' => 'Organization', + ); + $iDimLocation = $this->CreateObject('URP_Dimensions', $aData, $oChange); + + //////////////////////////////////////// + // New specific profile, given access to everything + // + $aData = array( + 'name' => 'data guru', + 'description' => 'could do anything, because everything is granted', + ); + $iGuruProfile = $this->CreateObject('URP_Profiles', $aData, $oChange); + foreach($aClasses as $sClass) + { + foreach($aActions as $sAction) + { + $aData = array( + 'profileid' => $iGuruProfile, + 'class' => $sClass, + 'permission' => 'yes', + 'action' => $sAction, + ); + $this->CreateObject('URP_ActionGrant', $aData, $oChange); + } + } + $aData = array( + 'dimensionid' => $iDimLocation, + 'profileid' => $iGuruProfile, + 'value' => '', + 'attribute' => 'org_id', + ); + $this->CreateObject('URP_ProfileProjection', $aData, $oChange); + + // User login with super access rights + // + $aData = array( + 'org_id' => self::FindId('Organization'), + 'location_id' => self::FindId('Location'), + 'first_name' => 'Jesus', + 'name' => 'Deus', + 'email' => '', + ); + $iPerson = $this->CreateObject('Person', $aData, $oChange); + $aData = array( + 'contactid' => $iPerson, + 'login' => 'guru', + 'password' => 'guru', + 'language' => 'EN US', + ); + $iLogin = $this->CreateObject('UserLocal', $aData, $oChange); + + // Assign profiles to the new login + // + $aData = array( + 'userid' => $iLogin, + 'profileid' => $iGuruProfile, + 'reason' => 'he is the one', + ); + $this->CreateObject('URP_UserProfile', $aData, $oChange); + + //////////////////////////////////////// + // User login having all profiles, but seeing only his organization + // + $aData = array( + 'org_id' => self::FindId('Organization'), + 'location_id' => self::FindId('Location'), + 'first_name' => 'Little ze', + 'name' => 'Foo', + 'email' => '', + ); + $iPerson = $this->CreateObject('Person', $aData, $oChange); + $aData = array( + 'contactid' => $iPerson, + 'login' => 'foo', + 'password' => 'foo', + 'language' => 'EN US', + ); + $iLogin = $this->CreateObject('UserLocal', $aData, $oChange); + + // Assign profiles to the new login + // + foreach($aStdProfiles as $iProfileId) + { + $aData = array( + 'userid' => $iLogin, + 'profileid' => $iProfileId, + 'reason' => '', + ); + $this->CreateObject('URP_UserProfile', $aData, $oChange); + } + + // Project classes + // + $aMyClassesToProject = array(); + foreach($aClasses as $sClass) + { + if (MetaModel::IsValidAttCode($sClass, 'org_id')) + { + $aMyClassesToProject[$sClass] = 'org_id'; + } + } + foreach($aMyClassesToProject as $sClass => $sAttCode) + { + $aData = array( + 'dimensionid' => $iDimLocation, + 'class' => $sClass, + 'value' => '', + 'attribute' => $sAttCode, + ); + $this->CreateObject('URP_ClassProjection', $aData, $oChange); + } + + // Project profiles + // + foreach($aStdProfiles as $iProfileId) + { + $aData = array( + 'dimensionid' => $iDimLocation, + 'profileid' => $iProfileId, + 'value' => 'SELECT Person WHERE id = :user->contactid', + 'attribute' => 'org_id', + ); + $this->CreateObject('URP_ProfileProjection', $aData, $oChange); + } + + $oP->p('Created projections (Cf. login "foo", pwd "foo")'); + $oP->p('* foo can do configuration management for a given customer'); + $oP->p('* guru can do everything'); + } + + // For testing purposes -Romain + public function GoProjectionsLocation(WebPage $oP, $oChange) { // User login // @@ -156,7 +322,7 @@ class BenchmarkDataCreation 'profileid' => self::FindIdFromOQL("SELECT URP_Profiles WHERE name LIKE 'Configuration Manager'"), 'reason' => '', ); - $iFoo = $this->CreateObject('URP_UserProfile', $aData, $oChange); + $this->CreateObject('URP_UserProfile', $aData, $oChange); // Dimension // @@ -178,7 +344,7 @@ class BenchmarkDataCreation 'value' => '', 'attribute' => 'location_name', ); - $iFoo = $this->CreateObject('URP_ClassProjection', $aData, $oChange); + $this->CreateObject('URP_ClassProjection', $aData, $oChange); } // Project profiles @@ -192,7 +358,7 @@ class BenchmarkDataCreation 'value' => 'Grenoble', 'attribute' => '', ); - $iFoo = $this->CreateObject('URP_ProfileProjection', $aData, $oChange); + $this->CreateObject('URP_ProfileProjection', $aData, $oChange); } $oP->p('Created projections (Cf. login "foo", pwd "foo")'); @@ -216,7 +382,7 @@ class BenchmarkDataCreation // $aData = array( 'org_id' => $iOrg, - 'name' => 'Rio', + 'name' => 'Rio de Janeiro', ); $iLoc = $this->CreateObject('Location', $aData, $oChange); $this->MakeFeedback($oP, 'Location'); @@ -247,7 +413,15 @@ class BenchmarkDataCreation 'name' => 'Ningem #'.$i, 'email' => 'foo'.$i.'@nowhere.fr', ); - $this->CreateObject('Person', $aData, $oChange); + $iPerson = $this->CreateObject('Person', $aData, $oChange); + + // Contract/Infra + // + $aData = array( + 'contact_id' => $iPerson, + 'team_id' => $this->RandomId('Team'), + ); + $this->CreateObject('lnkTeamToContact', $aData, $oChange); } $this->MakeFeedback($oP, 'Person'); @@ -287,6 +461,19 @@ class BenchmarkDataCreation 'support_team_id' => $this->RandomId('Team'), ); $iContract = $this->CreateObject('CustomerContract', $aData, $oChange); + + // Contract/Contact (10% of contacts) + // + $iContactCount = ceil($this->m_aPlanned['Contracts'] / 10); + for($iLinked = 0 ; $iLinked < $iContactCount ; $iLinked++) + { + $aData = array( + 'contact_id' => $this->RandomId('Person'), + 'contract_id' => $iContract, + 'role' => 'role '.$iLinked, + ); + $this->CreateObject('lnkContractToContact', $aData, $oChange); + } } $this->MakeFeedback($oP, 'CustomerContract'); @@ -300,6 +487,7 @@ class BenchmarkDataCreation 'org_id' => $iOrg, 'location_id' => $iLoc, 'name' => 'server'.$i, + 'status' => 'production', ); $iServer = $this->CreateObject('Server', $aData, $oChange); @@ -317,16 +505,16 @@ class BenchmarkDataCreation // Interfaces // - $iInterfaceCount = 5; // See how aPlanned['Interfaces'] is computed - for($iLinked = 0 ; $iLinked < $iInterfaceCount ; $iLinked++) + for($iLinked = 0 ; $iLinked < $this->m_iIfByServer ; $iLinked++) { $aData = array( 'name' => "eth$iLinked", 'status' => 'implementation', 'org_id' => $iOrg, 'device_id' => $iServer, + 'status' => 'production', ); - $this->CreateObject('NetworkInterface', $aData, $oChange); + $this->CreateObject('NetworkInterface', $aData, $oChange, 'server if'); } } $this->MakeFeedback($oP, 'Server'); @@ -340,7 +528,8 @@ class BenchmarkDataCreation $aData = array( 'org_id' => $iOrg, 'location_id' => $iLoc, - 'name' => 'server'.$i, + 'name' => 'equipment #'.$i, + 'status' => 'production', ); $iNWDevice = $this->CreateObject('NetworkDevice', $aData, $oChange); @@ -358,21 +547,118 @@ class BenchmarkDataCreation // Interfaces // - $iInterfaceCount = 5; // See how aPlanned['Interfaces'] is computed - for($iLinked = 0 ; $iLinked < $iInterfaceCount ; $iLinked++) + for($iLinked = 0 ; $iLinked < $this->m_iIfByNWDevice ; $iLinked++) { $aData = array( 'name' => "eth$iLinked", 'status' => 'implementation', 'org_id' => $iOrg, 'device_id' => $iNWDevice, + 'connected_if' => $this->RandomId('NetworkInterface', 'server if'), + 'status' => 'production', ); - $this->CreateObject('NetworkInterface', $aData, $oChange); + $this->CreateObject('NetworkInterface', $aData, $oChange, 'equipment if'); } } $this->MakeFeedback($oP, 'NetworkDevice'); $this->MakeFeedback($oP, 'NetworkInterface'); + ///////////////////////// + // + // Application Software + // + for($i = 0 ; $i < $this->m_aPlanned['Application SW'] ; $i++) + { + $aData = array( + 'name' => 'Software #'.$i, + ); + $iNWDevice = $this->CreateObject('Application', $aData, $oChange); + } + $this->MakeFeedback($oP, 'Application'); + + ///////////////////////// + // + // Applications + // + for($i = 0 ; $i < $this->m_aPlanned['Applications'] ; $i++) + { + $aData = array( + 'org_id' => $iOrg, + 'device_id' => $this->RandomId('Server'), + 'software_id' => $this->RandomId('Application'), + 'name' => 'Application #'.$i, + 'status' => 'production', + ); + $iNWDevice = $this->CreateObject('ApplicationInstance', $aData, $oChange); + + // Contract/Infra + // + $iContractCount = 1; + for($iLinked = 0 ; $iLinked < $iContractCount ; $iLinked++) + { + $aData = array( + 'contract_id' => $this->RandomId('CustomerContract'), + 'ci_id' => $iNWDevice, + ); + $this->CreateObject('lnkContractToCI', $aData, $oChange); + } + } + $this->MakeFeedback($oP, 'ApplicationInstance'); + + ///////////////////////// + // + // Application Solution + // + for($i = 0 ; $i < $this->m_aPlanned['Solutions'] ; $i++) + { + $aData = array( + 'org_id' => $iOrg, + 'name' => 'Solution #'.$i, + 'status' => 'production', + ); + $iNWDevice = $this->CreateObject('ApplicationSolution', $aData, $oChange); + + // Contract/Infra + // + $iContractCount = 1; + for($iLinked = 0 ; $iLinked < $iContractCount ; $iLinked++) + { + $aData = array( + 'contract_id' => $this->RandomId('CustomerContract'), + 'ci_id' => $iNWDevice, + ); + $this->CreateObject('lnkContractToCI', $aData, $oChange); + } + } + $this->MakeFeedback($oP, 'ApplicationSolution'); + + ///////////////////////// + // + // Business Process + // + for($i = 0 ; $i < $this->m_aPlanned['Processes'] ; $i++) + { + $aData = array( + 'org_id' => $iOrg, + 'name' => 'Process #'.$i, + 'status' => 'production', + ); + $iNWDevice = $this->CreateObject('BusinessProcess', $aData, $oChange); + + // Contract/Infra + // + $iContractCount = 1; + for($iLinked = 0 ; $iLinked < $iContractCount ; $iLinked++) + { + $aData = array( + 'contract_id' => $this->RandomId('CustomerContract'), + 'ci_id' => $iNWDevice, + ); + $this->CreateObject('lnkContractToCI', $aData, $oChange); + } + } + $this->MakeFeedback($oP, 'BusinessProcess'); + ///////////////////////// // // Incident Tickets @@ -418,6 +704,47 @@ class BenchmarkDataCreation } $this->MakeFeedback($oP, 'Incident'); + ///////////////////////// + // + // Big Ticket + // + $aData = array( + 'org_id' => $iOrg, + 'caller_id' => $this->RandomId('Person'), + 'workgroup_id' => $this->RandomId('Team'), + 'agent_id' => $this->RandomId('Person'), + 'service_id' => $this->RandomId('Service'), + 'servicesubcategory_id' => $this->RandomId('ServiceSubcategory'), + 'title' => 'Big ticket', + 'ticket_log' => 'Testing...', + ); + $iTicket = $this->CreateObject('Incident', $aData, $oChange); + + // Incident/Infra + // + $iInfraCount = $this->m_aPlanned['Big ticket: CIs']; + for($iLinked = 0 ; $iLinked < $iInfraCount ; $iLinked++) + { + $aData = array( + 'ci_id' => $this->RandomId('Server'), + 'ticket_id' => $iTicket, + ); + $this->CreateObject('lnkTicketToCI', $aData, $oChange); + } + + // Incident/Contact + // + $iInfraCount = rand(0, 6) ; + for($iLinked = 0 ; $iLinked < $iInfraCount ; $iLinked++) + { + $aData = array( + 'contact_id' => $this->RandomId('Person'), + 'ticket_id' => $iTicket, + 'role' => 'role '.$iLinked, + ); + $this->CreateObject('lnkTicketToContact', $aData, $oChange); + } + ///////////////////////// // // Change Tickets @@ -529,6 +856,17 @@ function DisplayStep1(SetupWebPage $oP) { $sNextOperation = 'step2'; $oP->add("

iTop benchmarking

\n"); + + $oP->add("
\n"); + $oP->add("\n"); + $oP->add("\n"); + $oP->add("
\n"); + + $oP->add("
\n"); + $oP->add("\n"); + $oP->add("\n"); + $oP->add("
\n"); + $oP->add("

Please specify the requested volumes

\n"); $oP->add("
\n"); $oP->add("
Data load configuration\n"); @@ -600,10 +938,39 @@ function DisplayStep3(SetupWebPage $oP, $oDataCreation) $oMyChange->Set("userinfo", "Administrator"); $iChangeId = $oMyChange->DBInsertNoReload(); - $oDataCreation->GoProjections($oP, $oMyChange); $oDataCreation->GoVolume($oP, $oMyChange); } +/** + * Do create a profile management context + */ +function CreateProfilesOrganization(SetupWebPage $oP, $oDataCreation) +{ +// $sNextOperation = 'step3'; + + $oMyChange = MetaModel::NewObject("CMDBChange"); + $oMyChange->Set("date", time()); + $oMyChange->Set("userinfo", "Administrator"); + $iChangeId = $oMyChange->DBInsertNoReload(); + + $oDataCreation->GoProjectionsOrganization($oP, $oMyChange); +} + +/** + * Do create the data set... could take some time to execute + */ +function CreateProfilesLocation(SetupWebPage $oP, $oDataCreation) +{ +// $sNextOperation = 'step3'; + + $oMyChange = MetaModel::NewObject("CMDBChange"); + $oMyChange->Set("date", time()); + $oMyChange->Set("userinfo", "Administrator"); + $iChangeId = $oMyChange->DBInsertNoReload(); + + $oDataCreation->GoProjectionsLocation($oP, $oMyChange); +} + /** * Main program */ @@ -620,7 +987,19 @@ try case 'step1': DisplayStep1($oP); break; - + + case 'createprofiles_organization': + $oP->no_cache(); + $oDataCreation = new BenchmarkDataCreation(); + CreateProfilesOrganization($oP, $oDataCreation); + break; + + case 'createprofiles_location': + $oP->no_cache(); + $oDataCreation = new BenchmarkDataCreation(); + CreateProfilesLocation($oP, $oDataCreation); + break; + case 'step2': $oP->no_cache(); $iPlannedCIs = Utils::ReadParam('plannedcis');