]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/ACLActions/ACLAction.php
Release 6.5.16
[Github/sugarcrm.git] / modules / ACLActions / ACLAction.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 require_once('modules/ACLActions/actiondefs.php');
39 class ACLAction  extends SugarBean{
40     var $module_dir = 'ACLActions';
41     var $object_name = 'ACLAction';
42     var $table_name = 'acl_actions';
43     var $new_schema = true;
44     var $disable_custom_fields = true;
45     function ACLAction(){
46         parent::SugarBean();
47     }
48
49     /**
50     * static addActions($category, $type='module')
51     * Adds all default actions for a category/type
52     *
53     * @param STRING $category - the category (e.g module name - Accounts, Contacts)
54     * @param STRING $type - the type (e.g. 'module', 'field')
55     */
56     static function addActions($category, $type='module'){
57         global $ACLActions;
58         $db = DBManagerFactory::getInstance();
59         if(isset($ACLActions[$type])){
60             foreach($ACLActions[$type]['actions'] as $action_name =>$action_def){
61
62                 $action = new ACLAction();
63                 $query = "SELECT * FROM " . $action->table_name . " WHERE name='$action_name' AND category = '$category' AND acltype='$type' AND deleted=0 ";
64                 $result = $db->query($query);
65                 //only add if an action with that name and category don't exist
66                 $row=$db->fetchByAssoc($result);
67                 if ($row == null) {
68                     $action->name = $action_name;
69                     $action->category = $category;
70                     $action->aclaccess = $action_def['default'];
71                     $action->acltype = $type;
72                     $action->modified_user_id = 1;
73                     $action->created_by = 1;
74                     $action->save();
75
76                 }
77             }
78
79         }else{
80             sugar_die("FAILED TO ADD: $category - TYPE $type NOT DEFINED IN modules/ACLActions/actiondefs.php");
81         }
82
83     }
84
85     /**
86     * static removeActions($category, $type='module')
87     * Removes all default actions for a category/type
88     *
89     * @param STRING $category - the category (e.g module name - Accounts, Contacts)
90     * @param STRING $type - the type (e.g. 'module', 'field')
91     */
92     public static function removeActions($category, $type='module'){
93         global $ACLActions;
94         $db = DBManagerFactory::getInstance();
95         if(isset($ACLActions[$type])){
96             foreach($ACLActions[$type]['actions'] as $action_name =>$action_def){
97
98                 $action = new ACLAction();
99                 $query = "SELECT * FROM " . $action->table_name . " WHERE name='$action_name' AND category = '$category' AND acltype='$type' and deleted=0";
100                 $result = $db->query($query);
101                 //only add if an action with that name and category don't exist
102                 $row=$db->fetchByAssoc($result);
103                 if ($row != null) {
104                     $action->mark_deleted($row['id']);
105                 }
106             }
107         }else{
108             sugar_die("FAILED TO REMOVE: $category : $name - TYPE $type NOT DEFINED IN modules/ACLActions/actiondefs.php");
109         }
110     }
111
112     /**
113     * static AccessColor($access)
114     *
115     * returns the color associated with an access level
116     * these colors exist in the definitions in modules/ACLActions/actiondefs.php
117     * @param INT $access - the access level you want the color for
118     * @return the color either name or hex representation or false if the level does not exist
119     */
120     protected static function AccessColor($access){
121         global $ACLActionAccessLevels;
122         if(isset($ACLActionAccessLevels[$access])){
123
124             return $ACLActionAccessLevels[$access]['color'];
125         }
126         return false;
127
128     }
129
130     /**
131     * static AccessName($access)
132     *
133     * returns the translated name  associated with an access level
134     * these label definitions  exist in the definitions in modules/ACLActions/actiondefs.php
135     * @param INT $access - the access level you want the color for
136     * @return the translated access level name or false if the level does not exist
137     */
138     static function AccessName($access){
139         global $ACLActionAccessLevels;
140         if(isset($ACLActionAccessLevels[$access])){
141             return translate($ACLActionAccessLevels[$access]['label'], 'ACLActions');
142         }
143         return false;
144
145     }
146
147     /**
148      * static AccessLabel($access)
149      *
150      * returns the label  associated with an access level
151      * these label definitions  exist in the definitions in modules/ACLActions/actiondefs.php
152      * @param INT $access - the access level you want the color for
153      * @return the access level label or false if the level does not exist
154      */
155     protected static function AccessLabel($access){
156         global $ACLActionAccessLevels;
157         if(isset($ACLActionAccessLevels[$access])){
158             $label=preg_replace('/(LBL_ACCESS_)(.*)/', '$2', $ACLActionAccessLevels[$access]['label']);
159             return strtolower($label);
160
161         }
162         return false;
163
164     }
165
166     /**
167     * static getAccessOptions()
168     * this is used for building select boxes
169     * @return array containg access levels (ints) as keys and access names as values
170     */
171     protected static function getAccessOptions( $action, $type='module'){
172         global $ACLActions;
173         $options = array();
174
175         if(empty($ACLActions[$type]['actions'][$action]['aclaccess']))return $options;
176         foreach($ACLActions[$type]['actions'][$action]['aclaccess'] as $action){
177             $options[$action] = ACLAction::AccessName($action);
178         }
179         return $options;
180
181     }
182
183     /**
184     * function static getDefaultActions()
185     * This function will return a list of acl actions with their default access levels
186     *
187     *
188     */
189     public static function getDefaultActions($type='module', $action=''){
190         $query = "SELECT * FROM acl_actions WHERE deleted=0 ";
191         if(!empty($type)){
192             $query .= " AND acltype='$type'";
193         }
194         if(!empty($action)){
195             $query .= "AND name='$action'";
196         }
197         $query .= " ORDER BY category";
198
199         $db = DBManagerFactory::getInstance();
200         $result = $db->query($query);
201         $default_actions = array();
202         while($row = $db->fetchByAssoc($result) ){
203             $acl = new ACLAction();
204             $acl->populateFromRow($row);
205             $default_actions[] = $acl;
206         }
207         return $default_actions;
208     }
209
210
211     /**
212     * static getUserActions($user_id,$refresh=false, $category='', $action='')
213     * returns a list of user actions
214     * @param GUID $user_id
215     * @param BOOLEAN $refresh
216     * @param STRING $category
217     * @param STRING $action
218     * @return ARRAY of ACLActionsArray
219     */
220
221     static function getUserActions($user_id,$refresh=false, $category='',$type='', $action=''){
222         //check in the session if we already have it loaded
223         if(!$refresh && !empty($_SESSION['ACL'][$user_id])){
224             if(empty($category) && empty($action)){
225                 return $_SESSION['ACL'][$user_id];
226             }else{
227                 if(!empty($category) && isset($_SESSION['ACL'][$user_id][$category])){
228                     if(empty($action)){
229                         if(empty($type)){
230                             return $_SESSION['ACL'][$user_id][$category];
231                         }
232                         return $_SESSION['ACL'][$user_id][$category][$type];
233                     }else if(!empty($type) && isset($_SESSION['ACL'][$user_id][$category][$type][$action])){
234                         return $_SESSION['ACL'][$user_id][$category][$type][$action];
235                     }
236                 }
237             }
238         }
239         //if we don't have it loaded then lets check against the db
240         $additional_where = '';
241         $db = DBManagerFactory::getInstance();
242         if(!empty($category)){
243             $additional_where .= " AND acl_actions.category = '$category' ";
244         }
245         if(!empty($action)){
246             $additional_where .= " AND acl_actions.name = '$action' ";
247         }
248         if(!empty($type)){
249             $additional_where .= " AND acl_actions.acltype = '$type' ";
250         }
251         $query = "SELECT acl_actions .*, acl_roles_actions.access_override
252                     FROM acl_actions
253                     LEFT JOIN acl_roles_users ON acl_roles_users.user_id = '$user_id' AND  acl_roles_users.deleted = 0
254                     LEFT JOIN acl_roles_actions ON acl_roles_actions.role_id = acl_roles_users.role_id AND acl_roles_actions.action_id = acl_actions.id AND acl_roles_actions.deleted=0
255                     WHERE acl_actions.deleted=0 $additional_where ORDER BY category,name";
256         $result = $db->query($query);
257         $selected_actions = array();
258         while($row = $db->fetchByAssoc($result, FALSE) ){
259             $acl = new ACLAction();
260             $isOverride  = false;
261             $acl->populateFromRow($row);
262             if(!empty($row['access_override'])){
263                 $acl->aclaccess = $row['access_override'];
264                 $isOverride = true;
265             }
266             if(!isset($selected_actions[$acl->category])){
267                 $selected_actions[$acl->category] = array();
268
269             }
270             if(!isset($selected_actions[$acl->category][$acl->acltype][$acl->name])
271                 || ($selected_actions[$acl->category][$acl->acltype][$acl->name]['aclaccess'] > $acl->aclaccess
272                     && $isOverride
273                     )
274                 ||
275                     (!empty($selected_actions[$acl->category][$acl->acltype][$acl->name]['isDefault'])
276                     && $isOverride
277                     )
278                 )
279             {
280
281
282                 $selected_actions[$acl->category][$acl->acltype][$acl->name] = $acl->toArray();
283                 $selected_actions[$acl->category][$acl->acltype][$acl->name]['isDefault'] = !$isOverride;
284             }
285
286         }
287
288         //only set the session variable if it was a full list;
289         if(empty($category) && empty($action)){
290             if(!isset($_SESSION['ACL'])){
291                 $_SESSION['ACL'] = array();
292             }
293             $_SESSION['ACL'][$user_id] = $selected_actions;
294         }else{
295             if(empty($action) && !empty($category)){
296                 if(!empty($type)){
297                     $_SESSION['ACL'][$user_id][$category][$type] = $selected_actions[$category][$type];}
298                 $_SESSION['ACL'][$user_id][$category] = $selected_actions[$category];
299             }else{
300                 if(!empty($action) && !empty($category) && !empty($type)){
301                 $_SESSION['ACL'][$user_id][$category][$type][$action] = $selected_actions[$category][$action];
302
303             }
304             }
305         }
306         
307         // Sort by translated categories
308         uksort($selected_actions, "ACLAction::langCompare");
309         return $selected_actions;
310     }
311     
312     private static function langCompare($a, $b) 
313     {
314         global $app_list_strings;
315         // Fallback to array key if translation is empty
316         $a = empty($app_list_strings['moduleList'][$a]) ? $a : $app_list_strings['moduleList'][$a];
317         $b = empty($app_list_strings['moduleList'][$b]) ? $b : $app_list_strings['moduleList'][$b];
318         if ($a == $b)
319             return 0;
320         return ($a < $b) ? -1 : 1;
321     }
322     
323     /**
324     * (static/ non-static)function hasAccess($is_owner= false , $access = 0)
325     * checks if a user has access to this acl if the user is an owner it will check if owners have access
326     *
327     * This function may either be used statically or not. If used staticlly a user must pass in an access level not equal to zero
328     * @param boolean $is_owner
329     * @param int $access
330     * @return true or false
331     */
332     static function hasAccess($is_owner=false, $access = 0){
333
334         if($access != 0 && $access == ACL_ALLOW_ALL || ($is_owner && $access == ACL_ALLOW_OWNER))return true;
335        //if this exists, then this function is not static, so check the aclaccess parameter
336         if(isset($this) && isset($this->aclaccess)){
337             if($this->aclaccess == ACL_ALLOW_ALL || ($is_owner && $this->aclaccess == ACL_ALLOW_OWNER))
338             return true;
339         }
340         return false;
341     }
342
343
344
345
346
347
348
349
350
351     /**
352     * static function userHasAccess($user_id, $category, $action, $is_owner = false)
353     *
354     * @param GUID $user_id the user id who you want to check access for
355     * @param STRING $category the category you would like to check access for
356     * @param STRING $action the action of that category you would like to check access for
357     * @param BOOLEAN OPTIONAL $is_owner if the object is owned by the user you are checking access for
358     */
359     public static function userHasAccess($user_id, $category, $action,$type='module', $is_owner = false){
360        global $current_user;
361        if($current_user->isAdminForModule($category)&& !isset($_SESSION['ACL'][$user_id][$category][$type][$action]['aclaccess'])){
362         return true;
363         }
364         //check if we don't have it set in the cache if not lets reload the cache
365         if(ACLAction::getUserAccessLevel($user_id, $category, 'access', $type) < ACL_ALLOW_ENABLED) return false;
366         if(empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
367             ACLAction::getUserActions($user_id, false);
368
369         }
370
371         if(!empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
372             return ACLAction::hasAccess($is_owner, $_SESSION['ACL'][$user_id][$category][$type][$action]['aclaccess']);
373         }
374         return false;
375
376     }
377     /**
378     * function getUserAccessLevel($user_id, $category, $action,$type='module')
379     * returns the access level for a given category and action
380     *
381     * @param GUID  $user_id
382     * @param STRING $category
383     * @param STRING $action
384     * @param STRING $type
385     * @return INT (ACCESS LEVEL)
386     */
387     public static function getUserAccessLevel($user_id, $category, $action,$type='module'){
388         if(empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
389             ACLAction::getUserActions($user_id, false);
390
391         }
392         if(!empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
393             if (!empty($_SESSION['ACL'][$user_id][$category][$type]['admin']) && $_SESSION['ACL'][$user_id][$category][$type]['admin']['aclaccess'] >= ACL_ALLOW_ADMIN)
394             {
395                 // If you have admin access for a module, all ACL's are allowed
396                 return $_SESSION['ACL'][$user_id][$category][$type]['admin']['aclaccess'];
397             }            
398             return  $_SESSION['ACL'][$user_id][$category][$type][$action]['aclaccess'];
399         }
400     }
401
402     /**
403     * STATIC function userNeedsOwnership($user_id, $category, $action,$type='module')
404     * checks if a user should have ownership to do an action
405     *
406     * @param GUID $user_id
407     * @param STRING $category
408     * @param STRING $action
409     * @param STRING $type
410     * @return boolean
411     */
412     public static function userNeedsOwnership($user_id, $category, $action,$type='module'){
413         //check if we don't have it set in the cache if not lets reload the cache
414
415         if(empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
416             ACLAction::getUserActions($user_id, false);
417
418         }
419
420
421         if(!empty($_SESSION['ACL'][$user_id][$category][$type][$action])){
422             return $_SESSION['ACL'][$user_id][$category][$type][$action]['aclaccess'] == ACL_ALLOW_OWNER;
423         }
424         return false;
425
426     }
427     /**
428     *
429     * static pass by ref setupCategoriesMatrix(&$categories)
430     * takes in an array of categories and modifes them adding display information
431     *
432     * @param unknown_type $categories
433     */
434     public static function setupCategoriesMatrix(&$categories){
435         global $ACLActions, $current_user;
436         $names = array();
437         $disabled = array();
438         foreach($categories as $cat_name=>$category){
439             foreach($category as $type_name=>$type){
440                 foreach($type as $act_name=>$action){
441                     $names[$act_name] = translate($ACLActions[$type_name]['actions'][$act_name]['label'], 'ACLActions');
442                     $categories[$cat_name][$type_name][$act_name]['accessColor'] = ACLAction::AccessColor($action['aclaccess']);
443                     if($type_name== 'module'){
444
445                         if($act_name != 'aclaccess' && $categories[$cat_name]['module']['access']['aclaccess'] == ACL_ALLOW_DISABLED){
446                             $categories[$cat_name][$type_name][$act_name]['accessColor'] = 'darkgray';
447                             $disabled[] = $cat_name;
448                         }
449
450                     }
451                     $categories[$cat_name][$type_name][$act_name]['accessName'] = ACLAction::AccessName($action['aclaccess']);
452                     $categories[$cat_name][$type_name][$act_name]['accessLabel'] = ACLAction::AccessLabel($action['aclaccess']);
453
454                     if($cat_name=='Users'&& $act_name=='admin'){
455                         $categories[$cat_name][$type_name][$act_name]['accessOptions'][ACL_ALLOW_DEFAULT]=ACLAction::AccessName(ACL_ALLOW_DEFAULT);;
456                         $categories[$cat_name][$type_name][$act_name]['accessOptions'][ACL_ALLOW_DEV]=ACLAction::AccessName(ACL_ALLOW_DEV);;
457                     }
458                     else{
459                     $categories[$cat_name][$type_name][$act_name]['accessOptions'] =  ACLAction::getAccessOptions($act_name, $type_name);
460                     }
461                 }
462             }
463         }
464
465         if(!is_admin($current_user)){
466             foreach($disabled as $cat_name){
467                 unset($categories[$cat_name]);
468             }
469         }
470         return $names;
471     }
472
473
474
475     /**
476     * function toArray()
477     * returns this acl as an array
478     *
479     * @return array of fields with id, name, access and category
480     */
481     function toArray(){
482         $array_fields = array('id', 'aclaccess');
483         $arr = array();
484         foreach($array_fields as $field){
485             $arr[$field] = $this->$field;
486         }
487         return $arr;
488     }
489
490     /**
491     * function fromArray($arr)
492     * converts an array into an acl mapping name value pairs into files
493     *
494     * @param Array $arr
495     */
496     function fromArray($arr){
497         foreach($arr as $name=>$value){
498             $this->$name = $value;
499         }
500     }
501
502     /**
503     * function clearSessionCache()
504     * clears the session variable storing the cache information for acls
505     *
506     */
507     function clearSessionCache(){
508         unset($_SESSION['ACL']);
509     }
510
511
512
513
514
515
516
517
518
519
520
521
522
523 }