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