SugarCRM v7 - Conditional record locking through ACL's customisation
<?php | |
// | |
// Enrico Simonetti | |
// enricosimonetti.com | |
// | |
// 2016-05-08 on Sugar 7.7.0.0 | |
// file: custom/data/acl/SugarACLLock.php | |
// | |
// ACL to lock record in certain conditions. Always allow admin users and specific user ids | |
// | |
// Changes to this class might require the user browser's storage and cache to be cleared, to work correctly | |
// | |
class SugarACLLock extends SugarACLStrategy | |
{ | |
// allowed user ids | |
protected $user_ids_to_allow = array( | |
); | |
// denied actions | |
protected $denied_actions = array( | |
'edit', | |
'delete', | |
'massupdate', | |
'import', | |
); | |
// has to match on all conditions | |
protected $bean_lock_mappings = array( | |
'Cases' => array('status' => 'Closed', 'type_c' => 'Technical Support'), | |
); | |
// our custom method to check permissions | |
protected function _canUserWrite($context) | |
{ | |
// retrieve user from context | |
$user = $this->getCurrentUser($context); | |
if($user->isAdmin() || in_array($user->id, $this->user_ids_to_allow)) { | |
return true; | |
} else { | |
// check additional beans conditions here | |
// is there a bean? | |
if(!empty($context['bean']) && is_object($context['bean']) && !empty($context['bean']->id)) { | |
// do we have a mapped known object instance? | |
if($context['bean'] instanceof SugarBean && !empty($context['bean']->module_dir) && !empty($this->bean_lock_mappings[$context['bean']->module_dir])) { | |
// do we have all matching fields for this object? | |
foreach($this->bean_lock_mappings[$context['bean']->module_dir] as $field => $value) { | |
// check if field is empty, as its value might not be loaded | |
if(empty($context['bean']->$field)) { | |
// retrieve the full bean as in some occastions (like listviews), not all fields are available on the context | |
$bean = BeanFactory::getBean($context['bean']->module_dir, $context['bean']->id); | |
} else { | |
$bean = $context['bean']; | |
} | |
if(empty($bean->$field) || $bean->$field != $value) { | |
// all conditions have to match, if any field is different from the condition or empty, allow | |
return true; | |
} | |
} | |
// default do not allow once here | |
return false; | |
} | |
} | |
return true; | |
} | |
} | |
// runtime access check | |
public function checkAccess($module, $view, $context) | |
{ | |
$view = SugarACLStrategy::fixUpActionName($view); | |
// if it is not a blocked action, or there is no bean, allow it | |
if(!in_array($view, $this->denied_actions) || !isset($context['bean'])) { | |
return true; | |
} | |
// can user write? | |
if($this->_canUserWrite($context)) return true; | |
// everyone else for everything else is denied | |
return false; | |
} | |
// mostly for front-end access checks (cached on the application, per user) | |
public function getUserAccess($module, $access_list = array(), $context = array()) | |
{ | |
// retrieve original ACL | |
$acl = parent::getUserAccess($module, $access_list, $context); | |
// if user can't write | |
if(!$this->_canUserWrite($context)) { | |
// override access, disable access where required if not admin and not special user | |
foreach($acl as $access => $value) { | |
if(in_array($access, $this->denied_actions)) { | |
$acl[$access] = 0; | |
} | |
} | |
} | |
// return modified acl | |
return $acl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment