Commit | Line | Data |
---|---|---|
49626e3d CW |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
2fe49090 | 4 | | CiviCRM version 5 | |
49626e3d | 5 | +--------------------------------------------------------------------+ |
8c9251b3 | 6 | | Copyright CiviCRM LLC (c) 2004-2018 | |
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 | 32 | class 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; |
49626e3d | 38 | |
4cbe18b8 EM |
39 | /** |
40 | * @param $apiResult | |
41 | * @param $cmpvar | |
42 | * @param string $prefix | |
43 | */ | |
66eec473 | 44 | protected function assertAPIErrorCode($apiResult, $cmpvar, $prefix = '') { |
49626e3d CW |
45 | if (!empty($prefix)) { |
46 | $prefix .= ': '; | |
47 | } | |
6769c30e TO |
48 | $this->assertEquals($cmpvar, $apiResult['is_error'], |
49 | $prefix . (empty($apiResult['error_message']) ? '' : $apiResult['error_message'])); | |
668891f2 | 50 | //$this->assertEquals($cmpvar, $apiResult['is_error'], $prefix . print_r($apiResult, TRUE)); |
49626e3d CW |
51 | } |
52 | ||
53 | protected function setUp() { | |
54 | parent::setUp(); | |
49626e3d | 55 | |
6769c30e TO |
56 | if (empty($GLOBALS['_CV']['CIVI_SITE_KEY'])) { |
57 | $this->markTestSkipped('Missing siteKey'); | |
eb87411f | 58 | } |
38ba137b TO |
59 | |
60 | $this->old_api_keys = array(); | |
49626e3d CW |
61 | } |
62 | ||
6769c30e TO |
63 | protected function getRestUrl() { |
64 | return CRM_Core_Resources::singleton() | |
65 | ->getUrl('civicrm', 'extern/rest.php'); | |
66 | } | |
67 | ||
49626e3d | 68 | protected function tearDown() { |
38ba137b TO |
69 | if (!empty($this->old_api_keys)) { |
70 | foreach ($this->old_api_keys as $cid => $apiKey) { | |
6769c30e | 71 | civicrm_api3('Contact', 'create', array( |
38ba137b TO |
72 | 'id' => $cid, |
73 | 'api_key' => $apiKey, | |
74 | )); | |
75 | } | |
76 | } | |
49626e3d | 77 | parent::tearDown(); |
016157f0 | 78 | if (isset($this->nocms_contact_id)) { |
49626e3d CW |
79 | $deleteParams = array( |
80 | "id" => $this->nocms_contact_id, | |
21dfd5f5 | 81 | "skip_undelete" => 1, |
49626e3d | 82 | ); |
6769c30e | 83 | $res = civicrm_api3("Contact", "delete", $deleteParams); |
49626e3d CW |
84 | unset($this->nocms_contact_id); |
85 | } | |
86 | } | |
87 | ||
3cabb1aa | 88 | /** |
668891f2 TO |
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 | * | |
3cabb1aa TO |
92 | * @return array; each item is a list of parameters for testAPICalls |
93 | */ | |
00be9182 | 94 | public function apiTestCases() { |
3cabb1aa TO |
95 | $cases = array(); |
96 | ||
668891f2 TO |
97 | // entity,action: omit apiKey, valid entity+action |
98 | $cases[] = array( | |
481a74f4 | 99 | array(// query |
668891f2 TO |
100 | "entity" => "Contact", |
101 | "action" => "get", | |
6769c30e | 102 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
668891f2 TO |
103 | "json" => "1", |
104 | ), | |
105 | 1, // is_error | |
106 | ); | |
107 | ||
3cabb1aa TO |
108 | // entity,action: valid apiKey, valid entity+action |
109 | $cases[] = array( | |
481a74f4 | 110 | array(// query |
3cabb1aa TO |
111 | "entity" => "Contact", |
112 | "action" => "get", | |
6769c30e | 113 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 114 | "json" => "1", |
6769c30e | 115 | "api_key" => self::getApiKey(), |
3cabb1aa | 116 | ), |
668891f2 | 117 | 0, // is_error |
016157f0 | 118 | ); |
3cabb1aa TO |
119 | |
120 | // entity,action: bad apiKey, valid entity+action | |
121 | $cases[] = array( | |
481a74f4 | 122 | array(// query |
3cabb1aa TO |
123 | "entity" => "Contact", |
124 | "action" => "get", | |
6769c30e | 125 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 126 | "json" => "1", |
6769c30e | 127 | "api_key" => 'garbage_' . self::getApiKey(), |
3cabb1aa | 128 | ), |
668891f2 | 129 | 1, // is_error |
3cabb1aa TO |
130 | ); |
131 | ||
132 | // entity,action: valid apiKey, invalid entity+action | |
133 | $cases[] = array( | |
481a74f4 | 134 | array(// query |
3cabb1aa TO |
135 | "entity" => "Contactses", |
136 | "action" => "get", | |
6769c30e | 137 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 138 | "json" => "1", |
6769c30e | 139 | "api_key" => self::getApiKey(), |
3cabb1aa | 140 | ), |
668891f2 TO |
141 | 1, // is_error |
142 | ); | |
143 | ||
144 | // q=civicrm/entity/action: omit apiKey, valid entity+action | |
145 | $cases[] = array( | |
481a74f4 | 146 | array(// query |
668891f2 | 147 | "q" => "civicrm/contact/get", |
6769c30e | 148 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
668891f2 TO |
149 | "json" => "1", |
150 | ), | |
151 | 1, // is_error | |
3cabb1aa TO |
152 | ); |
153 | ||
154 | // q=civicrm/entity/action: valid apiKey, valid entity+action | |
155 | $cases[] = array( | |
481a74f4 | 156 | array(// query |
3cabb1aa | 157 | "q" => "civicrm/contact/get", |
6769c30e | 158 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 159 | "json" => "1", |
6769c30e | 160 | "api_key" => self::getApiKey(), |
3cabb1aa | 161 | ), |
668891f2 | 162 | 0, // is_error |
3cabb1aa TO |
163 | ); |
164 | ||
165 | // q=civicrm/entity/action: invalid apiKey, valid entity+action | |
166 | $cases[] = array( | |
481a74f4 | 167 | array(// query |
3cabb1aa | 168 | "q" => "civicrm/contact/get", |
6769c30e | 169 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 170 | "json" => "1", |
6769c30e | 171 | "api_key" => 'garbage_' . self::getApiKey(), |
3cabb1aa | 172 | ), |
668891f2 | 173 | 1, // is_error |
3cabb1aa TO |
174 | ); |
175 | ||
176 | // q=civicrm/entity/action: valid apiKey, invalid entity+action | |
177 | $cases[] = array( | |
481a74f4 | 178 | array(// query |
3cabb1aa | 179 | "q" => "civicrm/contactses/get", |
6769c30e | 180 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
3cabb1aa | 181 | "json" => "1", |
6769c30e | 182 | "api_key" => self::getApiKey(), |
3cabb1aa | 183 | ), |
668891f2 | 184 | 1, // is_error |
3cabb1aa TO |
185 | ); |
186 | ||
308e0075 | 187 | // q=civicrm/entity/action: valid apiKey, invalid entity+action |
cf739ea4 | 188 | // XXX Actually Ping is valid, no? |
308e0075 | 189 | $cases[] = array( |
481a74f4 | 190 | array(// query |
308e0075 | 191 | "q" => "civicrm/ping", |
6769c30e | 192 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
308e0075 | 193 | "json" => "1", |
6769c30e | 194 | "api_key" => self::getApiKey(), |
308e0075 TO |
195 | ), |
196 | 0, // is_error | |
197 | ); | |
198 | ||
3cabb1aa | 199 | return $cases; |
49626e3d CW |
200 | } |
201 | ||
3cabb1aa TO |
202 | /** |
203 | * @dataProvider apiTestCases | |
1e1fdcf6 EM |
204 | * @param $query |
205 | * @param $is_error | |
3cabb1aa | 206 | */ |
00be9182 | 207 | public function testAPICalls($query, $is_error) { |
38ba137b TO |
208 | $this->updateAdminApiKey(); |
209 | ||
016157f0 | 210 | $client = CRM_Utils_HttpClient::singleton(); |
6769c30e | 211 | list($status, $data) = $client->post($this->getRestUrl(), $query); |
016157f0 TO |
212 | $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status); |
213 | $result = json_decode($data, TRUE); | |
d56bbdb3 | 214 | if ($result === NULL) { |
6769c30e TO |
215 | $msg = print_r(array( |
216 | 'restUrl' => $this->getRestUrl(), | |
217 | 'query' => $query, | |
218 | 'response data' => $data, | |
219 | ), TRUE); | |
d56bbdb3 TO |
220 | $this->assertNotNull($result, $msg); |
221 | } | |
3cabb1aa | 222 | $this->assertAPIErrorCode($result, $is_error); |
49626e3d CW |
223 | } |
224 | ||
0f051868 | 225 | /** |
eceb18cc | 226 | * Submit a request with an API key that exists but does not correspond to. |
0f051868 TO |
227 | * a real user. Submit in "?entity=X&action=X" notation |
228 | */ | |
00be9182 | 229 | public function testNotCMSUser_entityAction() { |
016157f0 | 230 | $client = CRM_Utils_HttpClient::singleton(); |
0f051868 | 231 | |
016157f0 TO |
232 | //Create contact with api_key |
233 | $test_key = "testing1234"; | |
234 | $contactParams = array( | |
235 | "api_key" => $test_key, | |
236 | "contact_type" => "Individual", | |
21dfd5f5 | 237 | "first_name" => "RestTester1", |
016157f0 | 238 | ); |
6769c30e | 239 | $contact = civicrm_api3("Contact", "create", $contactParams); |
016157f0 | 240 | $this->nocms_contact_id = $contact["id"]; |
49626e3d | 241 | |
83479334 | 242 | // The key associates with a real contact but not a real user |
016157f0 TO |
243 | $params = array( |
244 | "entity" => "Contact", | |
245 | "action" => "get", | |
6769c30e | 246 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
016157f0 | 247 | "json" => "1", |
21dfd5f5 | 248 | "api_key" => $test_key, |
0f051868 | 249 | ); |
6769c30e | 250 | list($status, $data) = $client->post($this->getRestUrl(), $params); |
0f051868 TO |
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 | */ | |
00be9182 | 261 | public function testNotCMSUser_q() { |
0f051868 TO |
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", | |
21dfd5f5 | 269 | "first_name" => "RestTester1", |
0f051868 | 270 | ); |
6769c30e | 271 | $contact = civicrm_api3("Contact", "create", $contactParams); |
0f051868 TO |
272 | $this->nocms_contact_id = $contact["id"]; |
273 | ||
83479334 | 274 | // The key associates with a real contact but not a real user |
0f051868 TO |
275 | $params = array( |
276 | "q" => "civicrm/contact/get", | |
6769c30e | 277 | "key" => $GLOBALS['_CV']['CIVI_SITE_KEY'], |
0f051868 | 278 | "json" => "1", |
21dfd5f5 | 279 | "api_key" => $test_key, |
016157f0 | 280 | ); |
6769c30e | 281 | list($status, $data) = $client->post($this->getRestUrl(), $params); |
016157f0 TO |
282 | $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status); |
283 | $result = json_decode($data, TRUE); | |
284 | $this->assertNotNull($result); | |
285 | $this->assertAPIErrorCode($result, 1); | |
49626e3d CW |
286 | } |
287 | ||
38ba137b | 288 | protected function updateAdminApiKey() { |
6769c30e TO |
289 | /** @var int $adminContactId */ |
290 | $adminContactId = civicrm_api3('contact', 'getvalue', array( | |
291 | 'id' => '@user:' . $GLOBALS['_CV']['ADMIN_USER'], | |
292 | 'return' => 'id', | |
38ba137b TO |
293 | )); |
294 | ||
6769c30e TO |
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, | |
38ba137b TO |
302 | // 'return' => 'api_key', |
303 | //)); | |
304 | ||
6769c30e TO |
305 | civicrm_api3('Contact', 'create', array( |
306 | 'id' => $adminContactId, | |
307 | 'api_key' => self::getApiKey(), | |
38ba137b TO |
308 | )); |
309 | } | |
310 | ||
6769c30e TO |
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 | ||
49626e3d | 318 | } |