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