userrightsprofile.class.inc.php 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. <?php
  2. // Copyright (C) 2010 Combodo SARL
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; version 3 of the License.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. /**
  17. * UserRightsProfile
  18. * User management Module, basing the right on profiles and a matrix (similar to UserRightsMatrix, but profiles and other decorations have been added)
  19. *
  20. * @author Erwan Taloc <erwan.taloc@combodo.com>
  21. * @author Romain Quetiez <romain.quetiez@combodo.com>
  22. * @author Denis Flaven <denis.flaven@combodo.com>
  23. * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
  24. */
  25. define('ADMIN_PROFILE_NAME', 'Administrator');
  26. define('PORTAL_PROFILE_NAME', 'Portal user');
  27. class UserRightsBaseClass extends cmdbAbstractObject
  28. {
  29. // Whenever something changes, reload the privileges
  30. protected function AfterInsert()
  31. {
  32. UserRights::FlushPrivileges();
  33. }
  34. protected function AfterUpdate()
  35. {
  36. UserRights::FlushPrivileges();
  37. }
  38. protected function AfterDelete()
  39. {
  40. UserRights::FlushPrivileges();
  41. }
  42. }
  43. class URP_Profiles extends UserRightsBaseClass
  44. {
  45. public static function Init()
  46. {
  47. $aParams = array
  48. (
  49. "category" => "addon/userrights",
  50. "key_type" => "autoincrement",
  51. "name_attcode" => "name",
  52. "state_attcode" => "",
  53. "reconc_keys" => array(),
  54. "db_table" => "priv_urp_profiles",
  55. "db_key_field" => "id",
  56. "db_finalclass_field" => "",
  57. "display_template" => "",
  58. );
  59. MetaModel::Init_Params($aParams);
  60. //MetaModel::Init_InheritAttributes();
  61. MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  62. MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  63. MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("user_list", array("linked_class"=>"URP_UserProfile", "ext_key_to_me"=>"profileid", "ext_key_to_remote"=>"userid", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
  64. // Display lists
  65. MetaModel::Init_SetZListItems('details', array('name', 'description', 'user_list')); // Attributes to be displayed for the complete details
  66. MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
  67. // Search criteria
  68. MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
  69. MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
  70. }
  71. protected $m_bCheckReservedNames = true;
  72. protected function DisableCheckOnReservedNames()
  73. {
  74. $this->m_bCheckReservedNames = false;
  75. }
  76. /*
  77. * Create the built-in Administrator profile with its reserved name
  78. */
  79. public static function DoCreateAdminProfile()
  80. {
  81. $oNewObj = MetaModel::NewObject("URP_Profiles");
  82. $oNewObj->Set('name', ADMIN_PROFILE_NAME);
  83. $oNewObj->Set('description', 'Has the rights on everything (bypassing any control)');
  84. $oNewObj->DisableCheckOnReservedNames();
  85. $iNewId = $oNewObj->DBInsertNoReload();
  86. }
  87. /*
  88. * Create the built-in User Portal profile with its reserved name
  89. */
  90. public static function DoCreateUserPortalProfile()
  91. {
  92. $oNewObj = MetaModel::NewObject("URP_Profiles");
  93. $oNewObj->Set('name', PORTAL_PROFILE_NAME);
  94. $oNewObj->Set('description', '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.');
  95. $oNewObj->DisableCheckOnReservedNames();
  96. $iNewId = $oNewObj->DBInsertNoReload();
  97. }
  98. /*
  99. * Overload the standard behavior to preserve reserved names
  100. */
  101. public function DoCheckToWrite()
  102. {
  103. parent::DoCheckToWrite();
  104. if ($this->m_bCheckReservedNames)
  105. {
  106. $aChanges = $this->ListChanges();
  107. if (array_key_exists('name', $aChanges))
  108. {
  109. if ($this->GetOriginal('name') == ADMIN_PROFILE_NAME)
  110. {
  111. $this->m_aCheckIssues[] = "The name of the Administrator profile must not be changed";
  112. }
  113. elseif ($this->Get('name') == ADMIN_PROFILE_NAME)
  114. {
  115. $this->m_aCheckIssues[] = ADMIN_PROFILE_NAME." is a reserved to the built-in Administrator profile";
  116. }
  117. elseif ($this->GetOriginal('name') == PORTAL_PROFILE_NAME)
  118. {
  119. $this->m_aCheckIssues[] = "The name of the User Portal profile must not be changed";
  120. }
  121. elseif ($this->Get('name') == PORTAL_PROFILE_NAME)
  122. {
  123. $this->m_aCheckIssues[] = PORTAL_PROFILE_NAME." is a reserved to the built-in User Portal profile";
  124. }
  125. }
  126. }
  127. }
  128. function GetGrantAsHtml($oUserRights, $sClass, $sAction)
  129. {
  130. $iGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
  131. if (!is_null($iGrant))
  132. {
  133. return '<span style="background-color: #ddffdd;">'.Dict::S('UI:UserManagement:ActionAllowed:Yes').'</span>';
  134. }
  135. else
  136. {
  137. return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
  138. }
  139. }
  140. function DoShowGrantSumary($oPage)
  141. {
  142. if ($this->GetName() == "Administrator")
  143. {
  144. // Looks dirty, but ok that's THE ONE
  145. $oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));
  146. return;
  147. }
  148. // Note: for sure, we assume that the instance is derived from UserRightsProfile
  149. $oUserRights = UserRights::GetModuleInstance();
  150. $aDisplayData = array();
  151. foreach (MetaModel::GetClasses('bizmodel') as $sClass)
  152. {
  153. // Skip non instantiable classes
  154. if (MetaModel::IsAbstract($sClass)) continue;
  155. $aStimuli = array();
  156. foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
  157. {
  158. $oGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
  159. if (is_object($oGrant) && ($oGrant->Get('permission') == 'yes'))
  160. {
  161. $aStimuli[] = '<span title="'.$sStimulusCode.': '.htmlentities($oStimulus->GetDescription()).'">'.htmlentities($oStimulus->GetLabel()).'</span>';
  162. }
  163. }
  164. $sStimuli = implode(', ', $aStimuli);
  165. $aDisplayData[] = array(
  166. 'class' => MetaModel::GetName($sClass),
  167. 'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Read'),
  168. 'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Read'),
  169. 'write' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Modify'),
  170. 'bulkwrite' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Modify'),
  171. 'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Delete'),
  172. 'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Delete'),
  173. 'stimuli' => $sStimuli,
  174. );
  175. }
  176. $aDisplayConfig = array();
  177. $aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
  178. $aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
  179. $aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
  180. $aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
  181. $aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
  182. $aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+'));
  183. $aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+'));
  184. $aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
  185. $oPage->table($aDisplayConfig, $aDisplayData);
  186. }
  187. function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
  188. {
  189. parent::DisplayBareRelations($oPage, $bEditMode);
  190. if (!$bEditMode)
  191. {
  192. $oPage->SetCurrentTab(Dict::S('UI:UserManagement:GrantMatrix'));
  193. $this->DoShowGrantSumary($oPage);
  194. }
  195. }
  196. }
  197. class URP_UserProfile extends UserRightsBaseClass
  198. {
  199. public static function Init()
  200. {
  201. $aParams = array
  202. (
  203. "category" => "addon/userrights",
  204. "key_type" => "autoincrement",
  205. "name_attcode" => "userid",
  206. "state_attcode" => "",
  207. "reconc_keys" => array(),
  208. "db_table" => "priv_urp_userprofile",
  209. "db_key_field" => "id",
  210. "db_finalclass_field" => "",
  211. "display_template" => "",
  212. );
  213. MetaModel::Init_Params($aParams);
  214. //MetaModel::Init_InheritAttributes();
  215. MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
  216. MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
  217. MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
  218. MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
  219. MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
  220. // Display lists
  221. MetaModel::Init_SetZListItems('details', array('userid', 'profileid', 'reason')); // Attributes to be displayed for the complete details
  222. MetaModel::Init_SetZListItems('list', array('userid', 'profileid', 'reason')); // Attributes to be displayed for a list
  223. // Search criteria
  224. MetaModel::Init_SetZListItems('standard_search', array('userid', 'profileid')); // Criteria of the std search form
  225. MetaModel::Init_SetZListItems('advanced_search', array('userid', 'profileid')); // Criteria of the advanced search form
  226. }
  227. public function GetName()
  228. {
  229. return Dict::Format('UI:UserManagement:LinkBetween_User_And_Profile', $this->Get('userlogin'), $this->Get('profile'));
  230. }
  231. }
  232. class URP_UserOrg extends UserRightsBaseClass
  233. {
  234. public static function Init()
  235. {
  236. $aParams = array
  237. (
  238. "category" => "addon/userrights",
  239. "key_type" => "autoincrement",
  240. "name_attcode" => "userid",
  241. "state_attcode" => "",
  242. "reconc_keys" => array(),
  243. "db_table" => "priv_urp_userorg",
  244. "db_key_field" => "id",
  245. "db_finalclass_field" => "",
  246. "display_template" => "",
  247. );
  248. MetaModel::Init_Params($aParams);
  249. //MetaModel::Init_InheritAttributes();
  250. MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
  251. MetaModel::Init_AddAttribute(new AttributeExternalField("userlogin", array("allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
  252. MetaModel::Init_AddAttribute(new AttributeExternalKey("allowed_org_id", array("targetclass"=>"Organization", "jointype"=> "", "allowed_values"=>null, "sql"=>"allowed_org_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
  253. MetaModel::Init_AddAttribute(new AttributeExternalField("allowed_org_name", array("allowed_values"=>null, "extkey_attcode"=> 'allowed_org_id', "target_attcode"=>"name")));
  254. MetaModel::Init_AddAttribute(new AttributeString("reason", array("allowed_values"=>null, "sql"=>"reason", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
  255. // Display lists
  256. MetaModel::Init_SetZListItems('details', array('userid', 'allowed_org_id', 'reason')); // Attributes to be displayed for the complete details
  257. MetaModel::Init_SetZListItems('list', array('allowed_org_id', 'reason')); // Attributes to be displayed for a list
  258. // Search criteria
  259. MetaModel::Init_SetZListItems('standard_search', array('userid', 'allowed_org_id')); // Criteria of the std search form
  260. MetaModel::Init_SetZListItems('advanced_search', array('userid', 'allowed_org_id')); // Criteria of the advanced search form
  261. }
  262. public function GetName()
  263. {
  264. return Dict::Format('UI:UserManagement:LinkBetween_User_And_Org', $this->Get('userlogin'), $this->Get('allowed_org_name'));
  265. }
  266. }
  267. class URP_ActionGrant extends UserRightsBaseClass
  268. {
  269. public static function Init()
  270. {
  271. $aParams = array
  272. (
  273. "category" => "addon/userrights",
  274. "key_type" => "autoincrement",
  275. "name_attcode" => "profileid",
  276. "state_attcode" => "",
  277. "reconc_keys" => array(),
  278. "db_table" => "priv_urp_grant_actions",
  279. "db_key_field" => "id",
  280. "db_finalclass_field" => "",
  281. "display_template" => "",
  282. );
  283. MetaModel::Init_Params($aParams);
  284. //MetaModel::Init_InheritAttributes();
  285. // Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
  286. 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())));
  287. MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
  288. MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  289. 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())));
  290. MetaModel::Init_AddAttribute(new AttributeString("action", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
  291. // Display lists
  292. MetaModel::Init_SetZListItems('details', array('profileid', 'class', 'permission', 'action')); // Attributes to be displayed for the complete details
  293. MetaModel::Init_SetZListItems('list', array('class', 'permission', 'action')); // Attributes to be displayed for a list
  294. // Search criteria
  295. MetaModel::Init_SetZListItems('standard_search', array('profileid', 'class', 'permission', 'action')); // Criteria of the std search form
  296. MetaModel::Init_SetZListItems('advanced_search', array('profileid', 'class', 'permission', 'action')); // Criteria of the advanced search form
  297. }
  298. }
  299. class URP_StimulusGrant extends UserRightsBaseClass
  300. {
  301. public static function Init()
  302. {
  303. $aParams = array
  304. (
  305. "category" => "addon/userrights",
  306. "key_type" => "autoincrement",
  307. "name_attcode" => "profileid",
  308. "state_attcode" => "",
  309. "reconc_keys" => array(),
  310. "db_table" => "priv_urp_grant_stimulus",
  311. "db_key_field" => "id",
  312. "db_finalclass_field" => "",
  313. "display_template" => "",
  314. );
  315. MetaModel::Init_Params($aParams);
  316. //MetaModel::Init_InheritAttributes();
  317. // Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
  318. 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())));
  319. MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
  320. MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  321. 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())));
  322. MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
  323. // Display lists
  324. MetaModel::Init_SetZListItems('details', array('profileid', 'class', 'permission', 'stimulus')); // Attributes to be displayed for the complete details
  325. MetaModel::Init_SetZListItems('list', array('class', 'permission', 'stimulus')); // Attributes to be displayed for a list
  326. // Search criteria
  327. MetaModel::Init_SetZListItems('standard_search', array('profileid', 'class', 'permission', 'stimulus')); // Criteria of the std search form
  328. MetaModel::Init_SetZListItems('advanced_search', array('profileid', 'class', 'permission', 'stimulus')); // Criteria of the advanced search form
  329. }
  330. }
  331. class URP_AttributeGrant extends UserRightsBaseClass
  332. {
  333. public static function Init()
  334. {
  335. $aParams = array
  336. (
  337. "category" => "addon/userrights",
  338. "key_type" => "autoincrement",
  339. "name_attcode" => "actiongrantid",
  340. "state_attcode" => "",
  341. "reconc_keys" => array(),
  342. "db_table" => "priv_urp_grant_attributes",
  343. "db_key_field" => "id",
  344. "db_finalclass_field" => "",
  345. "display_template" => "",
  346. );
  347. MetaModel::Init_Params($aParams);
  348. //MetaModel::Init_InheritAttributes();
  349. 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())));
  350. MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  351. // Display lists
  352. MetaModel::Init_SetZListItems('details', array('actiongrantid', 'attcode')); // Attributes to be displayed for the complete details
  353. MetaModel::Init_SetZListItems('list', array('attcode')); // Attributes to be displayed for a list
  354. // Search criteria
  355. MetaModel::Init_SetZListItems('standard_search', array('actiongrantid', 'attcode')); // Criteria of the std search form
  356. MetaModel::Init_SetZListItems('advanced_search', array('actiongrantid', 'attcode')); // Criteria of the advanced search form
  357. }
  358. }
  359. class UserRightsProfile extends UserRightsAddOnAPI
  360. {
  361. static public $m_aActionCodes = array(
  362. UR_ACTION_READ => 'read',
  363. UR_ACTION_MODIFY => 'modify',
  364. UR_ACTION_DELETE => 'delete',
  365. UR_ACTION_BULK_READ => 'bulk read',
  366. UR_ACTION_BULK_MODIFY => 'bulk modify',
  367. UR_ACTION_BULK_DELETE => 'bulk delete',
  368. );
  369. // Installation: create the very first user
  370. public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
  371. {
  372. // Create a change to record the history of the User object
  373. $oChange = MetaModel::NewObject("CMDBChange");
  374. $oChange->Set("date", time());
  375. $oChange->Set("userinfo", "Initialization");
  376. $iChangeId = $oChange->DBInsert();
  377. $oOrg = new Organization();
  378. $oOrg->Set('name', 'My Company/Department');
  379. $oOrg->Set('code', 'SOMECODE');
  380. // $oOrg->Set('status', 'implementation');
  381. //$oOrg->Set('parent_id', xxx);
  382. $iOrgId = $oOrg->DBInsertTrackedNoReload($oChange, true /* skip security */);
  383. $oContact = new Person();
  384. $oContact->Set('name', 'My last name');
  385. $oContact->Set('first_name', 'My first name');
  386. //$oContact->Set('status', 'available');
  387. $oContact->Set('org_id', $iOrgId);
  388. $oContact->Set('email', 'my.email@foo.org');
  389. //$oContact->Set('phone', '');
  390. //$oContact->Set('location_id', $iLocationId);
  391. //$oContact->Set('employee_number', '');
  392. $iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
  393. $oUser = new UserLocal();
  394. $oUser->Set('login', $sAdminUser);
  395. $oUser->Set('password', $sAdminPwd);
  396. $oUser->Set('contactid', $iContactId);
  397. $oUser->Set('language', $sLanguage); // Language was chosen during the installation
  398. $iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
  399. // Add this user to the very specific 'admin' profile
  400. $oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true /*all data*/);
  401. if (is_object($oAdminProfile))
  402. {
  403. $oUserProfile = new URP_UserProfile();
  404. $oUserProfile->Set('userid', $iUserId);
  405. $oUserProfile->Set('profileid', $oAdminProfile->GetKey());
  406. $oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
  407. $oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */);
  408. }
  409. return true;
  410. }
  411. public function Setup()
  412. {
  413. SetupProfiles::ComputeITILProfiles();
  414. //SetupProfiles::ComputeBasicProfiles();
  415. SetupProfiles::DoCreateProfiles();
  416. return true;
  417. }
  418. public function Init()
  419. {
  420. MetaModel::RegisterPlugin('userrights', 'ACbyProfile');
  421. }
  422. protected $m_aAdmins; // id of users being linked to the well-known admin profile
  423. protected $m_aPortalUsers; // id of users being linked to the well-known admin profile
  424. protected $m_aProfiles; // id -> object
  425. protected $m_aUserProfiles; // userid,profileid -> object
  426. protected $m_aUserOrgs; // userid,orgid -> object
  427. // Those arrays could be completed on demand (inheriting parent permissions)
  428. protected $m_aClassActionGrants = null; // profile, class, action -> actiongrantid (or false if NO, or null/missing if undefined)
  429. protected $m_aClassStimulusGrants = array(); // profile, class, stimulus -> permission
  430. // Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read)
  431. protected $m_aObjectActionGrants = array();
  432. public function ResetCache()
  433. {
  434. // Loaded by Load cache
  435. $this->m_aProfiles = null;
  436. $this->m_aUserProfiles = null;
  437. $this->m_aUserOrgs = null;
  438. $this->m_aAdmins = null;
  439. $this->m_aPortalUsers = null;
  440. // Loaded on demand (time consuming as compared to the others)
  441. $this->m_aClassActionGrants = null;
  442. $this->m_aClassStimulusGrants = null;
  443. $this->m_aObjectActionGrants = array();
  444. }
  445. // Separate load: this cache is much more time consuming while loading
  446. // Thus it is loaded iif required
  447. // Could be improved by specifying the profile id
  448. public function LoadActionGrantCache()
  449. {
  450. if (!is_null($this->m_aClassActionGrants)) return;
  451. $oKPI = new ExecutionKPI();
  452. $oFilter = DBObjectSearch::FromOQL_AllData("SELECT URP_ActionGrant AS p WHERE p.permission = 'yes'");
  453. $aGrants = $oFilter->ToDataArray();
  454. foreach($aGrants as $aGrant)
  455. {
  456. $this->m_aClassActionGrants[$aGrant['profileid']][$aGrant['class']][strtolower($aGrant['action'])] = $aGrant['id'];
  457. }
  458. $oKPI->ComputeAndReport('Load of action grants');
  459. }
  460. public function LoadCache()
  461. {
  462. if (!is_null($this->m_aProfiles)) return;
  463. // Could be loaded in a shared memory (?)
  464. $oKPI = new ExecutionKPI();
  465. $oProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_Profiles"));
  466. $this->m_aProfiles = array();
  467. while ($oProfile = $oProfileSet->Fetch())
  468. {
  469. $this->m_aProfiles[$oProfile->GetKey()] = $oProfile;
  470. }
  471. $oUserProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_UserProfile"));
  472. $this->m_aUserProfiles = array();
  473. $this->m_aAdmins = array();
  474. $this->m_aPortalUsers = array();
  475. while ($oUserProfile = $oUserProfileSet->Fetch())
  476. {
  477. $this->m_aUserProfiles[$oUserProfile->Get('userid')][$oUserProfile->Get('profileid')] = $oUserProfile;
  478. if ($oUserProfile->Get('profile') == ADMIN_PROFILE_NAME)
  479. {
  480. $this->m_aAdmins[] = $oUserProfile->Get('userid');
  481. }
  482. elseif ($oUserProfile->Get('profile') == PORTAL_PROFILE_NAME)
  483. {
  484. $this->m_aPortalUsers[] = $oUserProfile->Get('userid');
  485. }
  486. }
  487. $oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_UserOrg"));
  488. $this->m_aUserOrgs = array();
  489. while ($oUserOrg = $oUserOrgSet->Fetch())
  490. {
  491. $this->m_aUserOrgs[$oUserOrg->Get('userid')][$oUserOrg->Get('allowed_org_id')] = $oUserOrg;
  492. }
  493. $this->m_aClassStimulusGrants = array();
  494. $oStimGrantSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_StimulusGrant"));
  495. $this->m_aStimGrants = array();
  496. while ($oStimGrant = $oStimGrantSet->Fetch())
  497. {
  498. $this->m_aClassStimulusGrants[$oStimGrant->Get('profileid')][$oStimGrant->Get('class')][$oStimGrant->Get('stimulus')] = $oStimGrant;
  499. }
  500. $oKPI->ComputeAndReport('Load of user management cache (excepted Action Grants)');
  501. /*
  502. echo "<pre>\n";
  503. print_r($this->m_aProfiles);
  504. print_r($this->m_aUserProfiles);
  505. print_r($this->m_aUserOrgs);
  506. print_r($this->m_aClassActionGrants);
  507. print_r($this->m_aClassStimulusGrants);
  508. echo "</pre>\n";
  509. exit;
  510. */
  511. return true;
  512. }
  513. public function IsAdministrator($oUser)
  514. {
  515. $this->LoadCache();
  516. if (in_array($oUser->GetKey(), $this->m_aAdmins))
  517. {
  518. return true;
  519. }
  520. else
  521. {
  522. return false;
  523. }
  524. }
  525. public function IsPortalUser($oUser)
  526. {
  527. $this->LoadCache();
  528. if (in_array($oUser->GetKey(), $this->m_aPortalUsers))
  529. {
  530. return true;
  531. }
  532. else
  533. {
  534. return false;
  535. }
  536. }
  537. public function GetSelectFilter($oUser, $sClass)
  538. {
  539. $this->LoadCache();
  540. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
  541. if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
  542. {
  543. return false;
  544. }
  545. // Determine how to position the objects of this class
  546. //
  547. if ($sClass == 'Organization')
  548. {
  549. $sAttCode = 'id';
  550. }
  551. elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
  552. {
  553. $sAttCode = 'org_id';
  554. }
  555. else
  556. {
  557. // The objects of this class are not positioned in this dimension
  558. // All of them are visible
  559. return true;
  560. }
  561. $oExpression = new FieldExpression($sAttCode, $sClass);
  562. // Position the user
  563. //
  564. @$aUserOrgs = $this->m_aUserOrgs[$oUser->GetKey()];
  565. if (!isset($aUserOrgs) || count($aUserOrgs) == 0)
  566. {
  567. // No position means 'Everywhere'
  568. return true;
  569. }
  570. $aIds = array_keys($aUserOrgs);
  571. $oListExpr = ListExpression::FromScalars($aIds);
  572. $oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
  573. $oFilter = new DBObjectSearch($sClass);
  574. $oFilter->AddConditionExpression($oCondition);
  575. return $oFilter;
  576. }
  577. // This verb has been made public to allow the development of an accurate feedback for the current configuration
  578. public function GetProfileActionGrant($iProfile, $sClass, $sAction)
  579. {
  580. $this->LoadActionGrantCache();
  581. // Note: action is forced lowercase to be more flexible (historical bug)
  582. $sAction = strtolower($sAction);
  583. if (isset($this->m_aClassActionGrants[$iProfile][$sClass][$sAction]))
  584. {
  585. return $this->m_aClassActionGrants[$iProfile][$sClass][$sAction];
  586. }
  587. // Recursively look for the grant record in the class hierarchy
  588. $sParentClass = MetaModel::GetParentPersistentClass($sClass);
  589. if (empty($sParentClass))
  590. {
  591. $iGrant = null;
  592. }
  593. else
  594. {
  595. // Recursively look for the grant record in the class hierarchy
  596. $iGrant = $this->GetProfileActionGrant($iProfile, $sParentClass, $sAction);
  597. }
  598. $this->m_aClassActionGrants[$iProfile][$sClass][$sAction] = $iGrant;
  599. return $iGrant;
  600. }
  601. protected function GetUserActionGrant($oUser, $sClass, $iActionCode)
  602. {
  603. $this->LoadCache();
  604. // load and cache permissions for the current user on the given class
  605. //
  606. $iUser = $oUser->GetKey();
  607. $aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
  608. if (is_array($aTest)) return $aTest;
  609. $sAction = self::$m_aActionCodes[$iActionCode];
  610. $iPermission = UR_ALLOWED_NO;
  611. $aAttributes = array();
  612. if (isset($this->m_aUserProfiles[$iUser]))
  613. {
  614. foreach($this->m_aUserProfiles[$iUser] as $iProfile => $oProfile)
  615. {
  616. $iGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
  617. if (is_null($iGrant) || !$iGrant)
  618. {
  619. continue; // loop to the next profile
  620. }
  621. else
  622. {
  623. $iPermission = UR_ALLOWED_YES;
  624. // update the list of attributes with those allowed for this profile
  625. //
  626. $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid");
  627. $oSet = new DBObjectSet($oSearch, array(), array('actiongrantid' => $iGrant));
  628. $aProfileAttributes = $oSet->GetColumnAsArray('attcode', false);
  629. if (count($aProfileAttributes) == 0)
  630. {
  631. $aAllAttributes = array_keys(MetaModel::ListAttributeDefs($sClass));
  632. $aAttributes = array_merge($aAttributes, $aAllAttributes);
  633. }
  634. else
  635. {
  636. $aAttributes = array_merge($aAttributes, $aProfileAttributes);
  637. }
  638. }
  639. }
  640. }
  641. $aRes = array(
  642. 'permission' => $iPermission,
  643. 'attributes' => $aAttributes,
  644. );
  645. $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
  646. return $aRes;
  647. }
  648. public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
  649. {
  650. $this->LoadCache();
  651. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  652. // and acceptable to consider only the root class of the object set
  653. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, $iActionCode);
  654. return $aObjectPermissions['permission'];
  655. }
  656. public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
  657. {
  658. $this->LoadCache();
  659. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  660. // and acceptable to consider only the root class of the object set
  661. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, $iActionCode);
  662. $aAttributes = $aObjectPermissions['attributes'];
  663. if (in_array($sAttCode, $aAttributes))
  664. {
  665. return $aObjectPermissions['permission'];
  666. }
  667. else
  668. {
  669. return UR_ALLOWED_NO;
  670. }
  671. }
  672. // This verb has been made public to allow the development of an accurate feedback for the current configuration
  673. public function GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode)
  674. {
  675. $this->LoadCache();
  676. if (isset($this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode]))
  677. {
  678. return $this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode];
  679. }
  680. else
  681. {
  682. return null;
  683. }
  684. }
  685. public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
  686. {
  687. $this->LoadCache();
  688. // Note: this code is VERY close to the code of IsActionAllowed()
  689. $iUser = $oUser->GetKey();
  690. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  691. // and acceptable to consider only the root class of the object set
  692. $iPermission = UR_ALLOWED_NO;
  693. if (isset($this->m_aUserProfiles[$iUser]))
  694. {
  695. foreach($this->m_aUserProfiles[$iUser] as $iProfile => $oProfile)
  696. {
  697. $oGrantRecord = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
  698. if (!is_null($oGrantRecord))
  699. {
  700. // no need to fetch the record, we've requested the records having permission = 'yes'
  701. $iPermission = UR_ALLOWED_YES;
  702. }
  703. }
  704. }
  705. return $iPermission;
  706. }
  707. public function FlushPrivileges()
  708. {
  709. $this->ResetCache();
  710. }
  711. }
  712. //
  713. // Create simple profiles into our user management model:
  714. // - administrator
  715. // - readers
  716. // - contributors
  717. //
  718. class SetupProfiles
  719. {
  720. protected static $m_aActions = array(
  721. UR_ACTION_READ => 'Read',
  722. UR_ACTION_MODIFY => 'Modify',
  723. UR_ACTION_DELETE => 'Delete',
  724. UR_ACTION_BULK_READ => 'Bulk Read',
  725. UR_ACTION_BULK_MODIFY => 'Bulk Modify',
  726. UR_ACTION_BULK_DELETE => 'Bulk Delete',
  727. );
  728. // Note: It is possible to specify the same class in several modules
  729. //
  730. protected static $m_aModules = array();
  731. protected static $m_aProfiles = array();
  732. protected static function DoCreateActionGrant($iProfile, $iAction, $sClass, $bPermission = true)
  733. {
  734. $oNewObj = MetaModel::NewObject("URP_ActionGrant");
  735. $oNewObj->Set('profileid', $iProfile);
  736. $oNewObj->Set('permission', $bPermission ? 'yes' : 'no');
  737. $oNewObj->Set('class', $sClass);
  738. $oNewObj->Set('action', self::$m_aActions[$iAction]);
  739. $iId = $oNewObj->DBInsertNoReload();
  740. return $iId;
  741. }
  742. protected static function DoCreateStimulusGrant($iProfile, $sStimulusCode, $sClass)
  743. {
  744. $oNewObj = MetaModel::NewObject("URP_StimulusGrant");
  745. $oNewObj->Set('profileid', $iProfile);
  746. $oNewObj->Set('permission', 'yes');
  747. $oNewObj->Set('class', $sClass);
  748. $oNewObj->Set('stimulus', $sStimulusCode);
  749. $iId = $oNewObj->DBInsertNoReload();
  750. return $iId;
  751. }
  752. protected static function DoCreateOneProfile($sName, $aProfileData)
  753. {
  754. $sDescription = $aProfileData['description'];
  755. if (strlen(trim($aProfileData['write_modules'])) == 0)
  756. {
  757. $aWriteModules = array();
  758. }
  759. else
  760. {
  761. $aWriteModules = explode(',', trim($aProfileData['write_modules']));
  762. }
  763. $aStimuli = $aProfileData['stimuli'];
  764. $oNewObj = MetaModel::NewObject("URP_Profiles");
  765. $oNewObj->Set('name', $sName);
  766. $oNewObj->Set('description', $sDescription);
  767. $iProfile = $oNewObj->DBInsertNoReload();
  768. // Grant read rights for everything
  769. //
  770. foreach (MetaModel::GetClasses('bizmodel') as $sClass)
  771. {
  772. self::DoCreateActionGrant($iProfile, UR_ACTION_READ, $sClass);
  773. self::DoCreateActionGrant($iProfile, UR_ACTION_BULK_READ, $sClass);
  774. }
  775. // Grant write for given modules
  776. // Start by compiling the information, because some modules may overlap
  777. $aWriteableClasses = array();
  778. foreach ($aWriteModules as $sModule)
  779. {
  780. //$oPage->p('Granting write access for the module"'.$sModule.'" - '.count(self::$m_aModules[$sModule]).' classes');
  781. foreach (self::$m_aModules[$sModule] as $sClass)
  782. {
  783. $aWriteableClasses[$sClass] = true;
  784. }
  785. }
  786. foreach ($aWriteableClasses as $sClass => $foo)
  787. {
  788. if (!MetaModel::IsValidClass($sClass))
  789. {
  790. throw new CoreException("Invalid class name '$sClass'");
  791. }
  792. self::DoCreateActionGrant($iProfile, UR_ACTION_MODIFY, $sClass);
  793. self::DoCreateActionGrant($iProfile, UR_ACTION_DELETE, $sClass);
  794. self::DoCreateActionGrant($iProfile, UR_ACTION_BULK_MODIFY, $sClass);
  795. // By default, do not allow bulk deletion operations for standard users
  796. // self::DoCreateActionGrant($iProfile, UR_ACTION_BULK_DELETE, $sClass);
  797. }
  798. // Grant stimuli for given classes
  799. foreach ($aStimuli as $sClass => $sAllowedStimuli)
  800. {
  801. if (!MetaModel::IsValidClass($sClass))
  802. {
  803. // Could be a class defined in a module that wasn't installed
  804. continue;
  805. //throw new CoreException("Invalid class name '$sClass'");
  806. }
  807. if ($sAllowedStimuli == 'any')
  808. {
  809. $aAllowedStimuli = array_keys(MetaModel::EnumStimuli($sClass));
  810. }
  811. elseif ($sAllowedStimuli == 'none')
  812. {
  813. $aAllowedStimuli = array();
  814. }
  815. else
  816. {
  817. $aAllowedStimuli = explode(',', $sAllowedStimuli);
  818. }
  819. foreach ($aAllowedStimuli as $sStimulusCode)
  820. {
  821. self::DoCreateStimulusGrant($iProfile, $sStimulusCode, $sClass);
  822. }
  823. }
  824. }
  825. public static function DoCreateProfiles()
  826. {
  827. URP_Profiles::DoCreateAdminProfile();
  828. URP_Profiles::DoCreateUserPortalProfile();
  829. foreach(self::$m_aProfiles as $sName => $aProfileData)
  830. {
  831. self::DoCreateOneProfile($sName, $aProfileData);
  832. }
  833. }
  834. public static function ComputeBasicProfiles()
  835. {
  836. // In this profiling scheme, one single module represents all the classes
  837. //
  838. self::$m_aModules = array(
  839. 'UserData' => MetaModel::GetClasses('bizmodel'),
  840. );
  841. self::$m_aProfiles = array(
  842. 'Reader' => array(
  843. 'description' => 'Person having a ready-only access to the data',
  844. 'write_modules' => '',
  845. 'stimuli' => array(
  846. ),
  847. ),
  848. 'Writer' => array(
  849. 'description' => 'Contributor to the contents (read + write access)',
  850. 'write_modules' => 'UserData',
  851. 'stimuli' => array(
  852. // any class => 'any'
  853. ),
  854. ),
  855. );
  856. }
  857. public static function ComputeITILProfiles()
  858. {
  859. // In this profiling scheme, modules are based on ITIL recommendations
  860. //
  861. self::$m_aModules = array(
  862. /*
  863. 'WriteModule' => array(
  864. 'someclass',
  865. 'anotherclass',
  866. ),
  867. */
  868. 'General' => MetaModel::GetClasses('structure'),
  869. 'Documentation' => MetaModel::GetClasses('documentation'),
  870. 'Configuration' => MetaModel::GetClasses('configmgmt'),
  871. 'Incident' => MetaModel::GetClasses('incidentmgmt'),
  872. 'Problem' => MetaModel::GetClasses('problemmgmt'),
  873. 'Change' => MetaModel::GetClasses('changemgmt'),
  874. 'Service' => MetaModel::GetClasses('servicemgmt'),
  875. 'Call' => MetaModel::GetClasses('requestmgmt'),
  876. 'KnownError' => MetaModel::GetClasses('knownerrormgmt'),
  877. );
  878. self::$m_aProfiles = array(
  879. 'Configuration Manager' => array(
  880. 'description' => 'Person in charge of the documentation of the managed CIs',
  881. 'write_modules' => 'General,Documentation,Configuration',
  882. 'stimuli' => array(
  883. //'bizServer' => 'none',
  884. //'bizContract' => 'none',
  885. //'bizIncidentTicket' => 'none',
  886. //'bizChangeTicket' => 'any',
  887. ),
  888. ),
  889. 'Service Desk Agent' => array(
  890. 'description' => 'Person in charge of creating incident reports',
  891. 'write_modules' => 'Incident,Call',
  892. 'stimuli' => array(
  893. 'Incident' => 'ev_assign',
  894. 'UserRequest' => 'ev_assign',
  895. ),
  896. ),
  897. 'Support Agent' => array(
  898. 'description' => 'Person analyzing and solving the current incidents',
  899. 'write_modules' => 'Incident',
  900. 'stimuli' => array(
  901. 'Incident' => 'ev_assign,ev_reassign,ev_resolve,ev_close',
  902. 'UserRequest' => 'ev_assign,ev_reassign,ev_resolve,ev_close,ev_freeze',
  903. ),
  904. ),
  905. 'Problem Manager' => array(
  906. 'description' => 'Person analyzing and solving the current problems',
  907. 'write_modules' => 'Problem,KnownError',
  908. 'stimuli' => array(
  909. 'Problem' => 'ev_assign,ev_reassign,ev_resolve,ev_close',
  910. ),
  911. ),
  912. 'Change Implementor' => array(
  913. 'description' => 'Person executing the changes',
  914. 'write_modules' => 'Change',
  915. 'stimuli' => array(
  916. 'NormalChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor',
  917. 'EmergencyChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor',
  918. 'RoutineChange' => 'ev_plan,ev_replan,ev_implement,ev_monitor',
  919. ),
  920. ),
  921. 'Change Supervisor' => array(
  922. 'description' => 'Person responsible for the overall change execution',
  923. 'write_modules' => 'Change',
  924. 'stimuli' => array(
  925. 'NormalChange' => 'ev_validate,ev_reject,ev_assign,ev_reopen,ev_finish',
  926. 'EmergencyChange' => 'ev_assign,ev_reopen,ev_finish',
  927. 'RoutineChange' => 'ev_assign,ev_reopen,ev_finish',
  928. ),
  929. ),
  930. 'Change Approver' => array(
  931. 'description' => 'Person who could be impacted by some changes',
  932. 'write_modules' => 'Change',
  933. 'stimuli' => array(
  934. 'NormalChange' => 'ev_approve,ev_notapprove',
  935. 'EmergencyChange' => 'ev_approve,ev_notapprove',
  936. 'RoutineChange' => 'none',
  937. ),
  938. ),
  939. 'Service Manager' => array(
  940. 'description' => 'Person responsible for the service delivered to the [internal] customer',
  941. 'write_modules' => 'Service',
  942. 'stimuli' => array(
  943. ),
  944. ),
  945. 'Document author' => array(
  946. 'description' => 'Any person who could contribute to documentation',
  947. 'write_modules' => 'Documentation',
  948. 'stimuli' => array(
  949. ),
  950. ),
  951. );
  952. }
  953. }
  954. UserRights::SelectModule('UserRightsProfile');
  955. ?>