dev/core#1744 - Civi/API - Simplify event naming
[civicrm-core.git] / Civi / API / Subscriber / PermissionCheck.php
CommitLineData
d0c9daa4
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
41498ac5 4 | Copyright CiviCRM LLC. All rights reserved. |
d0c9daa4 5 | |
41498ac5
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
d0c9daa4 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
d0c9daa4
TO
11
12namespace Civi\API\Subscriber;
46bcf597 13
d0c9daa4
TO
14use Civi\API\Events;
15use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
17/**
8882ff5c
TO
18 * For any API requests that correspond to a Doctrine entity
19 * ($apiRequest['doctrineClass']), check permissions specified in
20 * Civi\API\Annotation\Permission.
d0c9daa4
TO
21 */
22class PermissionCheck implements EventSubscriberInterface {
34f3bbd9 23
6550386a
EM
24 /**
25 * @return array
26 */
d0c9daa4 27 public static function getSubscribedEvents() {
c64f69d9 28 return [
39b870b8 29 'civi.api.authorize' => [
c64f69d9
CW
30 ['onApiAuthorize', Events::W_LATE],
31 ],
32 ];
d0c9daa4
TO
33 }
34
6550386a
EM
35 /**
36 * @param \Civi\API\Event\AuthorizeEvent $event
8882ff5c 37 * API authorization event.
6550386a
EM
38 *
39 * @throws \Civi\API\Exception\UnauthorizedException
40 */
d0c9daa4
TO
41 public function onApiAuthorize(\Civi\API\Event\AuthorizeEvent $event) {
42 $apiRequest = $event->getApiRequest();
43 if ($apiRequest['version'] < 4) {
44 // return early unless we’re told explicitly to do the permission check
45 if (empty($apiRequest['params']['check_permissions']) or $apiRequest['params']['check_permissions'] == FALSE) {
46 $event->authorize();
47 $event->stopPropagation();
48 return;
49 }
50
51 require_once 'CRM/Core/DAO/permissions.php';
52 $permissions = _civicrm_api3_permissions($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
53
54 // $params might’ve been reset by the alterAPIPermissions() hook
55 if (isset($apiRequest['params']['check_permissions']) and $apiRequest['params']['check_permissions'] == FALSE) {
56 $event->authorize();
57 $event->stopPropagation();
58 return;
59 }
60
bc5585af 61 if (!\CRM_Core_Permission::check($permissions) and !self::checkACLPermission($apiRequest)) {
d0c9daa4 62 if (is_array($permissions)) {
829072f0
MM
63 foreach ($permissions as &$permission) {
64 if (is_array($permission)) {
65 $permission = '( ' . implode(' or ', $permission) . ' )';
66 }
67 }
d0c9daa4
TO
68 $permissions = implode(' and ', $permissions);
69 }
8882ff5c
TO
70 // FIXME: Generating the exception ourselves allows for detailed error
71 // but doesn't play well with multiple authz subscribers.
fedf821c 72 throw new \Civi\API\Exception\UnauthorizedException("API permission check failed for {$apiRequest['entity']}/{$apiRequest['action']} call; insufficient permission: require $permissions");
d0c9daa4
TO
73 }
74
75 $event->authorize();
76 $event->stopPropagation();
77 }
8bcc0d86
CW
78 elseif ($apiRequest['version'] == 4) {
79 if (!$apiRequest->getCheckPermissions()) {
80 $event->authorize();
81 $event->stopPropagation();
82 }
83 }
d0c9daa4 84 }
96025800 85
bc5585af 86 /**
c90c8245 87 * Check API for ACL permission.
88 *
89 * @param array $apiRequest
90 *
91 * @return bool
92 */
bc5585af 93 public function checkACLPermission($apiRequest) {
a909a20c 94 switch ($apiRequest['entity']) {
bc5585af 95 case 'UFGroup':
96 case 'UFField':
97 $ufGroups = \CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
98 $aclCreate = \CRM_ACL_API::group(\CRM_Core_Permission::CREATE, NULL, 'civicrm_uf_group', $ufGroups);
99 $aclEdit = \CRM_ACL_API::group(\CRM_Core_Permission::EDIT, NULL, 'civicrm_uf_group', $ufGroups);
100 $ufGroupId = $apiRequest['entity'] == 'UFGroup' ? $apiRequest['params']['id'] : $apiRequest['params']['uf_group_id'];
101 if (in_array($ufGroupId, $aclEdit) or $aclCreate) {
102 return TRUE;
103 }
104 break;
e68f2900
WA
105
106 //CRM-16777: Disable schedule reminder with ACLs.
107 case 'ActionSchedule':
108 $events = \CRM_Event_BAO_Event::getEvents();
109 $aclEdit = \CRM_ACL_API::group(\CRM_Core_Permission::EDIT, NULL, 'civicrm_event', $events);
c64f69d9
CW
110 $param = ['id' => $apiRequest['params']['id']];
111 $eventId = \CRM_Core_BAO_ActionSchedule::retrieve($param, $value = []);
e68f2900
WA
112 if (in_array($eventId->entity_value, $aclEdit)) {
113 return TRUE;
114 }
115 break;
bc5585af 116 }
117
118 return FALSE;
119 }
120
6550386a 121}