3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
21 class CRM_Core_Permission_Base
{
24 * permission mapping to stub check() calls
27 public $permissions = NULL;
30 * Is this user someone with access for the entire system.
34 protected $_viewAdminUser = FALSE;
35 protected $_editAdminUser = FALSE;
38 * Am in in view permission or edit permission?
42 protected $_viewPermission = FALSE;
43 protected $_editPermission = FALSE;
46 * Translate permission.
49 * Permission string e.g "administer CiviCRM", "cms:access user record", "Drupal:administer content",
50 * "Joomla:action:com_asset"
52 * @param string $nativePrefix
54 * Array($portableName => $nativeName).
59 public function translatePermission($perm, $nativePrefix, $map) {
60 [$civiPrefix, $name] = CRM_Utils_String
::parsePrefix(':', $perm, NULL);
61 switch ($civiPrefix) {
67 return CRM_Utils_Array
::value($name, $map, CRM_Core_Permission
::ALWAYS_DENY_PERMISSION
);
73 return CRM_Core_Permission
::ALWAYS_DENY_PERMISSION
;
78 * Get the maximum permission of the current user with respect to _any_ contact records.
80 * @return int|string|null
81 * @see \CRM_Core_Permission::getPermission()
83 public function getPermission() {
86 if ($this->_editPermission
) {
87 return CRM_Core_Permission
::EDIT
;
89 elseif ($this->_viewPermission
) {
90 return CRM_Core_Permission
::VIEW
;
96 * Get the permissioned where clause for the user.
99 * The type of permission needed.
100 * @param array $tables
101 * (reference ) add the tables that are needed for the select clause.
102 * @param array $whereTables
103 * (reference ) add the tables that are needed for the where clause.
106 * the group where clause for this user
108 public function whereClause($type, &$tables, &$whereTables) {
113 * Get the permissioned where clause for the user when trying to see groups.
116 * The type of permission needed.
117 * @param array $tables
118 * (reference ) add the tables that are needed for the select clause.
119 * @param array $whereTables
120 * (reference ) add the tables that are needed for the where clause.
123 * the group where clause for this user
125 public function getPermissionedStaticGroupClause($type, &$tables, &$whereTables) {
127 return $this->groupClause($type, $tables, $whereTables);
131 * Get all groups from database, filtered by permissions
134 * @param string $groupType
135 * Type of group(Access/Mailing).
136 * @param bool $excludeHidden
137 * exclude hidden groups.
141 * array reference of all groups.
143 public function group($groupType = NULL, $excludeHidden = TRUE) {
144 $userId = CRM_Core_Session
::getLoggedInContactID();
145 $domainId = CRM_Core_Config
::domainID();
146 if (!isset(Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId])) {
147 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId] = Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId] = [];
150 $groupKey = $groupType ?
$groupType : 'all';
152 if (!isset(Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) {
153 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = [];
155 $groups = CRM_Core_PseudoConstant
::allGroup($groupType, $excludeHidden);
157 if ($this->check('edit all contacts')) {
158 // this is the most powerful permission, so we return
159 // immediately rather than dilute it further
160 $this->_editAdminUser
= $this->_viewAdminUser
= TRUE;
161 $this->_editPermission
= $this->_viewPermission
= TRUE;
162 Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups;
163 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups;
164 return Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey];
166 elseif ($this->check('view all contacts')) {
167 $this->_viewAdminUser
= TRUE;
168 $this->_viewPermission
= TRUE;
169 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups;
172 $ids = CRM_ACL_API
::group(CRM_Core_Permission
::VIEW
, NULL, 'civicrm_saved_search', $groups);
174 foreach (array_values($ids) as $id) {
175 $title = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Group', $id, 'title');
176 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title;
177 $this->_viewPermission
= TRUE;
181 $ids = CRM_ACL_API
::group(CRM_Core_Permission
::EDIT
, NULL, 'civicrm_saved_search', $groups);
183 foreach (array_values($ids) as $id) {
184 $title = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Group', $id, 'title');
185 Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title;
186 Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title;
187 $this->_editPermission
= TRUE;
188 $this->_viewPermission
= TRUE;
193 return Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey];
197 * Get group clause for this user.
200 * The type of permission needed.
201 * @param array $tables
202 * (reference ) add the tables that are needed for the select clause.
203 * @param array $whereTables
204 * (reference ) add the tables that are needed for the where clause.
207 * the group where clause for this user
209 public function groupClause($type, &$tables, &$whereTables) {
210 $userId = CRM_Core_Session
::getLoggedInContactID();
211 $domainId = CRM_Core_Config
::domainID();
212 if (!isset(Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId])) {
216 // we basically get all the groups here
218 if ($type == CRM_Core_Permission
::EDIT
) {
219 if ($this->_editAdminUser
) {
222 elseif (empty(Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) {
227 $groups = implode(', ', Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]);
228 $clauses[] = ' ( civicrm_group_contact.group_id IN ( ' . implode(', ', array_keys(Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) . " ) AND civicrm_group_contact.status = 'Added' ) ";
229 $tables['civicrm_group_contact'] = 1;
230 $whereTables['civicrm_group_contact'] = 1;
232 // foreach group that is potentially a saved search, add the saved search clause
233 foreach (array_keys(Civi
::$statics[__CLASS__
]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]) as $id) {
234 $group = new CRM_Contact_DAO_Group();
236 if ($group->find(TRUE) && $group->saved_search_id
) {
237 $clause = CRM_Contact_BAO_SavedSearch
::whereClause($group->saved_search_id
,
242 $clauses[] = $clause;
246 $clause = ' ( ' . implode(' OR ', $clauses) . ' ) ';
250 if ($this->_viewAdminUser
) {
253 elseif (empty(Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) {
258 $groups = implode(', ', Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]);
259 $clauses[] = ' civicrm_group.id IN (' . implode(', ', array_keys(Civi
::$statics[__CLASS__
]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) . " ) ";
260 $tables['civicrm_group'] = 1;
261 $whereTables['civicrm_group'] = 1;
262 $clause = ' ( ' . implode(' OR ', $clauses) . ' ) ';
269 * Given a permission string, check for access requirements
272 * The permission to check.
278 public function check($str, $userId = NULL) {
279 //no default behaviour
284 * Given a roles array, check for access requirements
286 * @param array $array
287 * The roles to check.
290 * true if yes, else false
292 public function checkGroupRole($array) {
297 * Get the palette of available permissions in the CMS's user-management system.
300 * List of permissions, keyed by symbolic name. Each item may have fields:
302 * - description: string
304 * The permission-name should correspond to the Civi notation used by
305 * 'CRM_Core_Permission::check()'. For CMS-specific permissions, these are
306 * translated names (eg "WordPress:list_users" or "Drupal:post comments").
308 * The list should include *only* CMS permissions. Exclude Civi-native permissions.
310 * @see \CRM_Core_Permission_Base::translatePermission()
312 public function getAvailablePermissions() {
317 * Get all the contact emails for users that have a specific permission.
319 * @param string $permissionName
320 * Name of the permission we are interested in.
322 * @throws CRM_Core_Exception.
324 public function permissionEmails($permissionName) {
325 throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
329 * Get all the contact emails for users that have a specific role.
331 * @param string $roleName
332 * Name of the role we are interested in.
334 * @throws CRM_Core_Exception.
336 public function roleEmails($roleName) {
337 throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
341 * Determine whether the permission store allows us to store
342 * a list of permissions generated dynamically (eg by
343 * hook_civicrm_permissions.)
347 public function isModulePermissionSupported() {
352 * Ensure that the CMS supports all the permissions defined by CiviCRM
353 * and its extensions. If there are stale permissions, they should be
354 * deleted. This is useful during module upgrade when the newer module
355 * version has removed permission that were defined in the older version.
357 * @param array $permissions
358 * Same format as CRM_Core_Permission::getCorePermissions().
360 * @throws CRM_Core_Exception
361 * @see CRM_Core_Permission::getCorePermissions
363 public function upgradePermissions($permissions) {
364 throw new CRM_Core_Exception("Unimplemented method: CRM_Core_Permission_*::upgradePermissions");
368 * Get the permissions defined in the hook_civicrm_permission implementation
369 * of the given module.
371 * Note: At time of writing, this is only used with native extension-modules, so
372 * there's one, predictable calling convention (regardless of CMS).
377 * Array of permissions, in the same format as CRM_Core_Permission::getCorePermissions().
378 * @see CRM_Core_Permission::getCorePermissions
380 public function getModulePermissions($module): array {
381 $return_permissions = [];
382 $fn_name = "{$module}_civicrm_permission";
383 if (function_exists($fn_name)) {
384 $module_permissions = [];
385 $fn_name($module_permissions);
386 $return_permissions = $module_permissions;
388 return $return_permissions;
392 * Get the permissions defined in the hook_civicrm_permission implementation
393 * in all enabled CiviCRM module extensions.
395 * @param bool $descriptions
398 * Array of permissions, in the same format as CRM_Core_Permission::getCorePermissions().
400 public function getAllModulePermissions($descriptions = FALSE): array {
402 CRM_Utils_Hook
::permission($permissions);
405 foreach ($permissions as $permission => $label) {
406 $permissions[$permission] = (is_array($label)) ?
$label : [$label];
410 // Passing in false here is to be deprecated.
411 foreach ($permissions as $permission => $label) {
412 $permissions[$permission] = (is_array($label)) ?
array_shift($label) : $label;