Merge pull request #17389 from seamuslee001/dev_core_1776
[civicrm-core.git] / tests / phpunit / E2E / Extern / RestTest.php
CommitLineData
49626e3d
CW
1<?php
2/*
3 +--------------------------------------------------------------------+
7d61e75f 4 | Copyright CiviCRM LLC. All rights reserved. |
49626e3d 5 | |
7d61e75f
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 |
49626e3d 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
49626e3d 11
83479334
TO
12/**
13 * Verify that the REST API bindings correctly parse and authenticate requests.
6769c30e
TO
14 *
15 * @group e2e
83479334 16 */
6769c30e 17class E2E_Extern_RestTest extends CiviEndToEndTestCase {
49626e3d 18 protected $url;
6769c30e 19 protected static $api_key;
49626e3d
CW
20 protected $session_id;
21 protected $nocms_contact_id;
38ba137b 22 protected $old_api_keys;
61001223 23 protected $adminContactId;
49626e3d 24
4cbe18b8
EM
25 /**
26 * @param $apiResult
27 * @param $cmpvar
28 * @param string $prefix
29 */
66eec473 30 protected function assertAPIErrorCode($apiResult, $cmpvar, $prefix = '') {
49626e3d
CW
31 if (!empty($prefix)) {
32 $prefix .= ': ';
33 }
6769c30e
TO
34 $this->assertEquals($cmpvar, $apiResult['is_error'],
35 $prefix . (empty($apiResult['error_message']) ? '' : $apiResult['error_message']));
668891f2 36 //$this->assertEquals($cmpvar, $apiResult['is_error'], $prefix . print_r($apiResult, TRUE));
49626e3d
CW
37 }
38
39 protected function setUp() {
40 parent::setUp();
49626e3d 41
6769c30e
TO
42 if (empty($GLOBALS['_CV']['CIVI_SITE_KEY'])) {
43 $this->markTestSkipped('Missing siteKey');
eb87411f 44 }
38ba137b 45
affcc9d2 46 $this->old_api_keys = [];
49626e3d
CW
47 }
48
6769c30e
TO
49 protected function getRestUrl() {
50 return CRM_Core_Resources::singleton()
51 ->getUrl('civicrm', 'extern/rest.php');
52 }
53
49626e3d 54 protected function tearDown() {
38ba137b
TO
55 if (!empty($this->old_api_keys)) {
56 foreach ($this->old_api_keys as $cid => $apiKey) {
6769c30e 57 civicrm_api3('Contact', 'create', array(
38ba137b
TO
58 'id' => $cid,
59 'api_key' => $apiKey,
60 ));
61 }
62 }
49626e3d 63 parent::tearDown();
016157f0 64 if (isset($this->nocms_contact_id)) {
49626e3d
CW
65 $deleteParams = array(
66 "id" => $this->nocms_contact_id,
21dfd5f5 67 "skip_undelete" => 1,
49626e3d 68 );
6769c30e 69 $res = civicrm_api3("Contact", "delete", $deleteParams);
49626e3d
CW
70 unset($this->nocms_contact_id);
71 }
72 }
73
3cabb1aa 74 /**
668891f2
TO
75 * Build a list of test cases. Each test case defines a set of REST query
76 * parameters and an expected outcome for the REST request (eg is_error=>1 or is_error=>0).
77 *
3cabb1aa
TO
78 * @return array; each item is a list of parameters for testAPICalls
79 */
00be9182 80 public function apiTestCases() {
affcc9d2 81 $cases = [];
3cabb1aa 82
668891f2
TO
83 // entity,action: omit apiKey, valid entity+action
84 $cases[] = array(
39b959db
SL
85 // query
86 array(
668891f2
TO
87 "entity" => "Contact",
88 "action" => "get",
6769c30e 89 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
668891f2
TO
90 "json" => "1",
91 ),
39b959db
SL
92 // is_error
93 1,
668891f2
TO
94 );
95
3cabb1aa
TO
96 // entity,action: valid apiKey, valid entity+action
97 $cases[] = array(
39b959db
SL
98 // query
99 array(
3cabb1aa
TO
100 "entity" => "Contact",
101 "action" => "get",
6769c30e 102 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 103 "json" => "1",
6769c30e 104 "api_key" => self::getApiKey(),
3cabb1aa 105 ),
39b959db
SL
106 // is_error
107 0,
016157f0 108 );
3cabb1aa
TO
109
110 // entity,action: bad apiKey, valid entity+action
111 $cases[] = array(
39b959db
SL
112 // query
113 array(
3cabb1aa
TO
114 "entity" => "Contact",
115 "action" => "get",
6769c30e 116 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 117 "json" => "1",
6769c30e 118 "api_key" => 'garbage_' . self::getApiKey(),
3cabb1aa 119 ),
39b959db
SL
120 // is_error
121 1,
3cabb1aa
TO
122 );
123
124 // entity,action: valid apiKey, invalid entity+action
125 $cases[] = array(
39b959db
SL
126 // query
127 array(
3cabb1aa
TO
128 "entity" => "Contactses",
129 "action" => "get",
6769c30e 130 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 131 "json" => "1",
6769c30e 132 "api_key" => self::getApiKey(),
3cabb1aa 133 ),
39b959db
SL
134 // is_error
135 1,
668891f2
TO
136 );
137
138 // q=civicrm/entity/action: omit apiKey, valid entity+action
139 $cases[] = array(
39b959db
SL
140 // query
141 array(
668891f2 142 "q" => "civicrm/contact/get",
6769c30e 143 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
668891f2
TO
144 "json" => "1",
145 ),
39b959db
SL
146 // is_error
147 1,
3cabb1aa
TO
148 );
149
150 // q=civicrm/entity/action: valid apiKey, valid entity+action
151 $cases[] = array(
39b959db
SL
152 // query
153 array(
3cabb1aa 154 "q" => "civicrm/contact/get",
6769c30e 155 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 156 "json" => "1",
6769c30e 157 "api_key" => self::getApiKey(),
3cabb1aa 158 ),
39b959db
SL
159 // is_error
160 0,
3cabb1aa
TO
161 );
162
163 // q=civicrm/entity/action: invalid apiKey, valid entity+action
164 $cases[] = array(
39b959db
SL
165 // query
166 array(
3cabb1aa 167 "q" => "civicrm/contact/get",
6769c30e 168 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 169 "json" => "1",
6769c30e 170 "api_key" => 'garbage_' . self::getApiKey(),
3cabb1aa 171 ),
39b959db
SL
172 // is_error
173 1,
3cabb1aa
TO
174 );
175
176 // q=civicrm/entity/action: valid apiKey, invalid entity+action
177 $cases[] = array(
39b959db
SL
178 // query
179 array(
3cabb1aa 180 "q" => "civicrm/contactses/get",
6769c30e 181 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
3cabb1aa 182 "json" => "1",
6769c30e 183 "api_key" => self::getApiKey(),
3cabb1aa 184 ),
39b959db
SL
185 // is_error
186 1,
3cabb1aa
TO
187 );
188
308e0075 189 // q=civicrm/entity/action: valid apiKey, invalid entity+action
cf739ea4 190 // XXX Actually Ping is valid, no?
308e0075 191 $cases[] = array(
39b959db
SL
192 // query
193 array(
308e0075 194 "q" => "civicrm/ping",
6769c30e 195 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
308e0075 196 "json" => "1",
6769c30e 197 "api_key" => self::getApiKey(),
308e0075 198 ),
39b959db
SL
199 // is_error
200 0,
308e0075
TO
201 );
202
3cabb1aa 203 return $cases;
49626e3d
CW
204 }
205
3cabb1aa
TO
206 /**
207 * @dataProvider apiTestCases
1e1fdcf6
EM
208 * @param $query
209 * @param $is_error
3cabb1aa 210 */
00be9182 211 public function testAPICalls($query, $is_error) {
38ba137b
TO
212 $this->updateAdminApiKey();
213
016157f0 214 $client = CRM_Utils_HttpClient::singleton();
6769c30e 215 list($status, $data) = $client->post($this->getRestUrl(), $query);
016157f0
TO
216 $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status);
217 $result = json_decode($data, TRUE);
d56bbdb3 218 if ($result === NULL) {
6769c30e
TO
219 $msg = print_r(array(
220 'restUrl' => $this->getRestUrl(),
221 'query' => $query,
222 'response data' => $data,
223 ), TRUE);
d56bbdb3
TO
224 $this->assertNotNull($result, $msg);
225 }
3cabb1aa 226 $this->assertAPIErrorCode($result, $is_error);
49626e3d
CW
227 }
228
0f051868 229 /**
eceb18cc 230 * Submit a request with an API key that exists but does not correspond to.
0f051868
TO
231 * a real user. Submit in "?entity=X&action=X" notation
232 */
00be9182 233 public function testNotCMSUser_entityAction() {
016157f0 234 $client = CRM_Utils_HttpClient::singleton();
0f051868 235
016157f0
TO
236 //Create contact with api_key
237 $test_key = "testing1234";
238 $contactParams = array(
239 "api_key" => $test_key,
240 "contact_type" => "Individual",
21dfd5f5 241 "first_name" => "RestTester1",
016157f0 242 );
6769c30e 243 $contact = civicrm_api3("Contact", "create", $contactParams);
016157f0 244 $this->nocms_contact_id = $contact["id"];
49626e3d 245
83479334 246 // The key associates with a real contact but not a real user
016157f0
TO
247 $params = array(
248 "entity" => "Contact",
249 "action" => "get",
6769c30e 250 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
016157f0 251 "json" => "1",
21dfd5f5 252 "api_key" => $test_key,
0f051868 253 );
6769c30e 254 list($status, $data) = $client->post($this->getRestUrl(), $params);
0f051868
TO
255 $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status);
256 $result = json_decode($data, TRUE);
257 $this->assertNotNull($result);
258 $this->assertAPIErrorCode($result, 1);
259 }
260
61001223
SL
261 /**
262 * Submit a request with an API key that exists but does not correspond to.
263 * a real user. Submit in "?entity=X&action=X" notation
264 */
265 public function testGetCorrectUserBack() {
266 $this->updateAdminApiKey();
267 $client = CRM_Utils_HttpClient::singleton();
268
269 //Create contact with api_key
270 // The key associates with a real contact but not a real user
271 $params = array(
272 "entity" => "Contact",
273 "action" => "get",
274 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
275 "json" => "1",
276 "api_key" => self::getApiKey(),
277 "id" => "user_contact_id",
278 );
279 list($status, $data) = $client->post($this->getRestUrl(), $params);
280 $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status);
281 $result = json_decode($data, TRUE);
282 $this->assertNotNull($result);
283 $this->assertEquals($result['id'], $this->adminContactId);
284 }
285
0f051868
TO
286 /**
287 * Submit a request with an API key that exists but does not correspond to
288 * a real user. Submit in "?q=civicrm/$entity/$action" notation
289 */
00be9182 290 public function testNotCMSUser_q() {
0f051868
TO
291 $client = CRM_Utils_HttpClient::singleton();
292
293 //Create contact with api_key
294 $test_key = "testing1234";
295 $contactParams = array(
296 "api_key" => $test_key,
297 "contact_type" => "Individual",
21dfd5f5 298 "first_name" => "RestTester1",
0f051868 299 );
6769c30e 300 $contact = civicrm_api3("Contact", "create", $contactParams);
0f051868
TO
301 $this->nocms_contact_id = $contact["id"];
302
83479334 303 // The key associates with a real contact but not a real user
0f051868
TO
304 $params = array(
305 "q" => "civicrm/contact/get",
6769c30e 306 "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'],
0f051868 307 "json" => "1",
21dfd5f5 308 "api_key" => $test_key,
016157f0 309 );
6769c30e 310 list($status, $data) = $client->post($this->getRestUrl(), $params);
016157f0
TO
311 $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status);
312 $result = json_decode($data, TRUE);
313 $this->assertNotNull($result);
314 $this->assertAPIErrorCode($result, 1);
49626e3d
CW
315 }
316
38ba137b 317 protected function updateAdminApiKey() {
6769c30e 318 /** @var int $adminContactId */
61001223 319 $this->adminContactId = civicrm_api3('contact', 'getvalue', array(
6769c30e
TO
320 'id' => '@user:' . $GLOBALS['_CV']['ADMIN_USER'],
321 'return' => 'id',
38ba137b
TO
322 ));
323
61001223
SL
324 $this->old_api_keys[$this->adminContactId] = CRM_Core_DAO::singleValueQuery('SELECT api_key FROM civicrm_contact WHERE id = %1', [
325 1 => [$this->adminContactId, 'Positive'],
420384a0 326 ]);
6769c30e
TO
327
328 //$this->old_admin_api_key = civicrm_api3('Contact', 'get', array(
329 // 'id' => $adminContactId,
38ba137b
TO
330 // 'return' => 'api_key',
331 //));
332
6769c30e 333 civicrm_api3('Contact', 'create', array(
61001223 334 'id' => $this->adminContactId,
6769c30e 335 'api_key' => self::getApiKey(),
38ba137b
TO
336 ));
337 }
338
6769c30e
TO
339 protected static function getApiKey() {
340 if (empty(self::$api_key)) {
341 self::$api_key = mt_rand() . mt_rand();
342 }
343 return self::$api_key;
344 }
345
49626e3d 346}