Queue APIv4 - Expose basic CRUD for queues (5.47 variant)
[civicrm-core.git] / CRM / Core / Permission.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
19 * This is the basic permission class wrapper
20 */
21class CRM_Core_Permission {
22
23 /**
d09edf64 24 * Static strings used to compose permissions.
6a488035
TO
25 *
26 * @const
27 * @var string
28 */
7da04cde 29 const EDIT_GROUPS = 'edit contacts in ', VIEW_GROUPS = 'view contacts in ';
6a488035
TO
30
31 /**
d09edf64 32 * The various type of permissions.
6a488035
TO
33 *
34 * @var int
35 */
7da04cde 36 const EDIT = 1, VIEW = 2, DELETE = 3, CREATE = 4, SEARCH = 5, ALL = 6, ADMIN = 7;
6a488035 37
085823c1 38 /**
d09edf64 39 * A placeholder permission which always fails.
085823c1
TO
40 */
41 const ALWAYS_DENY_PERMISSION = "*always deny*";
42
43 /**
d09edf64 44 * A placeholder permission which always fails.
085823c1
TO
45 */
46 const ALWAYS_ALLOW_PERMISSION = "*always allow*";
47
6dd18b98 48 /**
d09edf64 49 * Various authentication sources.
6dd18b98
DS
50 *
51 * @var int
52 */
7da04cde 53 const AUTH_SRC_UNKNOWN = 0, AUTH_SRC_CHECKSUM = 1, AUTH_SRC_SITEKEY = 2, AUTH_SRC_LOGIN = 4;
6dd18b98 54
6a488035 55 /**
d09edf64 56 * Get the current permission of this user.
6a488035 57 *
a6c01b45
CW
58 * @return string
59 * the permission of the user (edit or view or null)
6a488035
TO
60 */
61 public static function getPermission() {
62 $config = CRM_Core_Config::singleton();
41f314b6 63 return $config->userPermissionClass->getPermission();
6a488035
TO
64 }
65
66 /**
100fef9d 67 * Given a permission string or array, check for access requirements
6a488035 68 *
9b61e85d
CW
69 * Ex 1: Must have 'access CiviCRM'
70 * (string) 'access CiviCRM'
60ec9f43 71 *
b6e769ac
JM
72 * Ex 2: Must have 'access CiviCRM' and 'access AJAX API'
73 * ['access CiviCRM', 'access AJAX API']
60ec9f43 74 *
b6e769ac 75 * Ex 3: Must have 'access CiviCRM' or 'access AJAX API'
9b61e85d 76 * [
b6e769ac 77 * ['access CiviCRM', 'access AJAX API'],
9b61e85d 78 * ],
60ec9f43 79 *
b6e769ac 80 * Ex 4: Must have 'access CiviCRM' or 'access AJAX API' AND 'access CiviEvent'
9b61e85d 81 * [
b6e769ac 82 * ['access CiviCRM', 'access AJAX API'],
9b61e85d
CW
83 * 'access CiviEvent',
84 * ],
60ec9f43 85 *
9b61e85d
CW
86 * Note that in permissions.php this is keyed by the action eg.
87 * (access Civi || access AJAX) && (access CiviEvent || access CiviContribute)
88 * 'myaction' => [
b6e769ac 89 * ['access CiviCRM', 'access AJAX API'],
9b61e85d
CW
90 * ['access CiviEvent', 'access CiviContribute']
91 * ],
60ec9f43 92 *
9b61e85d
CW
93 * @param string|array $permissions
94 * The permission to check as an array or string -see examples.
60ec9f43 95 *
9b61e85d
CW
96 * @param int $contactId
97 * Contact id to check permissions for. Defaults to current logged-in user.
6a488035 98 *
acb1052e 99 * @return bool
9b61e85d 100 * true if contact has permission(s), else false
6a488035 101 */
18be3201 102 public static function check($permissions, $contactId = NULL) {
60ec9f43 103 $permissions = (array) $permissions;
9b61e85d 104 $userId = CRM_Core_BAO_UFMatch::getUFId($contactId);
60ec9f43 105
18be3201 106 /** @var CRM_Core_Permission_Temp $tempPerm */
59735506
TO
107 $tempPerm = CRM_Core_Config::singleton()->userPermissionTemp;
108
60ec9f43 109 foreach ($permissions as $permission) {
22e263ad 110 if (is_array($permission)) {
60ec9f43 111 foreach ($permission as $orPerm) {
18be3201 112 if (self::check($orPerm, $contactId)) {
60ec9f43 113 //one of our 'or' permissions has succeeded - stop checking this permission
b8a19656 114 return TRUE;
60ec9f43
E
115 }
116 }
117 //none of our our conditions was met
118 return FALSE;
119 }
120 else {
3ae62cab 121 // This is an individual permission
755a1835 122 $impliedPermissions = self::getImpliedPermissionsFor($permission);
123 $impliedPermissions[] = $permission;
124 foreach ($impliedPermissions as $permissionOption) {
125 $granted = CRM_Core_Config::singleton()->userPermissionClass->check($permissionOption, $userId);
126 // Call the permission_check hook to permit dynamic escalation (CRM-19256)
127 CRM_Utils_Hook::permission_check($permissionOption, $granted, $contactId);
128 if ($granted) {
129 break;
130 }
131 }
132
59735506 133 if (
3ae62cab 134 !$granted
59735506
TO
135 && !($tempPerm && $tempPerm->check($permission))
136 ) {
60ec9f43
E
137 //one of our 'and' conditions has not been met
138 return FALSE;
139 }
140 }
141 }
142 return TRUE;
6a488035
TO
143 }
144
dc92f2f8 145 /**
d09edf64 146 * Determine if any one of the permissions strings applies to current user.
dc92f2f8
TO
147 *
148 * @param array $perms
149 * @return bool
150 */
151 public static function checkAnyPerm($perms) {
152 foreach ($perms as $perm) {
153 if (CRM_Core_Permission::check($perm)) {
154 return TRUE;
155 }
156 }
157 return FALSE;
158 }
159
6a488035
TO
160 /**
161 * Given a group/role array, check for access requirements
162 *
6a0b768e
TO
163 * @param array $array
164 * The group/role to check.
6a488035 165 *
acb1052e 166 * @return bool
a6c01b45 167 * true if yes, else false
6a488035 168 */
00be9182 169 public static function checkGroupRole($array) {
6a488035 170 $config = CRM_Core_Config::singleton();
41f314b6 171 return $config->userPermissionClass->checkGroupRole($array);
6a488035
TO
172 }
173
174 /**
d09edf64 175 * Get the permissioned where clause for the user.
6a488035 176 *
6a0b768e
TO
177 * @param int $type
178 * The type of permission needed.
179 * @param array $tables
180 * (reference ) add the tables that are needed for the select clause.
181 * @param array $whereTables
182 * (reference ) add the tables that are needed for the where clause.
6a488035 183 *
a6c01b45
CW
184 * @return string
185 * the group where clause for this user
6a488035
TO
186 */
187 public static function getPermissionedStaticGroupClause($type, &$tables, &$whereTables) {
188 $config = CRM_Core_Config::singleton();
41f314b6 189 return $config->userPermissionClass->getPermissionedStaticGroupClause($type, $tables, $whereTables);
6a488035
TO
190 }
191
192 /**
193 * Get all groups from database, filtered by permissions
194 * for this user
195 *
6a0b768e
TO
196 * @param string $groupType
197 * Type of group(Access/Mailing).
3f8d2862
CW
198 * @param bool $excludeHidden
199 * exclude hidden groups.
6a488035 200 *
6a488035 201 *
a6c01b45
CW
202 * @return array
203 * array reference of all groups.
6a488035
TO
204 */
205 public static function group($groupType, $excludeHidden = TRUE) {
206 $config = CRM_Core_Config::singleton();
41f314b6 207 return $config->userPermissionClass->group($groupType, $excludeHidden);
6a488035
TO
208 }
209
a0ee3941 210 /**
317103ab 211 * @param int $userId
a0ee3941
EM
212 * @return bool
213 */
317103ab 214 public static function customGroupAdmin($userId = NULL) {
6a488035
TO
215 // check if user has all powerful permission
216 // or administer civicrm permission (CRM-1905)
317103ab 217 if (self::check('access all custom data', $userId)) {
6a488035
TO
218 return TRUE;
219 }
220
634e1a1a 221 if (
317103ab 222 self::check('administer Multiple Organizations', $userId) &&
6a488035
TO
223 self::isMultisiteEnabled()
224 ) {
225 return TRUE;
226 }
227
317103ab 228 if (self::check('administer CiviCRM data', $userId)) {
6a488035
TO
229 return TRUE;
230 }
231
232 return FALSE;
233 }
234
a0ee3941
EM
235 /**
236 * @param int $type
237 * @param bool $reset
317103ab 238 * @param int $userId
a0ee3941
EM
239 *
240 * @return array
241 */
317103ab 242 public static function customGroup($type = CRM_Core_Permission::VIEW, $reset = FALSE, $userId = NULL) {
41f314b6 243 $customGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_CustomField', 'custom_group_id',
be2fb01f
CW
244 ['fresh' => $reset]);
245 $defaultGroups = [];
6a488035
TO
246
247 // check if user has all powerful permission
248 // or administer civicrm permission (CRM-1905)
317103ab
CW
249 if (self::customGroupAdmin($userId)) {
250 return array_keys($customGroups);
6a488035
TO
251 }
252
317103ab 253 return CRM_ACL_API::group($type, $userId, 'civicrm_custom_group', $customGroups, $defaultGroups);
6a488035
TO
254 }
255
a0ee3941
EM
256 /**
257 * @param int $type
258 * @param null $prefix
259 * @param bool $reset
260 *
261 * @return string
262 */
00be9182 263 public static function customGroupClause($type = CRM_Core_Permission::VIEW, $prefix = NULL, $reset = FALSE) {
6a488035
TO
264 if (self::customGroupAdmin()) {
265 return ' ( 1 ) ';
266 }
267
268 $groups = self::customGroup($type, $reset);
269 if (empty($groups)) {
270 return ' ( 0 ) ';
271 }
272 else {
273 return "{$prefix}id IN ( " . implode(',', $groups) . ' ) ';
274 }
275 }
276
a0ee3941 277 /**
100fef9d 278 * @param int $gid
a0ee3941
EM
279 * @param int $type
280 *
281 * @return bool
282 */
6a488035
TO
283 public static function ufGroupValid($gid, $type = CRM_Core_Permission::VIEW) {
284 if (empty($gid)) {
285 return TRUE;
286 }
287
288 $groups = self::ufGroup($type);
63d76404 289 return !empty($groups) && in_array($gid, $groups);
6a488035
TO
290 }
291
a0ee3941
EM
292 /**
293 * @param int $type
294 *
295 * @return array
296 */
6a488035 297 public static function ufGroup($type = CRM_Core_Permission::VIEW) {
ff4f7744 298 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
299
300 $allGroups = array_keys($ufGroups);
301
302 // check if user has all powerful permission
303 if (self::check('profile listings and forms')) {
304 return $allGroups;
305 }
306
307 switch ($type) {
308 case CRM_Core_Permission::VIEW:
309 if (self::check('profile view')) {
310 return $allGroups;
311 }
312 break;
313
314 case CRM_Core_Permission::CREATE:
315 if (self::check('profile create')) {
316 return $allGroups;
317 }
318 break;
319
320 case CRM_Core_Permission::EDIT:
321 if (self::check('profile edit')) {
322 return $allGroups;
323 }
324 break;
325
326 case CRM_Core_Permission::SEARCH:
327 if (self::check('profile listings')) {
328 return $allGroups;
329 }
330 break;
331 }
332
333 return CRM_ACL_API::group($type, NULL, 'civicrm_uf_group', $ufGroups);
334 }
335
a0ee3941
EM
336 /**
337 * @param int $type
338 * @param null $prefix
339 * @param bool $returnUFGroupIds
340 *
341 * @return array|string
342 */
00be9182 343 public static function ufGroupClause($type = CRM_Core_Permission::VIEW, $prefix = NULL, $returnUFGroupIds = FALSE) {
6a488035
TO
344 $groups = self::ufGroup($type);
345 if ($returnUFGroupIds) {
346 return $groups;
347 }
348 elseif (empty($groups)) {
349 return ' ( 0 ) ';
350 }
351 else {
352 return "{$prefix}id IN ( " . implode(',', $groups) . ' ) ';
353 }
354 }
355
a0ee3941
EM
356 /**
357 * @param int $type
100fef9d 358 * @param int $eventID
a0ee3941
EM
359 * @param string $context
360 *
361 * @return array|null
362 */
e2d09ab4 363 public static function event($type = CRM_Core_Permission::VIEW, $eventID = NULL, $context = '') {
22e263ad
TO
364 if (!empty($context)) {
365 if (CRM_Core_Permission::check($context)) {
e2d09ab4
EM
366 return TRUE;
367 }
368 }
6a488035 369 $events = CRM_Event_PseudoConstant::event(NULL, TRUE);
be2fb01f 370 $includeEvents = [];
6a488035
TO
371
372 // check if user has all powerful permission
373 if (self::check('register for events')) {
374 $includeEvents = array_keys($events);
375 }
376
377 if ($type == CRM_Core_Permission::VIEW &&
378 self::check('view event info')
379 ) {
380 $includeEvents = array_keys($events);
381 }
382
383 $permissionedEvents = CRM_ACL_API::group($type, NULL, 'civicrm_event', $events, $includeEvents);
384 if (!$eventID) {
385 return $permissionedEvents;
386 }
41f314b6 387 if (!empty($permissionedEvents)) {
2efcf0c2 388 return array_search($eventID, $permissionedEvents) === FALSE ? NULL : $eventID;
41f314b6 389 }
dfa720e7 390 return NULL;
6a488035
TO
391 }
392
a0ee3941
EM
393 /**
394 * @param int $type
395 * @param null $prefix
396 *
397 * @return string
398 */
00be9182 399 public static function eventClause($type = CRM_Core_Permission::VIEW, $prefix = NULL) {
6a488035
TO
400 $events = self::event($type);
401 if (empty($events)) {
402 return ' ( 0 ) ';
403 }
404 else {
405 return "{$prefix}id IN ( " . implode(',', $events) . ' ) ';
406 }
407 }
408
a0ee3941 409 /**
44d17ec8
BS
410 * Checks that component is enabled and optionally that user has basic perm.
411 *
412 * @param string $module
413 * Specifies the name of the CiviCRM component.
a0ee3941 414 * @param bool $checkPermission
44d17ec8
BS
415 * Check not only that module is enabled, but that user has necessary
416 * permission.
417 * @param bool $requireAllCasesPermOnCiviCase
418 * Significant only if $module == CiviCase
419 * Require "access all cases and activities", not just
420 * "access my cases and activities".
a0ee3941
EM
421 *
422 * @return bool
44d17ec8 423 * Access to specified $module is granted.
a0ee3941 424 */
44d17ec8 425 public static function access($module, $checkPermission = TRUE, $requireAllCasesPermOnCiviCase = FALSE) {
6a488035
TO
426 $config = CRM_Core_Config::singleton();
427
428 if (!in_array($module, $config->enableComponents)) {
429 return FALSE;
430 }
431
432 if ($checkPermission) {
44d17ec8
BS
433 switch ($module) {
434 case 'CiviCase':
435 $access_all_cases = CRM_Core_Permission::check("access all cases and activities");
436 $access_my_cases = CRM_Core_Permission::check("access my cases and activities");
437 return $access_all_cases || (!$requireAllCasesPermOnCiviCase && $access_my_cases);
438
439 case 'CiviCampaign':
440 return CRM_Core_Permission::check("administer $module");
441
442 default:
443 return CRM_Core_Permission::check("access $module");
6a488035
TO
444 }
445 }
446
447 return TRUE;
448 }
449
450 /**
d09edf64 451 * Check permissions for delete and edit actions.
6a488035 452 *
6a0b768e
TO
453 * @param string $module
454 * Component name.
455 * @param int $action
456 * Action to be check across component.
6a488035 457 *
77b97be7
EM
458 *
459 * @return bool
460 */
00be9182 461 public static function checkActionPermission($module, $action) {
6a488035
TO
462 //check delete related permissions.
463 if ($action & CRM_Core_Action::DELETE) {
464 $permissionName = "delete in $module";
465 }
466 else {
be2fb01f 467 $editPermissions = [
6a488035
TO
468 'CiviEvent' => 'edit event participants',
469 'CiviMember' => 'edit memberships',
470 'CiviPledge' => 'edit pledges',
471 'CiviContribute' => 'edit contributions',
472 'CiviGrant' => 'edit grants',
473 'CiviMail' => 'access CiviMail',
474 'CiviAuction' => 'add auction items',
be2fb01f 475 ];
9c1bc317 476 $permissionName = $editPermissions[$module] ?? NULL;
6a488035
TO
477 }
478
479 if ($module == 'CiviCase' && !$permissionName) {
480 return CRM_Case_BAO_Case::accessCiviCase();
481 }
482 else {
483 //check for permission.
484 return CRM_Core_Permission::check($permissionName);
485 }
486 }
487
a0ee3941
EM
488 /**
489 * @param $args
490 * @param string $op
491 *
492 * @return bool
493 */
00be9182 494 public static function checkMenu(&$args, $op = 'and') {
6a488035
TO
495 if (!is_array($args)) {
496 return $args;
497 }
498 foreach ($args as $str) {
499 $res = CRM_Core_Permission::check($str);
500 if ($op == 'or' && $res) {
501 return TRUE;
502 }
503 elseif ($op == 'and' && !$res) {
504 return FALSE;
505 }
506 }
507 return ($op == 'or') ? FALSE : TRUE;
508 }
509
a0ee3941
EM
510 /**
511 * @param $item
512 *
513 * @return bool|mixed
514 * @throws Exception
515 */
00be9182 516 public static function checkMenuItem(&$item) {
6a488035
TO
517 if (!array_key_exists('access_callback', $item)) {
518 CRM_Core_Error::backtrace();
79e11805 519 throw new CRM_Core_Exception('Missing Access Callback key in menu item');
6a488035
TO
520 }
521
522 // if component_id is present, ensure it is enabled
3d31a5c6
TO
523 if (isset($item['component_id']) && $item['component_id']) {
524 if (!isset(Civi::$statics[__CLASS__]['componentNameId'])) {
525 Civi::$statics[__CLASS__]['componentNameId'] = array_flip(CRM_Core_Component::getComponentIDs());
526 }
527 $componentName = Civi::$statics[__CLASS__]['componentNameId'][$item['component_id']];
528
6a488035 529 $config = CRM_Core_Config::singleton();
3d31a5c6 530 if (is_array($config->enableComponents) && in_array($componentName, $config->enableComponents)) {
6a488035
TO
531 // continue with process
532 }
533 else {
534 return FALSE;
535 }
536 }
537
538 // the following is imitating drupal 6 code in includes/menu.inc
539 if (empty($item['access_callback']) ||
540 is_numeric($item['access_callback'])
541 ) {
596a8bdf 542 return (bool) $item['access_callback'];
6a488035
TO
543 }
544
545 // check whether the following Ajax requests submitted the right key
546 // FIXME: this should be integrated into ACLs proper
547 if (CRM_Utils_Array::value('page_type', $item) == 3) {
548 if (!CRM_Core_Key::validate($_REQUEST['key'], $item['path'])) {
549 return FALSE;
550 }
551 }
552
553 // check if callback is for checkMenu, if so optimize it
554 if (is_array($item['access_callback']) &&
555 $item['access_callback'][0] == 'CRM_Core_Permission' &&
556 $item['access_callback'][1] == 'checkMenu'
557 ) {
558 $op = CRM_Utils_Array::value(1, $item['access_arguments'], 'and');
559 return self::checkMenu($item['access_arguments'][0], $op);
560 }
561 else {
562 return call_user_func_array($item['access_callback'], $item['access_arguments']);
563 }
564 }
565
a0ee3941
EM
566 /**
567 * @param bool $all
9476d8d1 568 * Include disabled components
221b21b4 569 * @param bool $descriptions
9476d8d1 570 * Whether to return descriptions
a0ee3941
EM
571 *
572 * @return array
573 */
9476d8d1 574 public static function basicPermissions($all = FALSE, $descriptions = FALSE) {
be2fb01f 575 $cacheKey = implode('-', [$all, $descriptions]);
9476d8d1
CW
576 if (empty(Civi::$statics[__CLASS__][__FUNCTION__][$cacheKey])) {
577 Civi::$statics[__CLASS__][__FUNCTION__][$cacheKey] = self::assembleBasicPermissions($all, $descriptions);
221b21b4 578 }
9476d8d1 579 return Civi::$statics[__CLASS__][__FUNCTION__][$cacheKey];
221b21b4
AH
580 }
581
582 /**
583 * @param bool $all
584 * @param bool $descriptions
585 * whether to return descriptions
586 *
587 * @return array
d2b6eac8 588 * @throws \CRM_Core_Exception
221b21b4 589 */
d2b6eac8 590 public static function assembleBasicPermissions($all = FALSE, $descriptions = FALSE): array {
591 $permissions = self::getCoreAndComponentPermissions($all);
221b21b4 592
b4d6a411 593 // Add any permissions defined in hook_civicrm_permission implementations.
1a1100ef 594 $module_permissions = CRM_Core_Config::singleton()->userPermissionClass->getAllModulePermissions(TRUE);
b4d6a411 595 $permissions = array_merge($permissions, $module_permissions);
8c282315 596 if (!$descriptions) {
597 foreach ($permissions as $name => $attr) {
598 $permissions[$name] = array_shift($attr);
599 }
600 }
6a488035
TO
601 return $permissions;
602 }
603
a0ee3941
EM
604 /**
605 * @return array
606 */
00be9182 607 public static function getAnonymousPermissionsWarnings() {
be2fb01f 608 static $permissions = [];
81bb85ea 609 if (empty($permissions)) {
be2fb01f 610 $permissions = [
21dfd5f5 611 'administer CiviCRM',
be2fb01f 612 ];
81bb85ea
AC
613 $components = CRM_Core_Component::getComponents();
614 foreach ($components as $comp) {
615 if (!method_exists($comp, 'getAnonymousPermissionWarnings')) {
616 continue;
617 }
618 $permissions = array_merge($permissions, $comp->getAnonymousPermissionWarnings());
619 }
620 }
621 return $permissions;
622 }
623
a0ee3941
EM
624 /**
625 * @param $anonymous_perms
626 *
627 * @return array
628 */
00be9182 629 public static function validateForPermissionWarnings($anonymous_perms) {
81bb85ea
AC
630 return array_intersect($anonymous_perms, self::getAnonymousPermissionsWarnings());
631 }
632
a0ee3941 633 /**
6793d6a9 634 * Get core permissions.
221b21b4 635 *
a0ee3941
EM
636 * @return array
637 */
8c282315 638 public static function getCorePermissions() {
6a488035 639 $prefix = ts('CiviCRM') . ': ';
be2fb01f
CW
640 $permissions = [
641 'add contacts' => [
221b21b4
AH
642 $prefix . ts('add contacts'),
643 ts('Create a new contact record in CiviCRM'),
be2fb01f
CW
644 ],
645 'view all contacts' => [
221b21b4
AH
646 $prefix . ts('view all contacts'),
647 ts('View ANY CONTACT in the CiviCRM database, export contact info and perform activities such as Send Email, Phone Call, etc.'),
be2fb01f
CW
648 ],
649 'edit all contacts' => [
221b21b4
AH
650 $prefix . ts('edit all contacts'),
651 ts('View, Edit and Delete ANY CONTACT in the CiviCRM database; Create and edit relationships, tags and other info about the contacts'),
be2fb01f
CW
652 ],
653 'view my contact' => [
221b21b4 654 $prefix . ts('view my contact'),
be2fb01f
CW
655 ],
656 'edit my contact' => [
221b21b4 657 $prefix . ts('edit my contact'),
be2fb01f
CW
658 ],
659 'delete contacts' => [
221b21b4 660 $prefix . ts('delete contacts'),
be2fb01f
CW
661 ],
662 'access deleted contacts' => [
221b21b4
AH
663 $prefix . ts('access deleted contacts'),
664 ts('Access contacts in the trash'),
be2fb01f
CW
665 ],
666 'import contacts' => [
221b21b4
AH
667 $prefix . ts('import contacts'),
668 ts('Import contacts and activities'),
be2fb01f
CW
669 ],
670 'import SQL datasource' => [
40bc3c68
TO
671 $prefix . ts('import SQL datasource'),
672 ts('When importing, consume data directly from a SQL datasource'),
be2fb01f
CW
673 ],
674 'edit groups' => [
221b21b4
AH
675 $prefix . ts('edit groups'),
676 ts('Create new groups, edit group settings (e.g. group name, visibility...), delete groups'),
be2fb01f
CW
677 ],
678 'administer CiviCRM' => [
221b21b4
AH
679 $prefix . ts('administer CiviCRM'),
680 ts('Perform all tasks in the Administer CiviCRM control panel and Import Contacts'),
be2fb01f
CW
681 ],
682 'skip IDS check' => [
221b21b4 683 $prefix . ts('skip IDS check'),
d9a37cbc 684 ts('Warning: Give to trusted roles only; this permission has security implications. IDS system is bypassed for users with this permission. Prevents false errors for admin users.'),
be2fb01f
CW
685 ],
686 'access uploaded files' => [
221b21b4
AH
687 $prefix . ts('access uploaded files'),
688 ts('View / download files including images and photos'),
be2fb01f
CW
689 ],
690 'profile listings and forms' => [
221b21b4 691 $prefix . ts('profile listings and forms'),
d9a37cbc 692 ts('Warning: Give to trusted roles only; this permission has privacy implications. Add/edit data in online forms and access public searchable directories.'),
be2fb01f
CW
693 ],
694 'profile listings' => [
221b21b4 695 $prefix . ts('profile listings'),
d9a37cbc 696 ts('Warning: Give to trusted roles only; this permission has privacy implications. Access public searchable directories.'),
be2fb01f
CW
697 ],
698 'profile create' => [
221b21b4 699 $prefix . ts('profile create'),
d9a37cbc 700 ts('Add data in a profile form.'),
be2fb01f
CW
701 ],
702 'profile edit' => [
221b21b4 703 $prefix . ts('profile edit'),
d9a37cbc 704 ts('Edit data in a profile form.'),
be2fb01f
CW
705 ],
706 'profile view' => [
221b21b4 707 $prefix . ts('profile view'),
d9a37cbc 708 ts('View data in a profile.'),
be2fb01f
CW
709 ],
710 'access all custom data' => [
221b21b4
AH
711 $prefix . ts('access all custom data'),
712 ts('View all custom fields regardless of ACL rules'),
be2fb01f
CW
713 ],
714 'view all activities' => [
221b21b4
AH
715 $prefix . ts('view all activities'),
716 ts('View all activities (for visible contacts)'),
be2fb01f
CW
717 ],
718 'delete activities' => [
221b21b4 719 $prefix . ts('Delete activities'),
be2fb01f
CW
720 ],
721 'edit inbound email basic information' => [
ee90a98c
CR
722 $prefix . ts('edit inbound email basic information'),
723 ts('Edit all inbound email activities (for visible contacts) basic information. Content editing not allowed.'),
be2fb01f
CW
724 ],
725 'edit inbound email basic information and content' => [
ee90a98c
CR
726 $prefix . ts('edit inbound email basic information and content'),
727 ts('Edit all inbound email activities (for visible contacts) basic information and content.'),
be2fb01f
CW
728 ],
729 'access CiviCRM' => [
d9a37cbc
H
730 $prefix . ts('access CiviCRM backend and API'),
731 ts('Master control for access to the main CiviCRM backend and API. Give to trusted roles only.'),
be2fb01f
CW
732 ],
733 'access Contact Dashboard' => [
221b21b4
AH
734 $prefix . ts('access Contact Dashboard'),
735 ts('View Contact Dashboard (for themselves and visible contacts)'),
be2fb01f
CW
736 ],
737 'translate CiviCRM' => [
221b21b4
AH
738 $prefix . ts('translate CiviCRM'),
739 ts('Allow User to enable multilingual'),
be2fb01f
CW
740 ],
741 'manage tags' => [
eaaaef83
I
742 $prefix . ts('manage tags'),
743 ts('Create and rename tags'),
be2fb01f
CW
744 ],
745 'administer reserved groups' => [
221b21b4
AH
746 $prefix . ts('administer reserved groups'),
747 ts('Edit and disable Reserved Groups (Needs Edit Groups)'),
be2fb01f
CW
748 ],
749 'administer Tagsets' => [
221b21b4 750 $prefix . ts('administer Tagsets'),
be2fb01f
CW
751 ],
752 'administer reserved tags' => [
221b21b4 753 $prefix . ts('administer reserved tags'),
be2fb01f 754 ],
d76345c9
TO
755 'administer queues' => [
756 $prefix . ts('administer queues'),
757 ts('Initialize, browse, and cancel background processing queues'),
758 // At time of writing, we have specifically omitted the ability to edit fine-grained
759 // data about specific queue-tasks. Tasks are usually defined as PHP callables...
760 // and one should hesitate before allowing open-ended edits of PHP callables.
761 // However, it seems fine for web-admins to browse and cancel these things.
762 ],
be2fb01f 763 'administer dedupe rules' => [
221b21b4
AH
764 $prefix . ts('administer dedupe rules'),
765 ts('Create and edit rules, change the supervised and unsupervised rules'),
be2fb01f
CW
766 ],
767 'merge duplicate contacts' => [
221b21b4
AH
768 $prefix . ts('merge duplicate contacts'),
769 ts('Delete Contacts must also be granted in order for this to work.'),
be2fb01f
CW
770 ],
771 'force merge duplicate contacts' => [
fd630ef9 772 $prefix . ts('force merge duplicate contacts'),
773 ts('Delete Contacts must also be granted in order for this to work.'),
be2fb01f
CW
774 ],
775 'view debug output' => [
221b21b4
AH
776 $prefix . ts('view debug output'),
777 ts('View results of debug and backtrace'),
be2fb01f 778 ],
02d451ab 779
be2fb01f 780 'view all notes' => [
221b21b4
AH
781 $prefix . ts('view all notes'),
782 ts("View notes (for visible contacts) even if they're marked admin only"),
be2fb01f
CW
783 ],
784 'add contact notes' => [
088101a4
O
785 $prefix . ts('add contact notes'),
786 ts("Create notes for contacts"),
be2fb01f
CW
787 ],
788 'access AJAX API' => [
221b21b4
AH
789 $prefix . ts('access AJAX API'),
790 ts('Allow API access even if Access CiviCRM is not granted'),
be2fb01f
CW
791 ],
792 'access contact reference fields' => [
221b21b4
AH
793 $prefix . ts('access contact reference fields'),
794 ts('Allow entering data into contact reference fields'),
be2fb01f
CW
795 ],
796 'create manual batch' => [
221b21b4
AH
797 $prefix . ts('create manual batch'),
798 ts('Create an accounting batch (with Access to CiviContribute and View Own/All Manual Batches)'),
be2fb01f
CW
799 ],
800 'edit own manual batches' => [
221b21b4
AH
801 $prefix . ts('edit own manual batches'),
802 ts('Edit accounting batches created by user'),
be2fb01f
CW
803 ],
804 'edit all manual batches' => [
221b21b4
AH
805 $prefix . ts('edit all manual batches'),
806 ts('Edit all accounting batches'),
be2fb01f
CW
807 ],
808 'close own manual batches' => [
47a98aef 809 $prefix . ts('close own manual batches'),
5ad18cc2 810 ts('Close accounting batches created by user (with Access to CiviContribute)'),
be2fb01f
CW
811 ],
812 'close all manual batches' => [
47a98aef 813 $prefix . ts('close all manual batches'),
5ad18cc2 814 ts('Close all accounting batches (with Access to CiviContribute)'),
be2fb01f
CW
815 ],
816 'reopen own manual batches' => [
47a98aef 817 $prefix . ts('reopen own manual batches'),
5ad18cc2 818 ts('Reopen accounting batches created by user (with Access to CiviContribute)'),
be2fb01f
CW
819 ],
820 'reopen all manual batches' => [
47a98aef 821 $prefix . ts('reopen all manual batches'),
5ad18cc2 822 ts('Reopen all accounting batches (with Access to CiviContribute)'),
be2fb01f
CW
823 ],
824 'view own manual batches' => [
221b21b4
AH
825 $prefix . ts('view own manual batches'),
826 ts('View accounting batches created by user (with Access to CiviContribute)'),
be2fb01f
CW
827 ],
828 'view all manual batches' => [
221b21b4
AH
829 $prefix . ts('view all manual batches'),
830 ts('View all accounting batches (with Access to CiviContribute)'),
be2fb01f
CW
831 ],
832 'delete own manual batches' => [
221b21b4
AH
833 $prefix . ts('delete own manual batches'),
834 ts('Delete accounting batches created by user'),
be2fb01f
CW
835 ],
836 'delete all manual batches' => [
221b21b4
AH
837 $prefix . ts('delete all manual batches'),
838 ts('Delete all accounting batches'),
be2fb01f
CW
839 ],
840 'export own manual batches' => [
221b21b4
AH
841 $prefix . ts('export own manual batches'),
842 ts('Export accounting batches created by user'),
be2fb01f
CW
843 ],
844 'export all manual batches' => [
221b21b4
AH
845 $prefix . ts('export all manual batches'),
846 ts('Export all accounting batches'),
be2fb01f
CW
847 ],
848 'administer payment processors' => [
221b21b4
AH
849 $prefix . ts('administer payment processors'),
850 ts('Add, Update, or Disable Payment Processors'),
be2fb01f 851 ],
ebd92daf
TO
852 'render templates' => [
853 $prefix . ts('render templates'),
854 ts('Render open-ended template content. (Additional constraints may apply to autoloaded records and specific notations.)'),
855 ],
be2fb01f 856 'edit message templates' => [
221b21b4 857 $prefix . ts('edit message templates'),
be2fb01f
CW
858 ],
859 'edit system workflow message templates' => [
40a732a9 860 $prefix . ts('edit system workflow message templates'),
be2fb01f
CW
861 ],
862 'edit user-driven message templates' => [
40a732a9 863 $prefix . ts('edit user-driven message templates'),
be2fb01f
CW
864 ],
865 'view my invoices' => [
a664e7b3 866 $prefix . ts('view my invoices'),
dc6b437a 867 ts('Allow users to view/ download their own invoices'),
be2fb01f
CW
868 ],
869 'edit api keys' => [
d4463076
TO
870 $prefix . ts('edit api keys'),
871 ts('Edit API keys'),
be2fb01f
CW
872 ],
873 'edit own api keys' => [
d4463076
TO
874 $prefix . ts('edit own api keys'),
875 ts('Edit user\'s own API keys'),
be2fb01f
CW
876 ],
877 'send SMS' => [
63483feb
MM
878 $prefix . ts('send SMS'),
879 ts('Send an SMS'),
be2fb01f 880 ],
755a1835 881 'administer CiviCRM system' => [
882 'label' => $prefix . ts('administer CiviCRM System'),
4c85c7b6 883 'description' => ts('Perform all system administration tasks in CiviCRM'),
755a1835 884 ],
885 'administer CiviCRM data' => [
886 'label' => $prefix . ts('administer CiviCRM Data'),
4c85c7b6 887 'description' => ts('Permit altering all restricted data options'),
755a1835 888 ],
ea54c6e5 889 'all CiviCRM permissions and ACLs' => [
890 'label' => $prefix . ts('all CiviCRM permissions and ACLs'),
891 'description' => ts('Administer and use CiviCRM bypassing any other permission or ACL checks and enabling the creation of displays and forms that allow others to bypass checks. This permission should be given out with care'),
892 ],
be2fb01f 893 ];
ce6b4d9b 894 if (self::isMultisiteEnabled()) {
895 // This could arguably be moved to the multisite extension but
896 // within core it does permit editing group-organization records.
897 $permissions['administer Multiple Organizations'] = [
898 'label' => $prefix . ts('administer Multiple Organizations'),
899 'description' => ts('Administer multiple organizations. In practice this allows editing the group organization link'),
900 ];
901 }
6a488035
TO
902 return $permissions;
903 }
904
755a1835 905 /**
906 * Get permissions implied by 'superset' permissions.
907 *
908 * @return array
909 */
ea54c6e5 910 public static function getImpliedAdminPermissions(): array {
755a1835 911 return [
ea54c6e5 912 'administer CiviCRM' => ['implied_permissions' => ['administer CiviCRM system', 'administer CiviCRM data']],
913 'administer CiviCRM data' => ['implied_permissions' => ['edit message templates', 'administer dedupe rules']],
914 'administer CiviCRM system' => ['implied_permissions' => ['edit system workflow message templates']],
755a1835 915 ];
916 }
917
918 /**
919 * Get any super-permissions that imply the given permission.
920 *
921 * @param string $permission
922 *
923 * @return array
924 */
ea54c6e5 925 public static function getImpliedPermissionsFor(string $permission): array {
709672c6 926 if (in_array($permission[0], ['@', '*'], TRUE)) {
927 // Special permissions like '*always deny*' - see DynamicFKAuthorizationTest.
928 // Also '@afform - see AfformUsageTest.
929 return [];
930 }
ea54c6e5 931 $implied = Civi::cache('metadata')->get('implied_permissions', []);
932 if (isset($implied[$permission])) {
933 return $implied[$permission];
934 }
709672c6 935 $implied[$permission] = ['all CiviCRM permissions and ACLs'];
936 foreach (self::getImpliedAdminPermissions() as $key => $details) {
ea54c6e5 937 if (in_array($permission, $details['implied_permissions'] ?? [], TRUE)) {
938 $implied[$permission][] = $key;
755a1835 939 }
940 }
ea54c6e5 941 Civi::cache('metadata')->set('implied_permissions', $implied);
942 return $implied[$permission];
755a1835 943 }
944
bf9a7c0f
ES
945 /**
946 * For each entity provides an array of permissions required for each action
947 *
948 * The action is the array key, possible values:
949 * * create: applies to create (with no id in params)
950 * * update: applies to update, setvalue, create (with id in params)
951 * * get: applies to getcount, getsingle, getvalue and other gets
952 * * delete: applies to delete, replace
953 * * meta: applies to getfields, getoptions, getspec
954 * * default: catch-all for anything not declared
955 *
956 * Note: some APIs declare other actions as well
957 *
958 * Permissions should use arrays for AND and arrays of arrays for OR
1a5a2ade 959 * @see CRM_Core_Permission::check
bf9a7c0f
ES
960 *
961 * @return array of permissions
962 */
963 public static function getEntityActionPermissions() {
be2fb01f 964 $permissions = [];
bf9a7c0f
ES
965 // These are the default permissions - if any entity does not declare permissions for a given action,
966 // (or the entity does not declare permissions at all) - then the action will be used from here
be2fb01f 967 $permissions['default'] = [
bf9a7c0f 968 // applies to getfields, getoptions, etc.
be2fb01f 969 'meta' => ['access CiviCRM'],
bf9a7c0f
ES
970 // catch-all, applies to create, get, delete, etc.
971 // If an entity declares it's own 'default' action it will override this one
be2fb01f
CW
972 'default' => ['administer CiviCRM'],
973 ];
bf9a7c0f
ES
974
975 // Note: Additional permissions in DynamicFKAuthorization
be2fb01f
CW
976 $permissions['attachment'] = [
977 'default' => [
978 ['access CiviCRM', 'access AJAX API'],
979 ],
980 ];
bf9a7c0f
ES
981
982 // Contact permissions
be2fb01f
CW
983 $permissions['contact'] = [
984 'create' => [
bf9a7c0f
ES
985 'access CiviCRM',
986 'add contacts',
be2fb01f
CW
987 ],
988 'delete' => [
bf9a7c0f
ES
989 'access CiviCRM',
990 'delete contacts',
be2fb01f 991 ],
bf9a7c0f 992 // managed by query object
be2fb01f 993 'get' => [],
bf9a7c0f 994 // managed by _civicrm_api3_check_edit_permissions
be2fb01f
CW
995 'update' => [],
996 'getquick' => [
997 ['access CiviCRM', 'access AJAX API'],
998 ],
999 'duplicatecheck' => [
f257308b 1000 'access CiviCRM',
be2fb01f 1001 ],
9f8c8b7a 1002 'merge' => ['merge duplicate contacts'],
be2fb01f 1003 ];
bf9a7c0f 1004
cc477693 1005 $permissions['dedupe'] = [
1006 'getduplicates' => ['access CiviCRM'],
3ea6ec7d 1007 'getstatistics' => ['access CiviCRM'],
cc477693 1008 ];
1009
bf9a7c0f 1010 // CRM-16963 - Permissions for country.
be2fb01f
CW
1011 $permissions['country'] = [
1012 'get' => [
bf9a7c0f 1013 'access CiviCRM',
be2fb01f
CW
1014 ],
1015 'default' => [
bf9a7c0f 1016 'administer CiviCRM',
be2fb01f
CW
1017 ],
1018 ];
bf9a7c0f
ES
1019
1020 // Contact-related data permissions.
be2fb01f 1021 $permissions['address'] = [
bf9a7c0f
ES
1022 // get is managed by BAO::addSelectWhereClause
1023 // create/delete are managed by _civicrm_api3_check_edit_permissions
be2fb01f
CW
1024 'default' => [],
1025 ];
bf9a7c0f
ES
1026 $permissions['email'] = $permissions['address'];
1027 $permissions['phone'] = $permissions['address'];
1028 $permissions['website'] = $permissions['address'];
1029 $permissions['im'] = $permissions['address'];
1030 $permissions['open_i_d'] = $permissions['address'];
1031
1032 // Also managed by ACLs - CRM-19448
be2fb01f 1033 $permissions['entity_tag'] = ['default' => []];
bf9a7c0f
ES
1034 $permissions['note'] = $permissions['entity_tag'];
1035
1036 // Allow non-admins to get and create tags to support tagset widget
1037 // Delete is still reserved for admins
be2fb01f
CW
1038 $permissions['tag'] = [
1039 'get' => ['access CiviCRM'],
1040 'create' => ['access CiviCRM'],
1041 'update' => ['access CiviCRM'],
1042 ];
bf9a7c0f
ES
1043
1044 //relationship permissions
be2fb01f 1045 $permissions['relationship'] = [
bf9a7c0f 1046 // get is managed by BAO::addSelectWhereClause
be2fb01f
CW
1047 'get' => [],
1048 'delete' => [
bf9a7c0f
ES
1049 'access CiviCRM',
1050 'edit all contacts',
be2fb01f
CW
1051 ],
1052 'default' => [
bf9a7c0f
ES
1053 'access CiviCRM',
1054 'edit all contacts',
be2fb01f
CW
1055 ],
1056 ];
bf9a7c0f
ES
1057
1058 // CRM-17741 - Permissions for RelationshipType.
be2fb01f
CW
1059 $permissions['relationship_type'] = [
1060 'get' => [
bf9a7c0f 1061 'access CiviCRM',
be2fb01f
CW
1062 ],
1063 'default' => [
bf9a7c0f 1064 'administer CiviCRM',
be2fb01f
CW
1065 ],
1066 ];
bf9a7c0f
ES
1067
1068 // Activity permissions
be2fb01f
CW
1069 $permissions['activity'] = [
1070 'delete' => [
bf9a7c0f
ES
1071 'access CiviCRM',
1072 'delete activities',
be2fb01f
CW
1073 ],
1074 'get' => [
bf9a7c0f
ES
1075 'access CiviCRM',
1076 // Note that view all activities is also required within the api
1077 // if the id is not passed in. Where the id is passed in the activity
1078 // specific check functions are used and tested.
be2fb01f
CW
1079 ],
1080 'default' => [
bf9a7c0f
ES
1081 'access CiviCRM',
1082 'view all activities',
be2fb01f
CW
1083 ],
1084 ];
cdacd6ab 1085 $permissions['activity_contact'] = $permissions['activity'];
bf9a7c0f
ES
1086
1087 // Case permissions
be2fb01f
CW
1088 $permissions['case'] = [
1089 'create' => [
bf9a7c0f
ES
1090 'access CiviCRM',
1091 'add cases',
be2fb01f
CW
1092 ],
1093 'delete' => [
bf9a7c0f
ES
1094 'access CiviCRM',
1095 'delete in CiviCase',
be2fb01f
CW
1096 ],
1097 'restore' => [
8572e6de 1098 'administer CiviCase',
be2fb01f
CW
1099 ],
1100 'merge' => [
a6bc7218 1101 'administer CiviCase',
be2fb01f
CW
1102 ],
1103 'default' => [
bf9a7c0f 1104 // At minimum the user needs one of the following. Finer-grained access is controlled by CRM_Case_BAO_Case::addSelectWhereClause
be2fb01f
CW
1105 ['access my cases and activities', 'access all cases and activities'],
1106 ],
1107 ];
bf9a7c0f 1108 $permissions['case_contact'] = $permissions['case'];
7b52581f 1109 $permissions['case_activity'] = $permissions['case'];
bf9a7c0f 1110
be2fb01f
CW
1111 $permissions['case_type'] = [
1112 'default' => ['administer CiviCase'],
1113 'get' => [
bf9a7c0f 1114 // nested array = OR
be2fb01f
CW
1115 ['access my cases and activities', 'access all cases and activities'],
1116 ],
1117 ];
bf9a7c0f
ES
1118
1119 // Campaign permissions
be2fb01f
CW
1120 $permissions['campaign'] = [
1121 'get' => ['access CiviCRM'],
1122 'default' => [
bf9a7c0f 1123 // nested array = OR
be2fb01f
CW
1124 ['administer CiviCampaign', 'manage campaign'],
1125 ],
1126 ];
bf9a7c0f
ES
1127 $permissions['survey'] = $permissions['campaign'];
1128
1129 // Financial permissions
be2fb01f
CW
1130 $permissions['contribution'] = [
1131 'get' => [
bf9a7c0f
ES
1132 'access CiviCRM',
1133 'access CiviContribute',
be2fb01f
CW
1134 ],
1135 'delete' => [
bf9a7c0f
ES
1136 'access CiviCRM',
1137 'access CiviContribute',
1138 'delete in CiviContribute',
be2fb01f
CW
1139 ],
1140 'completetransaction' => [
bf9a7c0f 1141 'edit contributions',
be2fb01f
CW
1142 ],
1143 'default' => [
bf9a7c0f
ES
1144 'access CiviCRM',
1145 'access CiviContribute',
1146 'edit contributions',
be2fb01f
CW
1147 ],
1148 ];
bf9a7c0f 1149 $permissions['line_item'] = $permissions['contribution'];
7e49aa93 1150 $permissions['product'] = $permissions['contribution'];
bf9a7c0f 1151
ee73f136 1152 $permissions['financial_item'] = $permissions['contribution'];
87e130bb
EM
1153 $permissions['financial_type']['get'] = $permissions['contribution']['get'];
1154 $permissions['entity_financial_account']['get'] = $permissions['contribution']['get'];
1155 $permissions['financial_account']['get'] = $permissions['contribution']['get'];
6596faec 1156 $permissions['financial_trxn']['get'] = $permissions['contribution']['get'];
ee73f136 1157
bf9a7c0f 1158 // Payment permissions
be2fb01f
CW
1159 $permissions['payment'] = [
1160 'get' => [
bf9a7c0f
ES
1161 'access CiviCRM',
1162 'access CiviContribute',
be2fb01f
CW
1163 ],
1164 'delete' => [
bf9a7c0f
ES
1165 'access CiviCRM',
1166 'access CiviContribute',
1167 'delete in CiviContribute',
be2fb01f
CW
1168 ],
1169 'cancel' => [
bf9a7c0f
ES
1170 'access CiviCRM',
1171 'access CiviContribute',
1172 'edit contributions',
be2fb01f
CW
1173 ],
1174 'create' => [
bf9a7c0f
ES
1175 'access CiviCRM',
1176 'access CiviContribute',
1177 'edit contributions',
be2fb01f
CW
1178 ],
1179 'default' => [
bf9a7c0f
ES
1180 'access CiviCRM',
1181 'access CiviContribute',
1182 'edit contributions',
be2fb01f
CW
1183 ],
1184 ];
e4124a88 1185 $permissions['contribution_recur'] = $permissions['payment'];
bf9a7c0f
ES
1186
1187 // Custom field permissions
be2fb01f
CW
1188 $permissions['custom_field'] = [
1189 'default' => [
bf9a7c0f
ES
1190 'administer CiviCRM',
1191 'access all custom data',
be2fb01f
CW
1192 ],
1193 ];
bf9a7c0f
ES
1194 $permissions['custom_group'] = $permissions['custom_field'];
1195
1196 // Event permissions
be2fb01f
CW
1197 $permissions['event'] = [
1198 'create' => [
bf9a7c0f
ES
1199 'access CiviCRM',
1200 'access CiviEvent',
1201 'edit all events',
be2fb01f
CW
1202 ],
1203 'delete' => [
bf9a7c0f
ES
1204 'access CiviCRM',
1205 'access CiviEvent',
1206 'delete in CiviEvent',
be2fb01f
CW
1207 ],
1208 'get' => [
bf9a7c0f
ES
1209 'access CiviCRM',
1210 'access CiviEvent',
1211 'view event info',
be2fb01f
CW
1212 ],
1213 'update' => [
bf9a7c0f
ES
1214 'access CiviCRM',
1215 'access CiviEvent',
1216 'edit all events',
be2fb01f
CW
1217 ],
1218 ];
170af518 1219 // Exception refers to dedupe_exception.
1220 $permissions['exception'] = [
1221 'default' => ['merge duplicate contacts'],
1222 ];
5654496c 1223
418ffc5b 1224 $permissions['job'] = [
1225 'process_batch_merge' => ['merge duplicate contacts'],
1226 ];
5654496c 1227 $permissions['rule_group']['get'] = [['merge duplicate contacts', 'administer CiviCRM']];
bf9a7c0f
ES
1228 // Loc block is only used for events
1229 $permissions['loc_block'] = $permissions['event'];
1230
be2fb01f
CW
1231 $permissions['state_province'] = [
1232 'get' => [
fc2d1728 1233 'access CiviCRM',
be2fb01f
CW
1234 ],
1235 ];
fc2d1728 1236
bf9a7c0f 1237 // Price sets are shared by several components, user needs access to at least one of them
be2fb01f
CW
1238 $permissions['price_set'] = [
1239 'default' => [
1240 ['access CiviEvent', 'access CiviContribute', 'access CiviMember'],
1241 ],
1242 'get' => [
1243 ['access CiviCRM', 'view event info', 'make online contributions'],
1244 ],
1245 ];
bf9a7c0f
ES
1246
1247 // File permissions
be2fb01f
CW
1248 $permissions['file'] = [
1249 'default' => [
bf9a7c0f
ES
1250 'access CiviCRM',
1251 'access uploaded files',
be2fb01f
CW
1252 ],
1253 ];
bf9a7c0f
ES
1254 $permissions['files_by_entity'] = $permissions['file'];
1255
1256 // Group permissions
be2fb01f
CW
1257 $permissions['group'] = [
1258 'get' => [
bf9a7c0f 1259 'access CiviCRM',
be2fb01f
CW
1260 ],
1261 'default' => [
bf9a7c0f
ES
1262 'access CiviCRM',
1263 'edit groups',
be2fb01f
CW
1264 ],
1265 ];
bf9a7c0f
ES
1266
1267 $permissions['group_nesting'] = $permissions['group'];
1268 $permissions['group_organization'] = $permissions['group'];
1269
1270 //Group Contact permission
be2fb01f
CW
1271 $permissions['group_contact'] = [
1272 'get' => [
bf9a7c0f 1273 'access CiviCRM',
be2fb01f
CW
1274 ],
1275 'default' => [
bf9a7c0f
ES
1276 'access CiviCRM',
1277 'edit all contacts',
be2fb01f
CW
1278 ],
1279 ];
bf9a7c0f
ES
1280
1281 // CiviMail Permissions
be2fb01f 1282 $civiMailBasePerms = [
bf9a7c0f
ES
1283 // To get/preview/update, one must have least one of these perms:
1284 // Mailing API implementations enforce nuances of create/approve/schedule permissions.
1285 'access CiviMail',
1286 'create mailings',
1287 'schedule mailings',
1288 'approve mailings',
be2fb01f
CW
1289 ];
1290 $permissions['mailing'] = [
1291 'get' => [
bf9a7c0f
ES
1292 'access CiviCRM',
1293 $civiMailBasePerms,
be2fb01f
CW
1294 ],
1295 'delete' => [
bf9a7c0f
ES
1296 'access CiviCRM',
1297 $civiMailBasePerms,
1298 'delete in CiviMail',
be2fb01f
CW
1299 ],
1300 'submit' => [
bf9a7c0f 1301 'access CiviCRM',
be2fb01f
CW
1302 ['access CiviMail', 'schedule mailings'],
1303 ],
1304 'default' => [
bf9a7c0f
ES
1305 'access CiviCRM',
1306 $civiMailBasePerms,
be2fb01f
CW
1307 ],
1308 ];
bf9a7c0f
ES
1309 $permissions['mailing_group'] = $permissions['mailing'];
1310 $permissions['mailing_job'] = $permissions['mailing'];
1311 $permissions['mailing_recipients'] = $permissions['mailing'];
1312
be2fb01f
CW
1313 $permissions['mailing_a_b'] = [
1314 'get' => [
bf9a7c0f
ES
1315 'access CiviCRM',
1316 'access CiviMail',
be2fb01f
CW
1317 ],
1318 'delete' => [
bf9a7c0f
ES
1319 'access CiviCRM',
1320 'access CiviMail',
1321 'delete in CiviMail',
be2fb01f
CW
1322 ],
1323 'submit' => [
bf9a7c0f 1324 'access CiviCRM',
be2fb01f
CW
1325 ['access CiviMail', 'schedule mailings'],
1326 ],
1327 'default' => [
bf9a7c0f
ES
1328 'access CiviCRM',
1329 'access CiviMail',
be2fb01f
CW
1330 ],
1331 ];
bf9a7c0f
ES
1332
1333 // Membership permissions
be2fb01f
CW
1334 $permissions['membership'] = [
1335 'get' => [
bf9a7c0f
ES
1336 'access CiviCRM',
1337 'access CiviMember',
be2fb01f
CW
1338 ],
1339 'delete' => [
bf9a7c0f
ES
1340 'access CiviCRM',
1341 'access CiviMember',
1342 'delete in CiviMember',
be2fb01f
CW
1343 ],
1344 'default' => [
bf9a7c0f
ES
1345 'access CiviCRM',
1346 'access CiviMember',
1347 'edit memberships',
be2fb01f
CW
1348 ],
1349 ];
bf9a7c0f
ES
1350 $permissions['membership_status'] = $permissions['membership'];
1351 $permissions['membership_type'] = $permissions['membership'];
be2fb01f
CW
1352 $permissions['membership_payment'] = [
1353 'create' => [
bf9a7c0f
ES
1354 'access CiviCRM',
1355 'access CiviMember',
1356 'edit memberships',
1357 'access CiviContribute',
1358 'edit contributions',
be2fb01f
CW
1359 ],
1360 'delete' => [
bf9a7c0f
ES
1361 'access CiviCRM',
1362 'access CiviMember',
1363 'delete in CiviMember',
1364 'access CiviContribute',
1365 'delete in CiviContribute',
be2fb01f
CW
1366 ],
1367 'get' => [
bf9a7c0f
ES
1368 'access CiviCRM',
1369 'access CiviMember',
1370 'access CiviContribute',
be2fb01f
CW
1371 ],
1372 'update' => [
bf9a7c0f
ES
1373 'access CiviCRM',
1374 'access CiviMember',
1375 'edit memberships',
1376 'access CiviContribute',
1377 'edit contributions',
be2fb01f
CW
1378 ],
1379 ];
bf9a7c0f
ES
1380
1381 // Participant permissions
be2fb01f
CW
1382 $permissions['participant'] = [
1383 'create' => [
bf9a7c0f
ES
1384 'access CiviCRM',
1385 'access CiviEvent',
1386 'register for events',
be2fb01f
CW
1387 ],
1388 'delete' => [
bf9a7c0f
ES
1389 'access CiviCRM',
1390 'access CiviEvent',
1391 'edit event participants',
be2fb01f
CW
1392 ],
1393 'get' => [
bf9a7c0f
ES
1394 'access CiviCRM',
1395 'access CiviEvent',
1396 'view event participants',
be2fb01f
CW
1397 ],
1398 'update' => [
bf9a7c0f
ES
1399 'access CiviCRM',
1400 'access CiviEvent',
1401 'edit event participants',
be2fb01f
CW
1402 ],
1403 ];
1404 $permissions['participant_payment'] = [
1405 'create' => [
bf9a7c0f
ES
1406 'access CiviCRM',
1407 'access CiviEvent',
1408 'register for events',
1409 'access CiviContribute',
1410 'edit contributions',
be2fb01f
CW
1411 ],
1412 'delete' => [
bf9a7c0f
ES
1413 'access CiviCRM',
1414 'access CiviEvent',
1415 'edit event participants',
1416 'access CiviContribute',
1417 'delete in CiviContribute',
be2fb01f
CW
1418 ],
1419 'get' => [
bf9a7c0f
ES
1420 'access CiviCRM',
1421 'access CiviEvent',
1422 'view event participants',
1423 'access CiviContribute',
be2fb01f
CW
1424 ],
1425 'update' => [
bf9a7c0f
ES
1426 'access CiviCRM',
1427 'access CiviEvent',
1428 'edit event participants',
1429 'access CiviContribute',
1430 'edit contributions',
be2fb01f
CW
1431 ],
1432 ];
bf9a7c0f
ES
1433
1434 // Pledge permissions
be2fb01f
CW
1435 $permissions['pledge'] = [
1436 'create' => [
bf9a7c0f
ES
1437 'access CiviCRM',
1438 'access CiviPledge',
1439 'edit pledges',
be2fb01f
CW
1440 ],
1441 'delete' => [
bf9a7c0f
ES
1442 'access CiviCRM',
1443 'access CiviPledge',
1444 'delete in CiviPledge',
be2fb01f
CW
1445 ],
1446 'get' => [
bf9a7c0f
ES
1447 'access CiviCRM',
1448 'access CiviPledge',
be2fb01f
CW
1449 ],
1450 'update' => [
bf9a7c0f
ES
1451 'access CiviCRM',
1452 'access CiviPledge',
1453 'edit pledges',
be2fb01f
CW
1454 ],
1455 ];
bf9a7c0f
ES
1456
1457 //CRM-16777: Disable schedule reminder for user that have 'edit all events' and 'administer CiviCRM' permission.
be2fb01f
CW
1458 $permissions['action_schedule'] = [
1459 'update' => [
1460 [
bf9a7c0f
ES
1461 'access CiviCRM',
1462 'edit all events',
be2fb01f
CW
1463 ],
1464 ],
1465 ];
bf9a7c0f 1466
be2fb01f
CW
1467 $permissions['pledge_payment'] = [
1468 'create' => [
bf9a7c0f
ES
1469 'access CiviCRM',
1470 'access CiviPledge',
1471 'edit pledges',
1472 'access CiviContribute',
1473 'edit contributions',
be2fb01f
CW
1474 ],
1475 'delete' => [
bf9a7c0f
ES
1476 'access CiviCRM',
1477 'access CiviPledge',
1478 'delete in CiviPledge',
1479 'access CiviContribute',
1480 'delete in CiviContribute',
be2fb01f
CW
1481 ],
1482 'get' => [
bf9a7c0f
ES
1483 'access CiviCRM',
1484 'access CiviPledge',
1485 'access CiviContribute',
be2fb01f
CW
1486 ],
1487 'update' => [
bf9a7c0f
ES
1488 'access CiviCRM',
1489 'access CiviPledge',
1490 'edit pledges',
1491 'access CiviContribute',
1492 'edit contributions',
be2fb01f
CW
1493 ],
1494 ];
bf9a7c0f 1495
dfcf5ba2
CW
1496 // Dashboard permissions
1497 $permissions['dashboard'] = [
1498 'get' => [
1499 'access CiviCRM',
1500 ],
1501 ];
1502 $permissions['dashboard_contact'] = [
1503 'default' => [
1504 'access CiviCRM',
1505 ],
1506 ];
1507
9ac56a77
CW
1508 $permissions['saved_search'] = [
1509 'default' => ['administer CiviCRM data'],
1510 ];
1511
bf9a7c0f 1512 // Profile permissions
be2fb01f 1513 $permissions['profile'] = [
518fa0ee
SL
1514 // the profile will take care of this
1515 'get' => [],
be2fb01f 1516 ];
bf9a7c0f 1517
be2fb01f
CW
1518 $permissions['uf_group'] = [
1519 'create' => [
bf9a7c0f 1520 'access CiviCRM',
be2fb01f 1521 [
bf9a7c0f
ES
1522 'administer CiviCRM',
1523 'manage event profiles',
be2fb01f
CW
1524 ],
1525 ],
1526 'get' => [
bf9a7c0f 1527 'access CiviCRM',
be2fb01f
CW
1528 ],
1529 'update' => [
bf9a7c0f 1530 'access CiviCRM',
be2fb01f 1531 [
bf9a7c0f
ES
1532 'administer CiviCRM',
1533 'manage event profiles',
be2fb01f
CW
1534 ],
1535 ],
1536 ];
bf9a7c0f 1537 $permissions['uf_field'] = $permissions['uf_join'] = $permissions['uf_group'];
be2fb01f 1538 $permissions['uf_field']['delete'] = [
bf9a7c0f 1539 'access CiviCRM',
be2fb01f 1540 [
bf9a7c0f
ES
1541 'administer CiviCRM',
1542 'manage event profiles',
be2fb01f
CW
1543 ],
1544 ];
bf9a7c0f
ES
1545 $permissions['option_value'] = $permissions['uf_group'];
1546 $permissions['option_group'] = $permissions['option_value'];
1547
be2fb01f
CW
1548 $permissions['custom_value'] = [
1549 'gettree' => ['access CiviCRM'],
1550 ];
f26fa703 1551
be2fb01f
CW
1552 $permissions['message_template'] = [
1553 'get' => ['access CiviCRM'],
1554 'create' => [['edit message templates', 'edit user-driven message templates', 'edit system workflow message templates']],
1555 'update' => [['edit message templates', 'edit user-driven message templates', 'edit system workflow message templates']],
1556 ];
4341efe4
JV
1557
1558 $permissions['report_template']['update'] = 'save Report Criteria';
1559 $permissions['report_template']['create'] = 'save Report Criteria';
bf9a7c0f
ES
1560 return $permissions;
1561 }
1562
1563 /**
1564 * Translate an unknown action to a canonical form.
1565 *
1566 * @param string $action
1567 *
1568 * @return string
1569 * the standardised action name
1570 */
1571 public static function getGenericAction($action) {
1572 $snippet = substr($action, 0, 3);
1573 if ($action == 'replace' || $snippet == 'del') {
1574 // 'Replace' is a combination of get+create+update+delete; however, the permissions
1575 // on each of those will be tested separately at runtime. This is just a sniff-test
1576 // based on the heuristic that 'delete' tends to be the most closely guarded
1577 // of the necessary permissions.
1578 $action = 'delete';
1579 }
1580 elseif ($action == 'setvalue' || $snippet == 'upd') {
1581 $action = 'update';
1582 }
1583 elseif ($action == 'getfields' || $action == 'getfield' || $action == 'getspec' || $action == 'getoptions') {
1584 $action = 'meta';
1585 }
1586 elseif ($snippet == 'get') {
1587 $action = 'get';
1588 }
1589 return $action;
1590 }
1591
6a488035 1592 /**
d09edf64 1593 * Validate user permission across.
6a488035
TO
1594 * edit or view or with supportable acls.
1595 *
acb1052e
WA
1596 * @return bool
1597 */
00be9182 1598 public static function giveMeAllACLs() {
6a488035
TO
1599 if (CRM_Core_Permission::check('view all contacts') ||
1600 CRM_Core_Permission::check('edit all contacts')
1601 ) {
1602 return TRUE;
1603 }
1604
1605 $session = CRM_Core_Session::singleton();
1606 $contactID = $session->get('userID');
1607
6a488035
TO
1608 //check for acl.
1609 $aclPermission = self::getPermission();
be2fb01f 1610 if (in_array($aclPermission, [
6a488035 1611 CRM_Core_Permission::EDIT,
41f314b6 1612 CRM_Core_Permission::VIEW,
be2fb01f 1613 ])
41f314b6 1614 ) {
6a488035
TO
1615 return TRUE;
1616 }
1617
1618 // run acl where hook and see if the user is supplying an ACL clause
1619 // that is not false
be2fb01f 1620 $tables = $whereTables = [];
6a488035
TO
1621 $where = NULL;
1622
1623 CRM_Utils_Hook::aclWhereClause(CRM_Core_Permission::VIEW,
1624 $tables, $whereTables,
1625 $contactID, $where
1626 );
1627 return empty($whereTables) ? FALSE : TRUE;
1628 }
1629
1630 /**
100fef9d 1631 * Get component name from given permission.
6a488035 1632 *
41f314b6 1633 * @param string $permission
6a488035 1634 *
76e7a76c
CW
1635 * @return null|string
1636 * the name of component.
6a488035 1637 */
00be9182 1638 public static function getComponentName($permission) {
6a488035
TO
1639 $componentName = NULL;
1640 $permission = trim($permission);
1641 if (empty($permission)) {
1642 return $componentName;
1643 }
1644
be2fb01f 1645 static $allCompPermissions = [];
6a488035
TO
1646 if (empty($allCompPermissions)) {
1647 $components = CRM_Core_Component::getComponents();
1648 foreach ($components as $name => $comp) {
33777e4a
PJ
1649 //get all permissions of each components unconditionally
1650 $allCompPermissions[$name] = $comp->getPermissions(TRUE);
6a488035
TO
1651 }
1652 }
1653
1654 if (is_array($allCompPermissions)) {
1655 foreach ($allCompPermissions as $name => $permissions) {
b9021475 1656 if (array_key_exists($permission, $permissions)) {
6a488035
TO
1657 $componentName = $name;
1658 break;
1659 }
1660 }
1661 }
1662
1663 return $componentName;
1664 }
1665
1666 /**
d09edf64 1667 * Get all the contact emails for users that have a specific permission.
6a488035 1668 *
6a0b768e
TO
1669 * @param string $permissionName
1670 * Name of the permission we are interested in.
6a488035 1671 *
a6c01b45
CW
1672 * @return string
1673 * a comma separated list of email addresses
6a488035
TO
1674 */
1675 public static function permissionEmails($permissionName) {
1676 $config = CRM_Core_Config::singleton();
41f314b6 1677 return $config->userPermissionClass->permissionEmails($permissionName);
6a488035
TO
1678 }
1679
1680 /**
d09edf64 1681 * Get all the contact emails for users that have a specific role.
6a488035 1682 *
6a0b768e
TO
1683 * @param string $roleName
1684 * Name of the role we are interested in.
6a488035 1685 *
a6c01b45
CW
1686 * @return string
1687 * a comma separated list of email addresses
6a488035
TO
1688 */
1689 public static function roleEmails($roleName) {
1690 $config = CRM_Core_Config::singleton();
41f314b6 1691 return $config->userRoleClass->roleEmails($roleName);
6a488035
TO
1692 }
1693
a0ee3941
EM
1694 /**
1695 * @return bool
1696 */
00be9182 1697 public static function isMultisiteEnabled() {
63d76404 1698 return (bool) Civi::settings()->get('is_enabled');
6a488035 1699 }
96025800 1700
dc6b437a
GC
1701 /**
1702 * Verify if the user has permission to get the invoice.
1703 *
1704 * @return bool
1705 * TRUE if the user has download all invoices permission or download my
1706 * invoices permission and the invoice author is the current user.
1707 */
1708 public static function checkDownloadInvoice() {
4cfd4f45 1709 $cid = CRM_Core_Session::getLoggedInContactID();
dc6b437a
GC
1710 if (CRM_Core_Permission::check('access CiviContribute') ||
1711 (CRM_Core_Permission::check('view my invoices') && $_GET['cid'] == $cid)
1712 ) {
1713 return TRUE;
1714 }
1715 return FALSE;
1716 }
1717
b4d6a411 1718 /**
d2b6eac8 1719 * Get permissions for components.
1720 *
b4d6a411 1721 * @param bool $includeDisabled
1722 *
1723 * @return array
1724 * @throws \CRM_Core_Exception
1725 */
1726 protected static function getComponentPermissions(bool $includeDisabled): array {
1727 if (!$includeDisabled) {
1728 $components = CRM_Core_Component::getEnabledComponents();
1729 }
1730 else {
1731 $components = CRM_Core_Component::getComponents();
1732 }
1733
1734 $permissions = [];
1735 foreach ($components as $comp) {
1736 $perm = $comp->getPermissions($includeDisabled, TRUE);
1737 if ($perm) {
1738 $info = $comp->getInfo();
1739 foreach ($perm as $p => $attr) {
1740
1741 if (!is_array($attr)) {
1742 $attr = [$attr];
1743 }
1744
1745 $attr[0] = $info['translatedName'] . ': ' . $attr[0];
1746 $permissions[$p] = $attr;
1747 }
1748 }
1749 }
1750 return $permissions;
1751 }
1752
d2b6eac8 1753 /**
1754 * Get permissions for core functionality and for that of core components.
1755 *
1756 * @param bool $all
1757 *
1758 * @return array
1759 * @throws \CRM_Core_Exception
1760 */
1761 protected static function getCoreAndComponentPermissions(bool $all): array {
1762 $permissions = self::getCorePermissions();
1763 $permissions = array_merge($permissions, self::getComponentPermissions($all));
ea54c6e5 1764 $permissions['all CiviCRM permissions and ACLs']['implied_permissions'] = array_keys($permissions);
d2b6eac8 1765 return $permissions;
1766 }
1767
6a488035 1768}