userrightsprofile.class.inc.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  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. if (MetaModel::IsValidAttCode('Person', 'org_id'))
  388. {
  389. // Protect for a different data model where contacts are not part of an org
  390. $oContact->Set('org_id', $iOrgId);
  391. }
  392. $oContact->Set('email', 'my.email@foo.org');
  393. //$oContact->Set('phone', '');
  394. //$oContact->Set('location_id', $iLocationId);
  395. //$oContact->Set('employee_number', '');
  396. $iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
  397. $oUser = new UserLocal();
  398. $oUser->Set('login', $sAdminUser);
  399. $oUser->Set('password', $sAdminPwd);
  400. $oUser->Set('contactid', $iContactId);
  401. $oUser->Set('language', $sLanguage); // Language was chosen during the installation
  402. // Add this user to the very specific 'admin' profile
  403. $oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true /*all data*/);
  404. if (is_object($oAdminProfile))
  405. {
  406. $oUserProfile = new URP_UserProfile();
  407. //$oUserProfile->Set('userid', $iUserId);
  408. $oUserProfile->Set('profileid', $oAdminProfile->GetKey());
  409. $oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile');
  410. //$oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */);
  411. $oSet = DBObjectSet::FromObject($oUserProfile);
  412. $oUser->Set('profile_list', $oSet);
  413. }
  414. $iUserId = $oUser->DBInsertTrackedNoReload($oChange, true /* skip security */);
  415. return true;
  416. }
  417. public function Init()
  418. {
  419. MetaModel::RegisterPlugin('userrights', 'ACbyProfile');
  420. }
  421. protected $m_aAdmins; // id of users being linked to the well-known admin profile
  422. protected $m_aPortalUsers; // id of users being linked to the well-known admin profile
  423. protected $m_aProfiles; // id -> object
  424. protected $m_aUserProfiles; // userid,profileid -> object
  425. protected $m_aUserOrgs; // userid,orgid -> object
  426. // Those arrays could be completed on demand (inheriting parent permissions)
  427. protected $m_aClassActionGrants = null; // profile, class, action -> actiongrantid (or false if NO, or null/missing if undefined)
  428. protected $m_aClassStimulusGrants = array(); // profile, class, stimulus -> permission
  429. // Built on demand, could be optimized if necessary (doing a query for each attribute that needs to be read)
  430. protected $m_aObjectActionGrants = array();
  431. public function ResetCache()
  432. {
  433. // Loaded by Load cache
  434. $this->m_aProfiles = null;
  435. $this->m_aUserProfiles = null;
  436. $this->m_aUserOrgs = null;
  437. $this->m_aAdmins = null;
  438. $this->m_aPortalUsers = null;
  439. // Loaded on demand (time consuming as compared to the others)
  440. $this->m_aClassActionGrants = null;
  441. $this->m_aClassStimulusGrants = null;
  442. $this->m_aObjectActionGrants = array();
  443. }
  444. // Separate load: this cache is much more time consuming while loading
  445. // Thus it is loaded iif required
  446. // Could be improved by specifying the profile id
  447. public function LoadActionGrantCache()
  448. {
  449. if (!is_null($this->m_aClassActionGrants)) return;
  450. $oKPI = new ExecutionKPI();
  451. $oFilter = DBObjectSearch::FromOQL_AllData("SELECT URP_ActionGrant AS p WHERE p.permission = 'yes'");
  452. $aGrants = $oFilter->ToDataArray();
  453. foreach($aGrants as $aGrant)
  454. {
  455. $this->m_aClassActionGrants[$aGrant['profileid']][$aGrant['class']][strtolower($aGrant['action'])] = $aGrant['id'];
  456. }
  457. $oKPI->ComputeAndReport('Load of action grants');
  458. }
  459. public function LoadCache()
  460. {
  461. if (!is_null($this->m_aProfiles)) return;
  462. // Could be loaded in a shared memory (?)
  463. $oKPI = new ExecutionKPI();
  464. $oProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_Profiles"));
  465. $this->m_aProfiles = array();
  466. while ($oProfile = $oProfileSet->Fetch())
  467. {
  468. $this->m_aProfiles[$oProfile->GetKey()] = $oProfile;
  469. }
  470. $oUserProfileSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_UserProfile"));
  471. $this->m_aUserProfiles = array();
  472. $this->m_aAdmins = array();
  473. $this->m_aPortalUsers = array();
  474. while ($oUserProfile = $oUserProfileSet->Fetch())
  475. {
  476. $this->m_aUserProfiles[$oUserProfile->Get('userid')][$oUserProfile->Get('profileid')] = $oUserProfile;
  477. if ($oUserProfile->Get('profile') == ADMIN_PROFILE_NAME)
  478. {
  479. $this->m_aAdmins[] = $oUserProfile->Get('userid');
  480. }
  481. elseif ($oUserProfile->Get('profile') == PORTAL_PROFILE_NAME)
  482. {
  483. $this->m_aPortalUsers[] = $oUserProfile->Get('userid');
  484. }
  485. }
  486. $oUserOrgSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_UserOrg"));
  487. $this->m_aUserOrgs = array();
  488. while ($oUserOrg = $oUserOrgSet->Fetch())
  489. {
  490. $this->m_aUserOrgs[$oUserOrg->Get('userid')][$oUserOrg->Get('allowed_org_id')] = $oUserOrg;
  491. }
  492. $this->m_aClassStimulusGrants = array();
  493. $oStimGrantSet = new DBObjectSet(DBObjectSearch::FromOQL_AllData("SELECT URP_StimulusGrant"));
  494. $this->m_aStimGrants = array();
  495. while ($oStimGrant = $oStimGrantSet->Fetch())
  496. {
  497. $this->m_aClassStimulusGrants[$oStimGrant->Get('profileid')][$oStimGrant->Get('class')][$oStimGrant->Get('stimulus')] = $oStimGrant;
  498. }
  499. $oKPI->ComputeAndReport('Load of user management cache (excepted Action Grants)');
  500. /*
  501. echo "<pre>\n";
  502. print_r($this->m_aProfiles);
  503. print_r($this->m_aUserProfiles);
  504. print_r($this->m_aUserOrgs);
  505. print_r($this->m_aClassActionGrants);
  506. print_r($this->m_aClassStimulusGrants);
  507. echo "</pre>\n";
  508. exit;
  509. */
  510. return true;
  511. }
  512. public function IsAdministrator($oUser)
  513. {
  514. $this->LoadCache();
  515. if (in_array($oUser->GetKey(), $this->m_aAdmins))
  516. {
  517. return true;
  518. }
  519. else
  520. {
  521. return false;
  522. }
  523. }
  524. public function IsPortalUser($oUser)
  525. {
  526. $this->LoadCache();
  527. if (in_array($oUser->GetKey(), $this->m_aPortalUsers))
  528. {
  529. return true;
  530. }
  531. else
  532. {
  533. return false;
  534. }
  535. }
  536. public function GetSelectFilter($oUser, $sClass)
  537. {
  538. $this->LoadCache();
  539. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, UR_ACTION_READ);
  540. if ($aObjectPermissions['permission'] == UR_ALLOWED_NO)
  541. {
  542. return false;
  543. }
  544. // Determine how to position the objects of this class
  545. //
  546. if ($sClass == 'Organization')
  547. {
  548. $sAttCode = 'id';
  549. }
  550. elseif(MetaModel::IsValidAttCode($sClass, 'org_id'))
  551. {
  552. $sAttCode = 'org_id';
  553. }
  554. else
  555. {
  556. // The objects of this class are not positioned in this dimension
  557. // All of them are visible
  558. return true;
  559. }
  560. $oExpression = new FieldExpression($sAttCode, $sClass);
  561. // Position the user
  562. //
  563. @$aUserOrgs = $this->m_aUserOrgs[$oUser->GetKey()];
  564. if (!isset($aUserOrgs) || count($aUserOrgs) == 0)
  565. {
  566. // No position means 'Everywhere'
  567. return true;
  568. }
  569. $aIds = array_keys($aUserOrgs);
  570. $oListExpr = ListExpression::FromScalars($aIds);
  571. $oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
  572. $oFilter = new DBObjectSearch($sClass);
  573. $oFilter->AddConditionExpression($oCondition);
  574. return $oFilter;
  575. }
  576. // This verb has been made public to allow the development of an accurate feedback for the current configuration
  577. public function GetProfileActionGrant($iProfile, $sClass, $sAction)
  578. {
  579. $this->LoadActionGrantCache();
  580. // Note: action is forced lowercase to be more flexible (historical bug)
  581. $sAction = strtolower($sAction);
  582. if (isset($this->m_aClassActionGrants[$iProfile][$sClass][$sAction]))
  583. {
  584. return $this->m_aClassActionGrants[$iProfile][$sClass][$sAction];
  585. }
  586. // Recursively look for the grant record in the class hierarchy
  587. $sParentClass = MetaModel::GetParentPersistentClass($sClass);
  588. if (empty($sParentClass))
  589. {
  590. $iGrant = null;
  591. }
  592. else
  593. {
  594. // Recursively look for the grant record in the class hierarchy
  595. $iGrant = $this->GetProfileActionGrant($iProfile, $sParentClass, $sAction);
  596. }
  597. $this->m_aClassActionGrants[$iProfile][$sClass][$sAction] = $iGrant;
  598. return $iGrant;
  599. }
  600. protected function GetUserActionGrant($oUser, $sClass, $iActionCode)
  601. {
  602. $this->LoadCache();
  603. // load and cache permissions for the current user on the given class
  604. //
  605. $iUser = $oUser->GetKey();
  606. $aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
  607. if (is_array($aTest)) return $aTest;
  608. $sAction = self::$m_aActionCodes[$iActionCode];
  609. $iPermission = UR_ALLOWED_NO;
  610. $aAttributes = array();
  611. if (isset($this->m_aUserProfiles[$iUser]))
  612. {
  613. foreach($this->m_aUserProfiles[$iUser] as $iProfile => $oProfile)
  614. {
  615. $iGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
  616. if (is_null($iGrant) || !$iGrant)
  617. {
  618. continue; // loop to the next profile
  619. }
  620. else
  621. {
  622. $iPermission = UR_ALLOWED_YES;
  623. // update the list of attributes with those allowed for this profile
  624. //
  625. $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid");
  626. $oSet = new DBObjectSet($oSearch, array(), array('actiongrantid' => $iGrant));
  627. $aProfileAttributes = $oSet->GetColumnAsArray('attcode', false);
  628. if (count($aProfileAttributes) == 0)
  629. {
  630. $aAllAttributes = array_keys(MetaModel::ListAttributeDefs($sClass));
  631. $aAttributes = array_merge($aAttributes, $aAllAttributes);
  632. }
  633. else
  634. {
  635. $aAttributes = array_merge($aAttributes, $aProfileAttributes);
  636. }
  637. }
  638. }
  639. }
  640. $aRes = array(
  641. 'permission' => $iPermission,
  642. 'attributes' => $aAttributes,
  643. );
  644. $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
  645. return $aRes;
  646. }
  647. public function IsActionAllowed($oUser, $sClass, $iActionCode, $oInstanceSet = null)
  648. {
  649. $this->LoadCache();
  650. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  651. // and acceptable to consider only the root class of the object set
  652. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, $iActionCode);
  653. return $aObjectPermissions['permission'];
  654. }
  655. public function IsActionAllowedOnAttribute($oUser, $sClass, $sAttCode, $iActionCode, $oInstanceSet = null)
  656. {
  657. $this->LoadCache();
  658. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  659. // and acceptable to consider only the root class of the object set
  660. $aObjectPermissions = $this->GetUserActionGrant($oUser, $sClass, $iActionCode);
  661. $aAttributes = $aObjectPermissions['attributes'];
  662. if (in_array($sAttCode, $aAttributes))
  663. {
  664. return $aObjectPermissions['permission'];
  665. }
  666. else
  667. {
  668. return UR_ALLOWED_NO;
  669. }
  670. }
  671. // This verb has been made public to allow the development of an accurate feedback for the current configuration
  672. public function GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode)
  673. {
  674. $this->LoadCache();
  675. if (isset($this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode]))
  676. {
  677. return $this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode];
  678. }
  679. else
  680. {
  681. return null;
  682. }
  683. }
  684. public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
  685. {
  686. $this->LoadCache();
  687. // Note: this code is VERY close to the code of IsActionAllowed()
  688. $iUser = $oUser->GetKey();
  689. // Note: The object set is ignored because it was interesting to optimize for huge data sets
  690. // and acceptable to consider only the root class of the object set
  691. $iPermission = UR_ALLOWED_NO;
  692. if (isset($this->m_aUserProfiles[$iUser]))
  693. {
  694. foreach($this->m_aUserProfiles[$iUser] as $iProfile => $oProfile)
  695. {
  696. $oGrantRecord = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
  697. if (!is_null($oGrantRecord))
  698. {
  699. // no need to fetch the record, we've requested the records having permission = 'yes'
  700. $iPermission = UR_ALLOWED_YES;
  701. }
  702. }
  703. }
  704. return $iPermission;
  705. }
  706. public function FlushPrivileges()
  707. {
  708. $this->ResetCache();
  709. }
  710. }
  711. UserRights::SelectModule('UserRightsProfile');
  712. ?>