Merge pull request #18158 from mattwire/createProfileContact
[civicrm-core.git] / Civi / API / Subscriber / WhitelistSubscriber.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 namespace Civi\API\Subscriber;
12
13 use Civi\API\Events;
14 use Civi\API\Event\AuthorizeEvent;
15 use Civi\API\Event\RespondEvent;
16 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
18 /**
19 * The WhitelistSubscriber listens to API requests and matches them against
20 * a whitelist of allowed API calls. If an API call does NOT appear in the
21 * whitelist, then it generates an error.
22 *
23 * @package Civi
24 * @copyright CiviCRM LLC https://civicrm.org/licensing
25 */
26 class WhitelistSubscriber implements EventSubscriberInterface {
27
28 /**
29 * @return array
30 */
31 public static function getSubscribedEvents() {
32 return [
33 'civi.api.authorize' => ['onApiAuthorize', Events::W_EARLY],
34 'civi.api.respond' => ['onApiRespond', Events::W_MIDDLE],
35 ];
36 }
37
38 /**
39 * Array(WhitelistRule).
40 *
41 * @var array
42 */
43 protected $rules;
44
45 /**
46 * Array (scalar $reqId => WhitelistRule $rule).
47 *
48 * @var array
49 */
50 protected $activeRules;
51
52 /**
53 * @param array $rules
54 * Array of WhitelistRule.
55 * @see WhitelistRule
56 * @throws \CRM_Core_Exception
57 */
58 public function __construct($rules) {
59 $this->rules = [];
60 foreach ($rules as $rule) {
61 /** @var \Civi\API\WhitelistRule $rule */
62 if ($rule->isValid()) {
63 $this->rules[] = $rule;
64 }
65 else {
66 throw new \CRM_Core_Exception("Invalid rule");
67 }
68 }
69 }
70
71 /**
72 * Determine which, if any, whitelist rules apply this request.
73 * Reject unauthorized requests.
74 *
75 * @param \Civi\API\Event\AuthorizeEvent $event
76 * @throws \CRM_Core_Exception
77 */
78 public function onApiAuthorize(AuthorizeEvent $event) {
79 $apiRequest = $event->getApiRequest();
80 if (empty($apiRequest['params']['check_permissions']) || $apiRequest['params']['check_permissions'] !== 'whitelist') {
81 return;
82 }
83 foreach ($this->rules as $rule) {
84 if (TRUE === $rule->matches($apiRequest)) {
85 $this->activeRules[$apiRequest['id']] = $rule;
86 return;
87 }
88 }
89 throw new \CRM_Core_Exception('The request does not match any active API authorizations.');
90 }
91
92 /**
93 * Apply any filtering rules based on the chosen whitelist rule.
94 * @param \Civi\API\Event\RespondEvent $event
95 */
96 public function onApiRespond(RespondEvent $event) {
97 $apiRequest = $event->getApiRequest();
98 $id = $apiRequest['id'];
99 if (isset($this->activeRules[$id])) {
100 $event->setResponse($this->activeRules[$id]->filter($apiRequest, $event->getResponse()));
101 unset($this->activeRules[$id]);
102 }
103 }
104
105 }