Merge pull request #19766 from WeMoveEU/faster-select2-groups
[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 * @return bool
212 */
213 public static function customGroupAdmin() {
214 $admin = FALSE;
215
216 // check if user has all powerful permission
217 // or administer civicrm permission (CRM-1905)
218 if (self::check('access all custom data')) {
219 return TRUE;
220 }
221
222 if (
223 self::check('administer Multiple Organizations') &&
224 self::isMultisiteEnabled()
225 ) {
226 return TRUE;
227 }
228
229 if (self::check('administer CiviCRM')) {
230 return TRUE;
231 }
232
233 return FALSE;
234 }
235
236 /**
237 * @param int $type
238 * @param bool $reset
239 *
240 * @return array
241 */
242 public static function customGroup($type = CRM_Core_Permission::VIEW, $reset = FALSE) {
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()) {
250 $defaultGroups = array_keys($customGroups);
251 }
252
253 return CRM_ACL_API::group($type, NULL, 'civicrm_custom_group', $customGroups, $defaultGroups);
254 }
255
256 /**
257 * @param int $type
258 * @param 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 'edit message templates' => [
845 $prefix . ts('edit message templates'),
846 ],
847 'edit system workflow message templates' => [
848 $prefix . ts('edit system workflow message templates'),
849 ],
850 'edit user-driven message templates' => [
851 $prefix . ts('edit user-driven message templates'),
852 ],
853 'view my invoices' => [
854 $prefix . ts('view my invoices'),
855 ts('Allow users to view/ download their own invoices'),
856 ],
857 'edit api keys' => [
858 $prefix . ts('edit api keys'),
859 ts('Edit API keys'),
860 ],
861 'edit own api keys' => [
862 $prefix . ts('edit own api keys'),
863 ts('Edit user\'s own API keys'),
864 ],
865 'send SMS' => [
866 $prefix . ts('send SMS'),
867 ts('Send an SMS'),
868 ],
869 'administer CiviCRM system' => [
870 'label' => $prefix . ts('administer CiviCRM System'),
871 'description' => ts('Perform all system administration tasks in CiviCRM'),
872 ],
873 'administer CiviCRM data' => [
874 'label' => $prefix . ts('administer CiviCRM Data'),
875 'description' => ts('Permit altering all restricted data options'),
876 ],
877 ];
878 if (self::isMultisiteEnabled()) {
879 // This could arguably be moved to the multisite extension but
880 // within core it does permit editing group-organization records.
881 $permissions['administer Multiple Organizations'] = [
882 'label' => $prefix . ts('administer Multiple Organizations'),
883 'description' => ts('Administer multiple organizations. In practice this allows editing the group organization link'),
884 ];
885 }
886 foreach (self::getImpliedPermissions() as $name => $includes) {
887 foreach ($includes as $permission) {
888 $permissions[$name][] = $permissions[$permission];
889 }
890 }
891 return $permissions;
892 }
893
894 /**
895 * Get permissions implied by 'superset' permissions.
896 *
897 * @return array
898 */
899 public static function getImpliedPermissions() {
900 return [
901 'administer CiviCRM' => ['administer CiviCRM system', 'administer CiviCRM data'],
902 'administer CiviCRM data' => ['edit message templates', 'administer dedupe rules'],
903 'administer CiviCRM system' => ['edit system workflow message templates'],
904 ];
905 }
906
907 /**
908 * Get any super-permissions that imply the given permission.
909 *
910 * @param string $permission
911 *
912 * @return array
913 */
914 public static function getImpliedPermissionsFor(string $permission) {
915 $return = [];
916 foreach (self::getImpliedPermissions() as $superPermission => $components) {
917 if (in_array($permission, $components, TRUE)) {
918 $return[$superPermission] = $superPermission;
919 }
920 }
921 return $return;
922 }
923
924 /**
925 * For each entity provides an array of permissions required for each action
926 *
927 * The action is the array key, possible values:
928 * * create: applies to create (with no id in params)
929 * * update: applies to update, setvalue, create (with id in params)
930 * * get: applies to getcount, getsingle, getvalue and other gets
931 * * delete: applies to delete, replace
932 * * meta: applies to getfields, getoptions, getspec
933 * * default: catch-all for anything not declared
934 *
935 * Note: some APIs declare other actions as well
936 *
937 * Permissions should use arrays for AND and arrays of arrays for OR
938 * @see CRM_Core_Permission::check
939 *
940 * @return array of permissions
941 */
942 public static function getEntityActionPermissions() {
943 $permissions = [];
944 // These are the default permissions - if any entity does not declare permissions for a given action,
945 // (or the entity does not declare permissions at all) - then the action will be used from here
946 $permissions['default'] = [
947 // applies to getfields, getoptions, etc.
948 'meta' => ['access CiviCRM'],
949 // catch-all, applies to create, get, delete, etc.
950 // If an entity declares it's own 'default' action it will override this one
951 'default' => ['administer CiviCRM'],
952 ];
953
954 // Note: Additional permissions in DynamicFKAuthorization
955 $permissions['attachment'] = [
956 'default' => [
957 ['access CiviCRM', 'access AJAX API'],
958 ],
959 ];
960
961 // Contact permissions
962 $permissions['contact'] = [
963 'create' => [
964 'access CiviCRM',
965 'add contacts',
966 ],
967 'delete' => [
968 'access CiviCRM',
969 'delete contacts',
970 ],
971 // managed by query object
972 'get' => [],
973 // managed by _civicrm_api3_check_edit_permissions
974 'update' => [],
975 'getquick' => [
976 ['access CiviCRM', 'access AJAX API'],
977 ],
978 'duplicatecheck' => [
979 'access CiviCRM',
980 ],
981 'merge' => ['merge duplicate contacts'],
982 ];
983
984 $permissions['dedupe'] = [
985 'getduplicates' => ['access CiviCRM'],
986 'getstatistics' => ['access CiviCRM'],
987 ];
988
989 // CRM-16963 - Permissions for country.
990 $permissions['country'] = [
991 'get' => [
992 'access CiviCRM',
993 ],
994 'default' => [
995 'administer CiviCRM',
996 ],
997 ];
998
999 // Contact-related data permissions.
1000 $permissions['address'] = [
1001 // get is managed by BAO::addSelectWhereClause
1002 // create/delete are managed by _civicrm_api3_check_edit_permissions
1003 'default' => [],
1004 ];
1005 $permissions['email'] = $permissions['address'];
1006 $permissions['phone'] = $permissions['address'];
1007 $permissions['website'] = $permissions['address'];
1008 $permissions['im'] = $permissions['address'];
1009 $permissions['open_i_d'] = $permissions['address'];
1010
1011 // Also managed by ACLs - CRM-19448
1012 $permissions['entity_tag'] = ['default' => []];
1013 $permissions['note'] = $permissions['entity_tag'];
1014
1015 // Allow non-admins to get and create tags to support tagset widget
1016 // Delete is still reserved for admins
1017 $permissions['tag'] = [
1018 'get' => ['access CiviCRM'],
1019 'create' => ['access CiviCRM'],
1020 'update' => ['access CiviCRM'],
1021 ];
1022
1023 //relationship permissions
1024 $permissions['relationship'] = [
1025 // get is managed by BAO::addSelectWhereClause
1026 'get' => [],
1027 'delete' => [
1028 'access CiviCRM',
1029 'edit all contacts',
1030 ],
1031 'default' => [
1032 'access CiviCRM',
1033 'edit all contacts',
1034 ],
1035 ];
1036
1037 // CRM-17741 - Permissions for RelationshipType.
1038 $permissions['relationship_type'] = [
1039 'get' => [
1040 'access CiviCRM',
1041 ],
1042 'default' => [
1043 'administer CiviCRM',
1044 ],
1045 ];
1046
1047 // Activity permissions
1048 $permissions['activity'] = [
1049 'delete' => [
1050 'access CiviCRM',
1051 'delete activities',
1052 ],
1053 'get' => [
1054 'access CiviCRM',
1055 // Note that view all activities is also required within the api
1056 // if the id is not passed in. Where the id is passed in the activity
1057 // specific check functions are used and tested.
1058 ],
1059 'default' => [
1060 'access CiviCRM',
1061 'view all activities',
1062 ],
1063 ];
1064 $permissions['activity_contact'] = $permissions['activity'];
1065
1066 // Case permissions
1067 $permissions['case'] = [
1068 'create' => [
1069 'access CiviCRM',
1070 'add cases',
1071 ],
1072 'delete' => [
1073 'access CiviCRM',
1074 'delete in CiviCase',
1075 ],
1076 'restore' => [
1077 'administer CiviCase',
1078 ],
1079 'merge' => [
1080 'administer CiviCase',
1081 ],
1082 'default' => [
1083 // At minimum the user needs one of the following. Finer-grained access is controlled by CRM_Case_BAO_Case::addSelectWhereClause
1084 ['access my cases and activities', 'access all cases and activities'],
1085 ],
1086 ];
1087 $permissions['case_contact'] = $permissions['case'];
1088
1089 $permissions['case_type'] = [
1090 'default' => ['administer CiviCase'],
1091 'get' => [
1092 // nested array = OR
1093 ['access my cases and activities', 'access all cases and activities'],
1094 ],
1095 ];
1096
1097 // Campaign permissions
1098 $permissions['campaign'] = [
1099 'get' => ['access CiviCRM'],
1100 'default' => [
1101 // nested array = OR
1102 ['administer CiviCampaign', 'manage campaign'],
1103 ],
1104 ];
1105 $permissions['survey'] = $permissions['campaign'];
1106
1107 // Financial permissions
1108 $permissions['contribution'] = [
1109 'get' => [
1110 'access CiviCRM',
1111 'access CiviContribute',
1112 ],
1113 'delete' => [
1114 'access CiviCRM',
1115 'access CiviContribute',
1116 'delete in CiviContribute',
1117 ],
1118 'completetransaction' => [
1119 'edit contributions',
1120 ],
1121 'default' => [
1122 'access CiviCRM',
1123 'access CiviContribute',
1124 'edit contributions',
1125 ],
1126 ];
1127 $permissions['line_item'] = $permissions['contribution'];
1128
1129 // Payment permissions
1130 $permissions['payment'] = [
1131 'get' => [
1132 'access CiviCRM',
1133 'access CiviContribute',
1134 ],
1135 'delete' => [
1136 'access CiviCRM',
1137 'access CiviContribute',
1138 'delete in CiviContribute',
1139 ],
1140 'cancel' => [
1141 'access CiviCRM',
1142 'access CiviContribute',
1143 'edit contributions',
1144 ],
1145 'create' => [
1146 'access CiviCRM',
1147 'access CiviContribute',
1148 'edit contributions',
1149 ],
1150 'default' => [
1151 'access CiviCRM',
1152 'access CiviContribute',
1153 'edit contributions',
1154 ],
1155 ];
1156 $permissions['contribution_recur'] = $permissions['payment'];
1157
1158 // Custom field permissions
1159 $permissions['custom_field'] = [
1160 'default' => [
1161 'administer CiviCRM',
1162 'access all custom data',
1163 ],
1164 ];
1165 $permissions['custom_group'] = $permissions['custom_field'];
1166
1167 // Event permissions
1168 $permissions['event'] = [
1169 'create' => [
1170 'access CiviCRM',
1171 'access CiviEvent',
1172 'edit all events',
1173 ],
1174 'delete' => [
1175 'access CiviCRM',
1176 'access CiviEvent',
1177 'delete in CiviEvent',
1178 ],
1179 'get' => [
1180 'access CiviCRM',
1181 'access CiviEvent',
1182 'view event info',
1183 ],
1184 'update' => [
1185 'access CiviCRM',
1186 'access CiviEvent',
1187 'edit all events',
1188 ],
1189 ];
1190 // Exception refers to dedupe_exception.
1191 $permissions['exception'] = [
1192 'default' => ['merge duplicate contacts'],
1193 ];
1194
1195 $permissions['job'] = [
1196 'process_batch_merge' => ['merge duplicate contacts'],
1197 ];
1198 $permissions['rule_group']['get'] = [['merge duplicate contacts', 'administer CiviCRM']];
1199 // Loc block is only used for events
1200 $permissions['loc_block'] = $permissions['event'];
1201
1202 $permissions['state_province'] = [
1203 'get' => [
1204 'access CiviCRM',
1205 ],
1206 ];
1207
1208 // Price sets are shared by several components, user needs access to at least one of them
1209 $permissions['price_set'] = [
1210 'default' => [
1211 ['access CiviEvent', 'access CiviContribute', 'access CiviMember'],
1212 ],
1213 'get' => [
1214 ['access CiviCRM', 'view event info', 'make online contributions'],
1215 ],
1216 ];
1217
1218 // File permissions
1219 $permissions['file'] = [
1220 'default' => [
1221 'access CiviCRM',
1222 'access uploaded files',
1223 ],
1224 ];
1225 $permissions['files_by_entity'] = $permissions['file'];
1226
1227 // Group permissions
1228 $permissions['group'] = [
1229 'get' => [
1230 'access CiviCRM',
1231 ],
1232 'default' => [
1233 'access CiviCRM',
1234 'edit groups',
1235 ],
1236 ];
1237
1238 $permissions['group_nesting'] = $permissions['group'];
1239 $permissions['group_organization'] = $permissions['group'];
1240
1241 //Group Contact permission
1242 $permissions['group_contact'] = [
1243 'get' => [
1244 'access CiviCRM',
1245 ],
1246 'default' => [
1247 'access CiviCRM',
1248 'edit all contacts',
1249 ],
1250 ];
1251
1252 // CiviMail Permissions
1253 $civiMailBasePerms = [
1254 // To get/preview/update, one must have least one of these perms:
1255 // Mailing API implementations enforce nuances of create/approve/schedule permissions.
1256 'access CiviMail',
1257 'create mailings',
1258 'schedule mailings',
1259 'approve mailings',
1260 ];
1261 $permissions['mailing'] = [
1262 'get' => [
1263 'access CiviCRM',
1264 $civiMailBasePerms,
1265 ],
1266 'delete' => [
1267 'access CiviCRM',
1268 $civiMailBasePerms,
1269 'delete in CiviMail',
1270 ],
1271 'submit' => [
1272 'access CiviCRM',
1273 ['access CiviMail', 'schedule mailings'],
1274 ],
1275 'default' => [
1276 'access CiviCRM',
1277 $civiMailBasePerms,
1278 ],
1279 ];
1280 $permissions['mailing_group'] = $permissions['mailing'];
1281 $permissions['mailing_job'] = $permissions['mailing'];
1282 $permissions['mailing_recipients'] = $permissions['mailing'];
1283
1284 $permissions['mailing_a_b'] = [
1285 'get' => [
1286 'access CiviCRM',
1287 'access CiviMail',
1288 ],
1289 'delete' => [
1290 'access CiviCRM',
1291 'access CiviMail',
1292 'delete in CiviMail',
1293 ],
1294 'submit' => [
1295 'access CiviCRM',
1296 ['access CiviMail', 'schedule mailings'],
1297 ],
1298 'default' => [
1299 'access CiviCRM',
1300 'access CiviMail',
1301 ],
1302 ];
1303
1304 // Membership permissions
1305 $permissions['membership'] = [
1306 'get' => [
1307 'access CiviCRM',
1308 'access CiviMember',
1309 ],
1310 'delete' => [
1311 'access CiviCRM',
1312 'access CiviMember',
1313 'delete in CiviMember',
1314 ],
1315 'default' => [
1316 'access CiviCRM',
1317 'access CiviMember',
1318 'edit memberships',
1319 ],
1320 ];
1321 $permissions['membership_status'] = $permissions['membership'];
1322 $permissions['membership_type'] = $permissions['membership'];
1323 $permissions['membership_payment'] = [
1324 'create' => [
1325 'access CiviCRM',
1326 'access CiviMember',
1327 'edit memberships',
1328 'access CiviContribute',
1329 'edit contributions',
1330 ],
1331 'delete' => [
1332 'access CiviCRM',
1333 'access CiviMember',
1334 'delete in CiviMember',
1335 'access CiviContribute',
1336 'delete in CiviContribute',
1337 ],
1338 'get' => [
1339 'access CiviCRM',
1340 'access CiviMember',
1341 'access CiviContribute',
1342 ],
1343 'update' => [
1344 'access CiviCRM',
1345 'access CiviMember',
1346 'edit memberships',
1347 'access CiviContribute',
1348 'edit contributions',
1349 ],
1350 ];
1351
1352 // Participant permissions
1353 $permissions['participant'] = [
1354 'create' => [
1355 'access CiviCRM',
1356 'access CiviEvent',
1357 'register for events',
1358 ],
1359 'delete' => [
1360 'access CiviCRM',
1361 'access CiviEvent',
1362 'edit event participants',
1363 ],
1364 'get' => [
1365 'access CiviCRM',
1366 'access CiviEvent',
1367 'view event participants',
1368 ],
1369 'update' => [
1370 'access CiviCRM',
1371 'access CiviEvent',
1372 'edit event participants',
1373 ],
1374 ];
1375 $permissions['participant_payment'] = [
1376 'create' => [
1377 'access CiviCRM',
1378 'access CiviEvent',
1379 'register for events',
1380 'access CiviContribute',
1381 'edit contributions',
1382 ],
1383 'delete' => [
1384 'access CiviCRM',
1385 'access CiviEvent',
1386 'edit event participants',
1387 'access CiviContribute',
1388 'delete in CiviContribute',
1389 ],
1390 'get' => [
1391 'access CiviCRM',
1392 'access CiviEvent',
1393 'view event participants',
1394 'access CiviContribute',
1395 ],
1396 'update' => [
1397 'access CiviCRM',
1398 'access CiviEvent',
1399 'edit event participants',
1400 'access CiviContribute',
1401 'edit contributions',
1402 ],
1403 ];
1404
1405 // Pledge permissions
1406 $permissions['pledge'] = [
1407 'create' => [
1408 'access CiviCRM',
1409 'access CiviPledge',
1410 'edit pledges',
1411 ],
1412 'delete' => [
1413 'access CiviCRM',
1414 'access CiviPledge',
1415 'delete in CiviPledge',
1416 ],
1417 'get' => [
1418 'access CiviCRM',
1419 'access CiviPledge',
1420 ],
1421 'update' => [
1422 'access CiviCRM',
1423 'access CiviPledge',
1424 'edit pledges',
1425 ],
1426 ];
1427
1428 //CRM-16777: Disable schedule reminder for user that have 'edit all events' and 'administer CiviCRM' permission.
1429 $permissions['action_schedule'] = [
1430 'update' => [
1431 [
1432 'access CiviCRM',
1433 'edit all events',
1434 ],
1435 ],
1436 ];
1437
1438 $permissions['pledge_payment'] = [
1439 'create' => [
1440 'access CiviCRM',
1441 'access CiviPledge',
1442 'edit pledges',
1443 'access CiviContribute',
1444 'edit contributions',
1445 ],
1446 'delete' => [
1447 'access CiviCRM',
1448 'access CiviPledge',
1449 'delete in CiviPledge',
1450 'access CiviContribute',
1451 'delete in CiviContribute',
1452 ],
1453 'get' => [
1454 'access CiviCRM',
1455 'access CiviPledge',
1456 'access CiviContribute',
1457 ],
1458 'update' => [
1459 'access CiviCRM',
1460 'access CiviPledge',
1461 'edit pledges',
1462 'access CiviContribute',
1463 'edit contributions',
1464 ],
1465 ];
1466
1467 // Dashboard permissions
1468 $permissions['dashboard'] = [
1469 'get' => [
1470 'access CiviCRM',
1471 ],
1472 ];
1473 $permissions['dashboard_contact'] = [
1474 'default' => [
1475 'access CiviCRM',
1476 ],
1477 ];
1478
1479 // Profile permissions
1480 $permissions['profile'] = [
1481 // the profile will take care of this
1482 'get' => [],
1483 ];
1484
1485 $permissions['uf_group'] = [
1486 'create' => [
1487 'access CiviCRM',
1488 [
1489 'administer CiviCRM',
1490 'manage event profiles',
1491 ],
1492 ],
1493 'get' => [
1494 'access CiviCRM',
1495 ],
1496 'update' => [
1497 'access CiviCRM',
1498 [
1499 'administer CiviCRM',
1500 'manage event profiles',
1501 ],
1502 ],
1503 ];
1504 $permissions['uf_field'] = $permissions['uf_join'] = $permissions['uf_group'];
1505 $permissions['uf_field']['delete'] = [
1506 'access CiviCRM',
1507 [
1508 'administer CiviCRM',
1509 'manage event profiles',
1510 ],
1511 ];
1512 $permissions['option_value'] = $permissions['uf_group'];
1513 $permissions['option_group'] = $permissions['option_value'];
1514
1515 $permissions['custom_value'] = [
1516 'gettree' => ['access CiviCRM'],
1517 ];
1518
1519 $permissions['message_template'] = [
1520 'get' => ['access CiviCRM'],
1521 'create' => [['edit message templates', 'edit user-driven message templates', 'edit system workflow message templates']],
1522 'update' => [['edit message templates', 'edit user-driven message templates', 'edit system workflow message templates']],
1523 ];
1524
1525 $permissions['report_template']['update'] = 'save Report Criteria';
1526 $permissions['report_template']['create'] = 'save Report Criteria';
1527 return $permissions;
1528 }
1529
1530 /**
1531 * Translate an unknown action to a canonical form.
1532 *
1533 * @param string $action
1534 *
1535 * @return string
1536 * the standardised action name
1537 */
1538 public static function getGenericAction($action) {
1539 $snippet = substr($action, 0, 3);
1540 if ($action == 'replace' || $snippet == 'del') {
1541 // 'Replace' is a combination of get+create+update+delete; however, the permissions
1542 // on each of those will be tested separately at runtime. This is just a sniff-test
1543 // based on the heuristic that 'delete' tends to be the most closely guarded
1544 // of the necessary permissions.
1545 $action = 'delete';
1546 }
1547 elseif ($action == 'setvalue' || $snippet == 'upd') {
1548 $action = 'update';
1549 }
1550 elseif ($action == 'getfields' || $action == 'getfield' || $action == 'getspec' || $action == 'getoptions') {
1551 $action = 'meta';
1552 }
1553 elseif ($snippet == 'get') {
1554 $action = 'get';
1555 }
1556 return $action;
1557 }
1558
1559 /**
1560 * Validate user permission across.
1561 * edit or view or with supportable acls.
1562 *
1563 * @return bool
1564 */
1565 public static function giveMeAllACLs() {
1566 if (CRM_Core_Permission::check('view all contacts') ||
1567 CRM_Core_Permission::check('edit all contacts')
1568 ) {
1569 return TRUE;
1570 }
1571
1572 $session = CRM_Core_Session::singleton();
1573 $contactID = $session->get('userID');
1574
1575 //check for acl.
1576 $aclPermission = self::getPermission();
1577 if (in_array($aclPermission, [
1578 CRM_Core_Permission::EDIT,
1579 CRM_Core_Permission::VIEW,
1580 ])
1581 ) {
1582 return TRUE;
1583 }
1584
1585 // run acl where hook and see if the user is supplying an ACL clause
1586 // that is not false
1587 $tables = $whereTables = [];
1588 $where = NULL;
1589
1590 CRM_Utils_Hook::aclWhereClause(CRM_Core_Permission::VIEW,
1591 $tables, $whereTables,
1592 $contactID, $where
1593 );
1594 return empty($whereTables) ? FALSE : TRUE;
1595 }
1596
1597 /**
1598 * Get component name from given permission.
1599 *
1600 * @param string $permission
1601 *
1602 * @return null|string
1603 * the name of component.
1604 */
1605 public static function getComponentName($permission) {
1606 $componentName = NULL;
1607 $permission = trim($permission);
1608 if (empty($permission)) {
1609 return $componentName;
1610 }
1611
1612 static $allCompPermissions = [];
1613 if (empty($allCompPermissions)) {
1614 $components = CRM_Core_Component::getComponents();
1615 foreach ($components as $name => $comp) {
1616 //get all permissions of each components unconditionally
1617 $allCompPermissions[$name] = $comp->getPermissions(TRUE);
1618 }
1619 }
1620
1621 if (is_array($allCompPermissions)) {
1622 foreach ($allCompPermissions as $name => $permissions) {
1623 if (array_key_exists($permission, $permissions)) {
1624 $componentName = $name;
1625 break;
1626 }
1627 }
1628 }
1629
1630 return $componentName;
1631 }
1632
1633 /**
1634 * Get all the contact emails for users that have a specific permission.
1635 *
1636 * @param string $permissionName
1637 * Name of the permission we are interested in.
1638 *
1639 * @return string
1640 * a comma separated list of email addresses
1641 */
1642 public static function permissionEmails($permissionName) {
1643 $config = CRM_Core_Config::singleton();
1644 return $config->userPermissionClass->permissionEmails($permissionName);
1645 }
1646
1647 /**
1648 * Get all the contact emails for users that have a specific role.
1649 *
1650 * @param string $roleName
1651 * Name of the role we are interested in.
1652 *
1653 * @return string
1654 * a comma separated list of email addresses
1655 */
1656 public static function roleEmails($roleName) {
1657 $config = CRM_Core_Config::singleton();
1658 return $config->userRoleClass->roleEmails($roleName);
1659 }
1660
1661 /**
1662 * @return bool
1663 */
1664 public static function isMultisiteEnabled() {
1665 return (bool) Civi::settings()->get('is_enabled');
1666 }
1667
1668 /**
1669 * Verify if the user has permission to get the invoice.
1670 *
1671 * @return bool
1672 * TRUE if the user has download all invoices permission or download my
1673 * invoices permission and the invoice author is the current user.
1674 */
1675 public static function checkDownloadInvoice() {
1676 $cid = CRM_Core_Session::getLoggedInContactID();
1677 if (CRM_Core_Permission::check('access CiviContribute') ||
1678 (CRM_Core_Permission::check('view my invoices') && $_GET['cid'] == $cid)
1679 ) {
1680 return TRUE;
1681 }
1682 return FALSE;
1683 }
1684
1685 /**
1686 * Get permissions for components.
1687 *
1688 * @param bool $includeDisabled
1689 *
1690 * @return array
1691 * @throws \CRM_Core_Exception
1692 */
1693 protected static function getComponentPermissions(bool $includeDisabled): array {
1694 if (!$includeDisabled) {
1695 $components = CRM_Core_Component::getEnabledComponents();
1696 }
1697 else {
1698 $components = CRM_Core_Component::getComponents();
1699 }
1700
1701 $permissions = [];
1702 foreach ($components as $comp) {
1703 $perm = $comp->getPermissions($includeDisabled, TRUE);
1704 if ($perm) {
1705 $info = $comp->getInfo();
1706 foreach ($perm as $p => $attr) {
1707
1708 if (!is_array($attr)) {
1709 $attr = [$attr];
1710 }
1711
1712 $attr[0] = $info['translatedName'] . ': ' . $attr[0];
1713 $permissions[$p] = $attr;
1714 }
1715 }
1716 }
1717 return $permissions;
1718 }
1719
1720 /**
1721 * Get permissions for core functionality and for that of core components.
1722 *
1723 * @param bool $all
1724 *
1725 * @return array
1726 * @throws \CRM_Core_Exception
1727 */
1728 protected static function getCoreAndComponentPermissions(bool $all): array {
1729 $permissions = self::getCorePermissions();
1730 $permissions = array_merge($permissions, self::getComponentPermissions($all));
1731 return $permissions;
1732 }
1733
1734 }