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