From 38cca0c1448135c97e5324ac93fa79eda36dc6f4 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Tue, 14 Aug 2012 16:06:51 +0000 Subject: [PATCH] Profiles defined in XML (setup + runtime), beta version (stable, upgrade required) SVN:trunk[2149] --- .../userrightsprofile.class.inc.php | 437 +++---------- application/displayblock.class.inc.php | 2 +- core/dbobject.class.php | 9 + core/userrights.class.inc.php | 21 +- .../datamodel.itop-profiles-itil.xml | 576 ++++++++++++++++++ .../module.itop-profiles-itil.php | 320 +--------- setup/ajax.dataloader.php | 53 ++ setup/compiler.class.inc.php | 191 +++++- setup/modelfactory.class.inc.php | 8 + setup/modulediscovery.class.inc.php | 1 + 10 files changed, 937 insertions(+), 681 deletions(-) create mode 100644 datamodel/itop-profiles-itil/datamodel.itop-profiles-itil.xml diff --git a/addons/userrights/userrightsprofile.class.inc.php b/addons/userrights/userrightsprofile.class.inc.php index edd8693e6..6268fc516 100644 --- a/addons/userrights/userrightsprofile.class.inc.php +++ b/addons/userrights/userrightsprofile.class.inc.php @@ -47,28 +47,6 @@ class UserRightsBaseClassGUI extends cmdbAbstractObject } } -class UserRightsBaseClass extends DBObject -{ - // Whenever something changes, reload the privileges - - protected function AfterInsert() - { - UserRights::FlushPrivileges(); - } - - protected function AfterUpdate() - { - UserRights::FlushPrivileges(); - } - - protected function AfterDelete() - { - UserRights::FlushPrivileges(); - } -} - - - class URP_Profiles extends UserRightsBaseClassGUI { @@ -101,27 +79,9 @@ class URP_Profiles extends UserRightsBaseClassGUI MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form } - protected $m_bCheckReservedNames = true; - protected function DisableCheckOnReservedNames() - { - $this->m_bCheckReservedNames = false; - } - - - protected static $m_aActions = array( - UR_ACTION_READ => 'Read', - UR_ACTION_MODIFY => 'Modify', - UR_ACTION_DELETE => 'Delete', - UR_ACTION_BULK_READ => 'Bulk Read', - UR_ACTION_BULK_MODIFY => 'Bulk Modify', - UR_ACTION_BULK_DELETE => 'Bulk Delete', - ); - - protected static $m_aCacheActionGrants = null; - protected static $m_aCacheStimulusGrants = null; protected static $m_aCacheProfiles = null; - public static function DoCreateProfile($sName, $sDescription, $bReservedName = false) + public static function DoCreateProfile($sName, $sDescription) { if (is_null(self::$m_aCacheProfiles)) { @@ -142,118 +102,19 @@ class URP_Profiles extends UserRightsBaseClassGUI $oNewObj = MetaModel::NewObject("URP_Profiles"); $oNewObj->Set('name', $sName); $oNewObj->Set('description', $sDescription); - if ($bReservedName) - { - $oNewObj->DisableCheckOnReservedNames(); - } $iId = $oNewObj->DBInsertNoReload(); self::$m_aCacheProfiles[$sCacheKey] = $iId; return $iId; } - public static function DoCreateActionGrant($iProfile, $iAction, $sClass, $bPermission = true) - { - $sAction = self::$m_aActions[$iAction]; - - if (is_null(self::$m_aCacheActionGrants)) - { - self::$m_aCacheActionGrants = array(); - $oFilterAll = new DBObjectSearch('URP_ActionGrant'); - $oSet = new DBObjectSet($oFilterAll); - while ($oGrant = $oSet->Fetch()) - { - self::$m_aCacheActionGrants[$oGrant->Get('profileid').'-'.$oGrant->Get('action').'-'.$oGrant->Get('class')] = $oGrant->GetKey(); - } - } - - $sCacheKey = "$iProfile-$sAction-$sClass"; - if (isset(self::$m_aCacheActionGrants[$sCacheKey])) - { - return self::$m_aCacheActionGrants[$sCacheKey]; - } - - $oNewObj = MetaModel::NewObject("URP_ActionGrant"); - $oNewObj->Set('profileid', $iProfile); - $oNewObj->Set('permission', $bPermission ? 'yes' : 'no'); - $oNewObj->Set('class', $sClass); - $oNewObj->Set('action', $sAction); - $iId = $oNewObj->DBInsertNoReload(); - self::$m_aCacheActionGrants[$sCacheKey] = $iId; - return $iId; - } - - public static function DoCreateStimulusGrant($iProfile, $sStimulusCode, $sClass) - { - if (is_null(self::$m_aCacheStimulusGrants)) - { - self::$m_aCacheStimulusGrants = array(); - $oFilterAll = new DBObjectSearch('URP_StimulusGrant'); - $oSet = new DBObjectSet($oFilterAll); - while ($oGrant = $oSet->Fetch()) - { - self::$m_aCacheStimulusGrants[$oGrant->Get('profileid').'-'.$oGrant->Get('stimulus').'-'.$oGrant->Get('class')] = $oGrant->GetKey(); - } - } - - $sCacheKey = "$iProfile-$sStimulusCode-$sClass"; - if (isset(self::$m_aCacheStimulusGrants[$sCacheKey])) - { - return self::$m_aCacheStimulusGrants[$sCacheKey]; - } - $oNewObj = MetaModel::NewObject("URP_StimulusGrant"); - $oNewObj->Set('profileid', $iProfile); - $oNewObj->Set('permission', 'yes'); - $oNewObj->Set('class', $sClass); - $oNewObj->Set('stimulus', $sStimulusCode); - $iId = $oNewObj->DBInsertNoReload(); - self::$m_aCacheStimulusGrants[$sCacheKey] = $iId; - return $iId; - } - - /* - * Create the built-in Administrator profile with its reserved name - */ - public static function DoCreateAdminProfile() - { - self::DoCreateProfile(ADMIN_PROFILE_NAME, 'Has the rights on everything (bypassing any control)', true /* reserved name */); - } - - /* - * Overload the standard behavior to preserve reserved names - */ - public function DoCheckToWrite() - { - parent::DoCheckToWrite(); - - if ($this->m_bCheckReservedNames) - { - $aChanges = $this->ListChanges(); - if (array_key_exists('name', $aChanges)) - { - if ($this->GetOriginal('name') == ADMIN_PROFILE_NAME) - { - $this->m_aCheckIssues[] = "The name of the Administrator profile must not be changed"; - } - elseif ($this->Get('name') == ADMIN_PROFILE_NAME) - { - $this->m_aCheckIssues[] = ADMIN_PROFILE_NAME." is a reserved to the built-in Administrator profile"; - } - elseif ($this->GetOriginal('name') == PORTAL_PROFILE_NAME) - { - $this->m_aCheckIssues[] = "The name of the User Portal profile must not be changed"; - } - elseif ($this->Get('name') == PORTAL_PROFILE_NAME) - { - $this->m_aCheckIssues[] = PORTAL_PROFILE_NAME." is a reserved to the built-in User Portal profile"; - } - } - } - } - function GetGrantAsHtml($oUserRights, $sClass, $sAction) { - $iGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction); - if (!is_null($iGrant)) + $bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction); + if (is_null($bGrant)) + { + return ''.Dict::S('UI:UserManagement:ActionAllowed:No').''; + } + elseif ($bGrant) { return ''.Dict::S('UI:UserManagement:ActionAllowed:Yes').''; } @@ -284,8 +145,8 @@ class URP_Profiles extends UserRightsBaseClassGUI $aStimuli = array(); foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) { - $oGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); - if (is_object($oGrant) && ($oGrant->Get('permission') == 'yes')) + $bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); + if ($bGrant === true) { $aStimuli[] = ''.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').''; } @@ -294,12 +155,12 @@ class URP_Profiles extends UserRightsBaseClassGUI $aDisplayData[] = array( 'class' => MetaModel::GetName($sClass), - 'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Read'), - 'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Read'), - 'write' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Modify'), - 'bulkwrite' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Modify'), - 'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Delete'), - 'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Delete'), + 'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'), + 'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'br'), + 'write' => $this->GetGrantAsHtml($oUserRights, $sClass, 'w'), + 'bulkwrite' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bw'), + 'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'd'), + 'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'bd'), 'stimuli' => $sStimuli, ); } @@ -325,6 +186,30 @@ class URP_Profiles extends UserRightsBaseClassGUI $this->DoShowGrantSumary($oPage); } } + + public static function GetConstantColumns() + { + return array('name', 'description'); + } + + + // returns an array of id => array of column => php value(so-called "real value") + public static function GetConstantValues() + { + return ProfilesConfig::GetProfilesValues(); + } + + // Before deleting a profile, + // preserve DB integrity by deleting links to users + protected function OnDelete() + { + // Note: this may break the rule that says: "a user must have at least ONE profile" ! + $oLnkSet = $this->Get('user_list'); + while($oLnk = $oLnkSet->Fetch()) + { + $oLnk->DBDelete(); + } + } } @@ -410,123 +295,17 @@ class URP_UserOrg extends UserRightsBaseClassGUI } -class URP_ActionGrant extends UserRightsBaseClass -{ - public static function Init() - { - $aParams = array - ( - "category" => "addon/userrights", - "key_type" => "autoincrement", - "name_attcode" => "profileid", - "state_attcode" => "", - "reconc_keys" => array(), - "db_table" => "priv_urp_grant_actions", - "db_key_field" => "id", - "db_finalclass_field" => "", - "display_template" => "", - ); - MetaModel::Init_Params($aParams); - //MetaModel::Init_InheritAttributes(); - - // Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked) - MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name"))); - MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); - - MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); - - // Display lists - MetaModel::Init_SetZListItems('details', array('profileid', 'class', 'permission', 'action')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('class', 'permission', 'action')); // Attributes to be displayed for a list - // Search criteria - MetaModel::Init_SetZListItems('standard_search', array('profileid', 'class', 'permission', 'action')); // Criteria of the std search form - MetaModel::Init_SetZListItems('advanced_search', array('profileid', 'class', 'permission', 'action')); // Criteria of the advanced search form - } -} - - -class URP_StimulusGrant extends UserRightsBaseClass -{ - public static function Init() - { - $aParams = array - ( - "category" => "addon/userrights", - "key_type" => "autoincrement", - "name_attcode" => "profileid", - "state_attcode" => "", - "reconc_keys" => array(), - "db_table" => "priv_urp_grant_stimulus", - "db_key_field" => "id", - "db_finalclass_field" => "", - "display_template" => "", - ); - MetaModel::Init_Params($aParams); - //MetaModel::Init_InheritAttributes(); - - // Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked) - MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name"))); - MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); - - MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); - - // Display lists - MetaModel::Init_SetZListItems('details', array('profileid', 'class', 'permission', 'stimulus')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('class', 'permission', 'stimulus')); // Attributes to be displayed for a list - // Search criteria - MetaModel::Init_SetZListItems('standard_search', array('profileid', 'class', 'permission', 'stimulus')); // Criteria of the std search form - MetaModel::Init_SetZListItems('advanced_search', array('profileid', 'class', 'permission', 'stimulus')); // Criteria of the advanced search form - } -} - - -class URP_AttributeGrant extends UserRightsBaseClass -{ - public static function Init() - { - $aParams = array - ( - "category" => "addon/userrights", - "key_type" => "autoincrement", - "name_attcode" => "actiongrantid", - "state_attcode" => "", - "reconc_keys" => array(), - "db_table" => "priv_urp_grant_attributes", - "db_key_field" => "id", - "db_finalclass_field" => "", - "display_template" => "", - ); - MetaModel::Init_Params($aParams); - //MetaModel::Init_InheritAttributes(); - - MetaModel::Init_AddAttribute(new AttributeExternalKey("actiongrantid", array("targetclass"=>"URP_ActionGrant", "jointype"=> "", "allowed_values"=>null, "sql"=>"actiongrantid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); - - // Display lists - MetaModel::Init_SetZListItems('details', array('actiongrantid', 'attcode')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('attcode')); // Attributes to be displayed for a list - // Search criteria - MetaModel::Init_SetZListItems('standard_search', array('actiongrantid', 'attcode')); // Criteria of the std search form - MetaModel::Init_SetZListItems('advanced_search', array('actiongrantid', 'attcode')); // Criteria of the advanced search form - } -} - - class UserRightsProfile extends UserRightsAddOnAPI { static public $m_aActionCodes = array( - UR_ACTION_READ => 'read', - UR_ACTION_MODIFY => 'modify', - UR_ACTION_DELETE => 'delete', - UR_ACTION_BULK_READ => 'bulk read', - UR_ACTION_BULK_MODIFY => 'bulk modify', - UR_ACTION_BULK_DELETE => 'bulk delete', + UR_ACTION_READ => 'r', + UR_ACTION_MODIFY => 'w', + UR_ACTION_DELETE => 'd', + UR_ACTION_BULK_READ => 'br', + UR_ACTION_BULK_MODIFY => 'bw', + UR_ACTION_BULK_DELETE => 'bd', ); // Installation: create the very first user @@ -604,10 +383,6 @@ class UserRightsProfile extends UserRightsAddOnAPI protected $m_aUserProfiles = array(); // userid,profileid -> object protected $m_aUserOrgs = array(); // userid -> array of orgid - // Those arrays could be completed on demand (inheriting parent permissions) - protected $m_aClassActionGrants = null; // profile, class, action -> actiongrantid (or false if NO, or null/missing if undefined) - protected $m_aClassStimulusGrants = array(); // profile, class, stimulus -> permission - // Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read) protected $m_aObjectActionGrants = array(); @@ -686,32 +461,10 @@ class UserRightsProfile extends UserRightsAddOnAPI $this->m_aAdmins = array(); $this->m_aPortalUsers = array(); - // Loaded on demand (time consuming as compared to the others) - $this->m_aClassActionGrants = null; - $this->m_aClassStimulusGrants = null; - + // Cache $this->m_aObjectActionGrants = array(); } - // Separate load: this cache is much more time consuming while loading - // Thus it is loaded iif required - // Could be improved by specifying the profile id - public function LoadActionGrantCache() - { - if (!is_null($this->m_aClassActionGrants)) return; - - $oKPI = new ExecutionKPI(); - - $oFilter = DBObjectSearch::FromOQL_AllData("SELECT URP_ActionGrant AS p WHERE p.permission = 'yes'"); - $aGrants = $oFilter->ToDataArray(); - foreach($aGrants as $aGrant) - { - $this->m_aClassActionGrants[$aGrant['profileid']][$aGrant['class']][strtolower($aGrant['action'])] = $aGrant['id']; - } - - $oKPI->ComputeAndReport('Load of action grants'); - } - public function LoadCache() { if (!is_null($this->m_aProfiles)) return; @@ -731,14 +484,6 @@ class UserRightsProfile extends UserRightsAddOnAPI $this->m_aProfiles[$oProfile->GetKey()] = $oProfile; } - $this->m_aClassStimulusGrants = array(); - $oStimGrantSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_StimulusGrant")); - $this->m_aStimGrants = array(); - while ($oStimGrant = $oStimGrantSet->Fetch()) - { - $this->m_aClassStimulusGrants[$oStimGrant->Get('profileid')][$oStimGrant->Get('class')][$oStimGrant->Get('stimulus')] = $oStimGrant; - } - $oKPI->ComputeAndReport('Load of user management cache (excepted Action Grants)'); /* @@ -746,8 +491,6 @@ class UserRightsProfile extends UserRightsAddOnAPI print_r($this->m_aProfiles); print_r($this->m_aUserProfiles); print_r($this->m_aUserOrgs); - print_r($this->m_aClassActionGrants); - print_r($this->m_aClassStimulusGrants); echo "\n"; exit; */ @@ -891,29 +634,10 @@ exit; // This verb has been made public to allow the development of an accurate feedback for the current configuration public function GetProfileActionGrant($iProfile, $sClass, $sAction) { - $this->LoadActionGrantCache(); - // Note: action is forced lowercase to be more flexible (historical bug) $sAction = strtolower($sAction); - if (isset($this->m_aClassActionGrants[$iProfile][$sClass][$sAction])) - { - return $this->m_aClassActionGrants[$iProfile][$sClass][$sAction]; - } - // Recursively look for the grant record in the class hierarchy - $sParentClass = MetaModel::GetParentPersistentClass($sClass); - if (empty($sParentClass)) - { - $iGrant = null; - } - else - { - // Recursively look for the grant record in the class hierarchy - $iGrant = $this->GetProfileActionGrant($iProfile, $sParentClass, $sAction); - } - - $this->m_aClassActionGrants[$iProfile][$sClass][$sAction] = $iGrant; - return $iGrant; + return ProfilesConfig::GetProfileActionGrant($iProfile, $sClass, $sAction); } protected function GetUserActionGrant($oUser, $sClass, $iActionCode) @@ -928,39 +652,32 @@ exit; $sAction = self::$m_aActionCodes[$iActionCode]; - $iPermission = UR_ALLOWED_NO; + $bStatus = null; $aAttributes = array(); foreach($this->GetUserProfiles($iUser) as $iProfile => $oProfile) { - $iGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction); - if (is_null($iGrant) || !$iGrant) + $bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction); + if (!is_null($bGrant)) + { + if ($bGrant) { - continue; // loop to the next profile + if (is_null($bStatus)) + { + $bStatus = true; + } } else { - $iPermission = UR_ALLOWED_YES; - - // update the list of attributes with those allowed for this profile - // - $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid"); - $oSet = new DBObjectSet($oSearch, array(), array('actiongrantid' => $iGrant)); - $aProfileAttributes = $oSet->GetColumnAsArray('attcode', false); - if (count($aProfileAttributes) == 0) - { - $aAllAttributes = array_keys(MetaModel::ListAttributeDefs($sClass)); - $aAttributes = array_merge($aAttributes, $aAllAttributes); - } - else - { - $aAttributes = array_merge($aAttributes, $aProfileAttributes); - } + $bStatus = false; } } + } + + $iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO; $aRes = array( 'permission' => $iPermission, - 'attributes' => $aAttributes, +// 'attributes' => $aAttributes, ); $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes; return $aRes; @@ -1063,16 +780,7 @@ exit; // This verb has been made public to allow the development of an accurate feedback for the current configuration public function GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode) { - $this->LoadCache(); - - if (isset($this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode])) - { - return $this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode]; - } - else - { - return null; - } + return ProfilesConfig::GetProfileStimulusGrant($iProfile, $sClass, $sStimulusCode); } public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null) @@ -1083,16 +791,27 @@ exit; // Note: The object set is ignored because it was interesting to optimize for huge data sets // and acceptable to consider only the root class of the object set - $iPermission = UR_ALLOWED_NO; + $bStatus = null; foreach($this->GetUserProfiles($iUser) as $iProfile => $oProfile) { - $oGrantRecord = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode); - if (!is_null($oGrantRecord)) + $bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode); + if (!is_null($bGrant)) + { + if ($bGrant) { - // no need to fetch the record, we've requested the records having permission = 'yes' - $iPermission = UR_ALLOWED_YES; + if (is_null($bStatus)) + { + $bStatus = true; + } + } + else + { + $bStatus = false; } } + } + + $iPermission = $bStatus ? UR_ALLOWED_YES : UR_ALLOWED_NO; return $iPermission; } diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 8ad4fa3f7..5ca2fff0f 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -1179,7 +1179,7 @@ class MenuBlock extends DisplayBlock $sDefault.= "&default[$sKey]=$sValue"; } } - $bIsCreationAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES); + $bIsCreationAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_CREATE) == UR_ALLOWED_YES); switch($oSet->Count()) { case 0: diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 787b3eccf..a6d62555f 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -789,6 +789,15 @@ abstract class DBObject public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '') { $iFlags = 0; // By default (if no life cycle) no flag at all + + if (method_exists(get_class($this), 'GetConstantColumns')) + { + if (in_array($sAttCode, $this->GetConstantColumns())) + { + return OPT_ATT_READONLY; + } + } + $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this)); if (!empty($sStateAttCode)) { diff --git a/core/userrights.class.inc.php b/core/userrights.class.inc.php index d14eebdc3..8ef04d29b 100644 --- a/core/userrights.class.inc.php +++ b/core/userrights.class.inc.php @@ -41,6 +41,8 @@ define('UR_ACTION_BULK_READ', 4); // Export multiple objects define('UR_ACTION_BULK_MODIFY', 5); // Create/modify multiple objects define('UR_ACTION_BULK_DELETE', 6); // Delete multiple objects +define('UR_ACTION_CREATE', 7); // Instantiate an object + define('UR_ACTION_APPLICATION_DEFINED', 10000); // Application specific actions (CSV import, View schema...) /** @@ -671,9 +673,20 @@ class UserRights if (MetaModel::DBIsReadOnly()) { + if ($iActionCode == UR_ACTION_CREATE) return false; if ($iActionCode == UR_ACTION_MODIFY) return false; - if ($iActionCode == UR_ACTION_DELETE) return false; if ($iActionCode == UR_ACTION_BULK_MODIFY) return false; + if ($iActionCode == UR_ACTION_DELETE) return false; + if ($iActionCode == UR_ACTION_BULK_DELETE) return false; + } + + if (method_exists($sClass, 'GetConstantColumns')) + { + // As opposed to the read-only DB, modifying an object is allowed + // (the constant columns will be marked as read-only) + // + if ($iActionCode == UR_ACTION_CREATE) return false; + if ($iActionCode == UR_ACTION_DELETE) return false; if ($iActionCode == UR_ACTION_BULK_DELETE) return false; } @@ -685,6 +698,12 @@ class UserRights { $oUser = self::$m_oUser; } + if ($iActionCode == UR_ACTION_CREATE) + { + // The addons currently DO NOT handle the case "CREATE" + // Therefore it is considered to be equivalent to "MODIFY" + $iActionCode = UR_ACTION_MODIFY; + } return self::$m_oAddOn->IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet); } elseif(($iActionCode == UR_ACTION_READ) && MetaModel::HasCategory($sClass, 'view_in_gui')) diff --git a/datamodel/itop-profiles-itil/datamodel.itop-profiles-itil.xml b/datamodel/itop-profiles-itil/datamodel.itop-profiles-itil.xml new file mode 100644 index 000000000..c141707af --- /dev/null +++ b/datamodel/itop-profiles-itil/datamodel.itop-profiles-itil.xml @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configuration Manager + Person in charge of the documentation of the managed CIs + + + + allow + allow + allow + + + + + allow + allow + allow + + + + + allow + allow + allow + + + + + allow + allow + + + + + + Service Desk Agent + Person in charge of creating incident reports + + + + allow + allow + + + + + allow + allow + + + + + allow + + + + + allow + + + + + allow + + + + + allow + + + + + allow + allow + + + + + + Support Agent + Person analyzing and solving the current incidents + + + + allow + allow + + + + + allow + allow + + + + + allow + + + + + allow + + + + + allow + allow + allow + allow + + + + + allow + allow + allow + allow + allow + + + + + allow + allow + + + + + + Problem Manager + Person analyzing and solving the current problems + + + + allow + allow + + + + + allow + allow + + + + + allow + + + + + allow + + + + + allow + allow + allow + allow + + + + + allow + allow + + + + + + Change Implementor + Person executing the changes + + + + allow + allow + + + + + allow + + + + + allow + allow + allow + allow + + + + + allow + allow + allow + allow + + + + + allow + allow + allow + allow + + + + + allow + allow + + + + + + Change Supervisor + Person responsible for the overall change execution + + + + allow + allow + + + + + allow + + + + + allow + allow + allow + allow + allow + + + + + allow + allow + allow + + + + + allow + allow + allow + + + + + allow + allow + + + + + + Change Approver + Person who could be impacted by some changes + + + + allow + allow + + + + + allow + + + + + allow + allow + + + + + allow + allow + + + + + + + + allow + allow + + + + + + Service Manager + Person responsible for the service delivered to the [internal] customer + + + + allow + allow + + + + + allow + + + + + allow + allow + + + + + + Document author + Any person who could contribute to documentation + + + + allow + allow + allow + + + + + allow + + + + + allow + allow + + + + + + Portal user + Has the rights to access to the user portal. People having this profile will not be allowed to access the standard application, they will be automatically redirected to the user portal. + + + + allow + allow + + + + + allow + + + + + allow + + + + + allow + allow + + + + + + + diff --git a/datamodel/itop-profiles-itil/module.itop-profiles-itil.php b/datamodel/itop-profiles-itil/module.itop-profiles-itil.php index 4660f29f1..3f58b2f79 100644 --- a/datamodel/itop-profiles-itil/module.itop-profiles-itil.php +++ b/datamodel/itop-profiles-itil/module.itop-profiles-itil.php @@ -29,12 +29,11 @@ SetupWebPage::AddModule( ), 'mandatory' => true, 'visible' => false, - 'installer' => 'CreateITILProfilesInstaller', // Components // 'datamodel' => array( - //'model.itop-profiles-itil.php', + 'model.itop-profiles-itil.php', ), 'webservice' => array( //'webservices.itop-profiles-itil.php', @@ -59,321 +58,4 @@ SetupWebPage::AddModule( ) ); - -// Module installation handler -// -class CreateITILProfilesInstaller extends ModuleInstallerAPI -{ - public static function BeforeWritingConfig(Config $oConfiguration) - { - //$oConfiguration->SetModuleSetting('user-rigths-profile', 'myoption', 'myvalue'); - return $oConfiguration; - } - - public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) - { - self::ComputeITILProfiles(); - //self::ComputeBasicProfiles(); - $bFirstInstall = empty($sPreviousVersion); - self::DoCreateProfiles($bFirstInstall); - UserRights::FlushPrivileges(true /* reset admin cache */); - } - - // Note: It is possible to specify the same class in several modules - // - protected static $m_aModules = array(); - protected static $m_aProfiles = array(); - - protected static function DoSetupProfile($sName, $aProfileData) - { - $sDescription = $aProfileData['description']; - if (strlen(trim($aProfileData['write_modules'])) == 0) - { - $aWriteModules = array(); - } - else - { - $aWriteModules = explode(',', trim($aProfileData['write_modules'])); - } - if (strlen(trim($aProfileData['delete_modules'])) == 0) - { - $aDeleteModules = array(); - } - else - { - $aDeleteModules = explode(',', trim($aProfileData['delete_modules'])); - } - $aStimuli = $aProfileData['stimuli']; - - $iProfile = URP_Profiles::DoCreateProfile($sName, $sDescription); - - // Warning: BulkInsert is working because we will load one single class - // having one single table ! - // the benefit is: 10 queries (1 per profile) instead of 1500 - // which divides the overall user rights setup process by 5 - DBObject::BulkInsertStart(); - - // Grant read rights for everything - // - foreach (MetaModel::GetClasses('bizmodel') as $sClass) - { - URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_READ, $sClass); - URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_BULK_READ, $sClass); - } - - // Grant write for given modules - // Start by compiling the information, because some modules may overlap - $aWriteableClasses = array(); - foreach ($aWriteModules as $sModule) - { - //$oPage->p('Granting write access for the module"'.$sModule.'" - '.count(self::$m_aModules[$sModule]).' classes'); - foreach (self::$m_aModules[$sModule] as $sClass) - { - $aWriteableClasses[$sClass] = true; - } - } - foreach ($aWriteableClasses as $sClass => $foo) - { - if (!MetaModel::IsValidClass($sClass)) - { - throw new CoreException("Invalid class name '$sClass'"); - } - URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_MODIFY, $sClass); - URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_BULK_MODIFY, $sClass); - } - - // Grant delete for given modules - // Start by compiling the information, because some modules may overlap - $aDeletableClasses = array(); - foreach ($aDeleteModules as $sModule) - { - //$oPage->p('Granting delete access for the module"'.$sModule.'" - '.count(self::$m_aModules[$sModule]).' classes'); - foreach (self::$m_aModules[$sModule] as $sClass) - { - $aDeletableClasses[$sClass] = true; - } - } - foreach ($aDeletableClasses as $sClass => $foo) - { - if (!MetaModel::IsValidClass($sClass)) - { - throw new CoreException("Invalid class name '$sClass'"); - } - URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_DELETE, $sClass); - // By default, do not allow bulk deletion operations for standard users - // URP_Profiles::DoCreateActionGrant($iProfile, UR_ACTION_BULK_DELETE, $sClass); - } - - // Grant stimuli for given classes - foreach ($aStimuli as $sClass => $sAllowedStimuli) - { - if (!MetaModel::IsValidClass($sClass)) - { - // Could be a class defined in a module that wasn't installed - continue; - //throw new CoreException("Invalid class name '$sClass'"); - } - - if ($sAllowedStimuli == 'any') - { - $aAllowedStimuli = array_keys(MetaModel::EnumStimuli($sClass)); - } - elseif ($sAllowedStimuli == 'none') - { - $aAllowedStimuli = array(); - } - else - { - $aAllowedStimuli = explode(',', $sAllowedStimuli); - } - foreach ($aAllowedStimuli as $sStimulusCode) - { - URP_Profiles::DoCreateStimulusGrant($iProfile, $sStimulusCode, $sClass); - } - } - // Again: this is working only because action/stimulus grant are classes made of a single table! - DBObject::BulkInsertFlush(); - } - - /* - * Create the built-in User Portal profile with its reserved name - */ - public static function DoCreateUserPortalProfile() - { - // Do not attempt to create this profile if the module 'User Request Management' is not installed - // Note: ideally, the creation of this profile should be moved to the 'User Request Management' module - if (!MetaModel::IsValidClass('UserRequest')) return; - - $iNewId = URP_Profiles::DoCreateProfile(PORTAL_PROFILE_NAME, 'Has the rights to access to the user portal. People having this profile will not be allowed to access the standard application, they will be automatically redirected to the user portal.', true /* reserved name */); - - // Grant read rights for everything - // - foreach (MetaModel::GetClasses('bizmodel') as $sClass) - { - URP_Profiles::DoCreateActionGrant($iNewId, UR_ACTION_READ, $sClass); - URP_Profiles::DoCreateActionGrant($iNewId, UR_ACTION_BULK_READ, $sClass); - } - // Can create UserRequests and attach Documents to it - self::SafeCreateActionGrant($iNewId, UR_ACTION_MODIFY, 'UserRequest'); - self::SafeCreateActionGrant($iNewId, UR_ACTION_MODIFY, 'lnkTicketToDoc'); - self::SafeCreateActionGrant($iNewId, UR_ACTION_DELETE, 'lnkTicketToDoc'); - self::SafeCreateActionGrant($iNewId, UR_ACTION_MODIFY, 'FileDoc'); - // Can close user requests - self::SafeCreateStimulusGrant($iNewId, 'ev_close', 'UserRequest'); - } - protected static function SafeCreateActionGrant($iProfile, $iAction, $sClass, $bPermission = true) - { - if (MetaModel::IsValidClass($sClass)) URP_Profiles::DoCreateActionGrant($iProfile, $iAction, $sClass, $bPermission); - } - - protected static function SafeCreateStimulusGrant($iProfile, $sStimulusCode, $sClass) - { - if (MetaModel::IsValidClass($sClass)) URP_Profiles::DoCreateStimulusGrant($iProfile, $sStimulusCode, $sClass); - } - - public static function DoCreateProfiles($bFirstInstall = true) - { - URP_Profiles::DoCreateAdminProfile(); // Will be created only if it does not exist - self::DoCreateUserPortalProfile(); // Will be created only if it does not exist and updated otherwise - - foreach(self::$m_aProfiles as $sName => $aProfileData) - { - self::DoSetupProfile($sName, $aProfileData); - } - } - - public static function ComputeBasicProfiles() - { - // In this profiling scheme, one single module represents all the classes - // - self::$m_aModules = array( - 'UserData' => MetaModel::GetClasses('bizmodel'), - ); - - self::$m_aProfiles = array( - 'Reader' => array( - 'description' => 'Person having a ready-only access to the data', - 'write_modules' => '', - 'delete_modules' => '', - 'stimuli' => array( - ), - ), - 'Writer' => array( - 'description' => 'Contributor to the contents (read + write access)', - 'write_modules' => 'UserData', - 'delete_modules' => 'UserData', - 'stimuli' => array( - // any class => 'any' - ), - ), - ); - } - - public static function ComputeITILProfiles() - { - // In this profiling scheme, modules are based on ITIL recommendations - // - self::$m_aModules = array( - 'General' => MetaModel::GetClasses('structure'), - 'Documentation' => MetaModel::GetClasses('documentation'), - 'Configuration' => MetaModel::GetClasses('configmgmt'), - 'Incident' => MetaModel::GetClasses('incidentmgmt'), - 'Problem' => MetaModel::GetClasses('problemmgmt'), - 'Change' => MetaModel::GetClasses('changemgmt'), - 'Service' => MetaModel::GetClasses('servicemgmt'), - 'Call' => MetaModel::GetClasses('requestmgmt'), - 'KnownError' => MetaModel::GetClasses('knownerrormgmt'), - 'LnkTickets' => MetaModel::GetClasses('lnkticket'), - 'LnkIncidents' => MetaModel::GetClasses('lnkincident'), - 'LnkServices' => MetaModel::GetClasses('lnkservice'), - 'LnkKnownErrors' => MetaModel::GetClasses('lnkknownerror'), - ); - - self::$m_aProfiles = array( - 'Configuration Manager' => array( - 'description' => 'Person in charge of the documentation of the managed CIs', - 'write_modules' => 'General,Documentation,Configuration', - 'delete_modules' => 'General,Documentation,Configuration', - 'stimuli' => array( - //'Server' => 'none', - //'Contract' => 'none', - //'IncidentTicket' => 'none', - //'ChangeTicket' => 'any', - ), - ), - 'Service Desk Agent' => array( - 'description' => 'Person in charge of creating incident reports', - 'write_modules' => 'Incident,Call', - 'delete_modules' => 'LnkTickets,LnkIncidents', - 'stimuli' => array( - 'Incident' => 'ev_assign', - 'UserRequest' => 'ev_assign', - ), - ), - 'Support Agent' => array( - 'description' => 'Person analyzing and solving the current incidents', - 'write_modules' => 'Incident,Call', - 'delete_modules' => 'LnkTickets,LnkIncidents', - 'stimuli' => array( - 'Incident' => 'ev_assign,ev_reassign,ev_resolve,ev_close', - 'UserRequest' => 'ev_assign,ev_reassign,ev_resolve,ev_close,ev_freeze', - ), - ), - 'Problem Manager' => array( - 'description' => 'Person analyzing and solving the current problems', - 'write_modules' => 'Problem,KnownError', - 'delete_modules' => 'LnkTickets,LnkKnownErrors', - 'stimuli' => array( - 'Problem' => 'ev_assign,ev_reassign,ev_resolve,ev_close', - ), - ), - - 'Change Implementor' => array( - 'description' => 'Person executing the changes', - 'write_modules' => 'Change', - 'delete_modules' => 'LnkTickets', - 'stimuli' => array( - 'NormalChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor', - 'EmergencyChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor', - 'RoutineChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor', - ), - ), - 'Change Supervisor' => array( - 'description' => 'Person responsible for the overall change execution', - 'write_modules' => 'Change', - 'delete_modules' => 'LnkTickets', - 'stimuli' => array( - 'NormalChange' => 'ev_validate,ev_reject,ev_assign,ev_reopen,ev_finish', - 'EmergencyChange' => 'ev_assign,ev_reopen,ev_finish', - 'RoutineChange' => 'ev_assign,ev_reopen,ev_finish', - ), - ), - 'Change Approver' => array( - 'description' => 'Person who could be impacted by some changes', - 'write_modules' => 'Change', - 'delete_modules' => 'LnkTickets', - 'stimuli' => array( - 'NormalChange' => 'ev_approve,ev_notapprove', - 'EmergencyChange' => 'ev_approve,ev_notapprove', - 'RoutineChange' => 'none', - ), - ), - 'Service Manager' => array( - 'description' => 'Person responsible for the service delivered to the [internal] customer', - 'write_modules' => 'Service', - 'delete_modules' => 'LnkServices', - 'stimuli' => array( - ), - ), - 'Document author' => array( - 'description' => 'Any person who could contribute to documentation', - 'write_modules' => 'Documentation', - 'delete_modules' => 'Documentation,LnkTickets', - 'stimuli' => array( - ), - ), - ); - } -} - ?> diff --git a/setup/ajax.dataloader.php b/setup/ajax.dataloader.php index 360ab6812..e2260ddbe 100644 --- a/setup/ajax.dataloader.php +++ b/setup/ajax.dataloader.php @@ -280,6 +280,59 @@ try } } + // Constant classes (e.g. User profiles) + // + foreach (MetaModel::GetClasses() as $sClass) + { + if (method_exists($sClass, 'GetConstantColumns')) + { + // Temporary... until this get really encapsulated as the default and transparent behavior + $oMyChange = MetaModel::NewObject("CMDBChange"); + $oMyChange->Set("date", time()); + $sUserString = CMDBChange::GetCurrentUserName(); + $oMyChange->Set("userinfo", $sUserString); + $iChangeId = $oMyChange->DBInsert(); + + // Create/Delete/Update objects of this class, + // according to the given constant values + // + $aAttList = call_user_func(array($sClass, 'GetConstantColumns')); + $aRefValues = call_user_func(array($sClass, 'GetConstantValues')); + $aDBIds = array(); + $oAll = new DBObjectSet(new DBObjectSearch($sClass)); + while ($oObj = $oAll->Fetch()) + { + if (array_key_exists($oObj->GetKey(), $aRefValues)) + { + $aObjValues = $aRefValues[$oObj->GetKey()]; + foreach ($aAttList as $sAttCode) + { + $oObj->Set($sAttCode, $aObjValues[$sAttCode]); + } + $oObj->DBUpdateTracked($oMyChange); + $aDBIds[$oObj->GetKey()] = true; + } + else + { + $oObj->DBDeleteTracked($oMyChange); + } + } + foreach ($aRefValues as $iRefId => $aObjValues) + { + if (!array_key_exists($iRefId, $aDBIds)) + { + $oNewObj = MetaModel::NewObject($sClass); + $oNewObj->SetKey($iRefId); + foreach ($aAttList as $sAttCode) + { + $oNewObj->Set($sAttCode, $aObjValues[$sAttCode]); + } + $oNewObj->DBInsertTracked($oMyChange); + } + } + } + } + if (!$oProductionEnv->RecordInstallation($oConfig, $aSelectedModules, $sModuleDir)) { throw(new Exception("Failed to record the installation information")); diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php index 798ee059a..620a26e35 100644 --- a/setup/compiler.class.inc.php +++ b/setup/compiler.class.inc.php @@ -52,6 +52,10 @@ class MFCompiler public function Compile($sTargetDir, $oP = null) { + $aAllClasses = array(); // flat list of classes + + // Determine the target modules for the MENUS + // $aMenuNodes = array(); $aMenusByModule = array(); foreach ($this->oFactory->ListActiveChildNodes('menus', 'menu') as $oMenuNode) @@ -63,6 +67,17 @@ class MFCompiler $aMenusByModule[$sModuleMenu][] = $sMenuId; } + // Determine the target module (exactly one!) for USER RIGHTS + // + $oUserRightsNode = $this->oFactory->GetNodes('user_rights')->item(0); + if (!$oUserRightsNode) + { + throw new Exception("Missing configuration for user rights"); + } + $sUserRightsModule = $oUserRightsNode->getAttribute('_created_in'); + + // List root classes + // $this->aRootClasses = array(); foreach ($this->oFactory->ListRootClasses() as $oClass) { @@ -70,6 +85,8 @@ class MFCompiler $this->aRootClasses[$oClass->getAttribute('id')] = $oClass; } + // Compile, module by module + // $aModules = $this->oFactory->GetLoadedModules(); foreach($aModules as $foo => $oModule) { @@ -94,13 +111,14 @@ class MFCompiler { foreach($oClasses as $oClass) { + $sClass = $oClass->getAttribute("id"); + $aAllClasses[] = $sClass; try { $sCompiledCode .= $this->CompileClass($oClass, $sRelativeDir, $oP); } catch (ssDOMFormatException $e) { - $sClass = $oClass->getAttribute("id"); throw new Exception("Failed to process class '$sClass', from '$sModuleRootDir': ".$e->getMessage()); } } @@ -164,6 +182,13 @@ EOF; } } + // User rights + // + if ($sModuleName == $sUserRightsModule) + { + $sCompiledCode .= $this->CompileUserRights($oUserRightsNode); + } + // Create (overwrite if existing) the compiled file // if (strlen($sCompiledCode) > 0) @@ -968,7 +993,171 @@ EOF; } return $sPHP; + } // function CompileMenu + + protected function CompileUserRights($oUserRightsNode) + { + static $aActionsInShort = array( + 'read' => 'r', + 'bulk read' => 'br', + 'write' => 'w', + 'bulk write' => 'bw', + 'delete' => 'd', + 'bulk delete' => 'bd', + ); + + // Groups + // + $aGroupClasses = array(); + $oGroups = $oUserRightsNode->GetUniqueElement('groups'); + foreach($oGroups->getElementsByTagName('group') as $oGroup) + { + $sGroupId = $oGroup->getAttribute("id"); + + $aClasses = array(); + $oClasses = $oGroup->GetUniqueElement('classes'); + foreach($oClasses->getElementsByTagName('class') as $oClass) + { + + $sClass = $oClass->getAttribute("id"); + $aClasses[] = $sClass; + + //$bSubclasses = $this->GetPropBoolean($oClass, 'subclasses', true); + //if ($bSubclasses)... + } + + $aGroupClasses[$sGroupId] = $aClasses; + } + + // Profiles and grants + // + $aProfiles = array(); + // Hardcode the administrator profile + $aProfiles[1] = array( + 'name' => 'Administrator', + 'description' => 'Has the rights on everything (bypassing any control)' + ); + + $aGrants = array(); + $oProfiles = $oUserRightsNode->GetUniqueElement('profiles'); + foreach($oProfiles->getElementsByTagName('profile') as $oProfile) + { + $iProfile = $oProfile->getAttribute("id"); + $sName = $oProfile->GetChildText('name'); + $sDescription = $oProfile->GetChildText('description'); + + $oGroups = $oProfile->GetUniqueElement('groups'); + foreach($oGroups->getElementsByTagName('group') as $oGroup) + { + $sGroupId = $oGroup->getAttribute("id"); + + $aActions = array(); + $oActions = $oGroup->GetUniqueElement('actions'); + foreach($oActions->getElementsByTagName('action') as $oAction) + { + $sAction = $oAction->getAttribute("id"); + $sType = $oAction->getAttribute("xsi:type"); + $sGrant = $oAction->GetText(); + $bGrant = ($sGrant == 'allow'); + + if ($sGroupId == '*') + { + $aGrantClasses = array('*'); + } + else + { + $aGrantClasses = $aGroupClasses[$sGroupId]; + } + foreach ($aGrantClasses as $sClass) + { + if ($sType == 'stimulus') + { + $sGrantKey = $iProfile.'_'.$sClass.'_s_'.$sAction; + } + else + { + $sAction = $aActionsInShort[$sType]; + $sGrantKey = $iProfile.'_'.$sClass.'_'.$sAction; + } + if (isset($aGrants[$sGrantKey])) + { + if (!$bGrant) + { + $aGrants[$sGrantKey] = false; + } + } + else + { + $aGrants[$sGrantKey] = $bGrant; + } + } + } + } + + $aProfiles[$iProfile] = array( + 'name' => $sName, + 'description' => $sDescription + ); + } + + $sProfiles = var_export($aProfiles, true); + $sGrants = var_export($aGrants, true); + + $sPHP = +<< array of column => php value(so-called "real value") + public static function GetProfilesValues() + { + return self::\$aPROFILES; + } +} + +EOF; + return $sPHP; + } // function CompileUserRights + } diff --git a/setup/modelfactory.class.inc.php b/setup/modelfactory.class.inc.php index 7d9d16503..2d3fd4072 100644 --- a/setup/modelfactory.class.inc.php +++ b/setup/modelfactory.class.inc.php @@ -314,6 +314,14 @@ class ModelFactory $oNode->SetAttribute('_created_in', $sModuleName); } } + $oUserRightsNode = $oXPath->query('/itop_design/user_rights')->item(0); + if ($oUserRightsNode) + { + if ($oUserRightsNode->getAttribute('_created_in') == '') + { + $oUserRightsNode->SetAttribute('_created_in', $sModuleName); + } + } $oDeltaRoot = $oDocument->childNodes->item(0); $this->LoadDelta($oDocument, $oDeltaRoot, $this->oDOMDocument); diff --git a/setup/modulediscovery.class.inc.php b/setup/modulediscovery.class.inc.php index 6f0dfc04f..c19663b01 100644 --- a/setup/modulediscovery.class.inc.php +++ b/setup/modulediscovery.class.inc.php @@ -64,6 +64,7 @@ class ModuleDiscovery } $aArgs['root_dir'] = dirname($sFilePath); + $aArgs['module_file'] = $sFilePath; self::$m_aModules[$sId] = $aArgs;