Commit | Line | Data |
---|---|---|
19b53e5b C |
1 | <?php |
2 | ||
380f3545 TO |
3 | /* |
4 | +--------------------------------------------------------------------+ | |
7d61e75f | 5 | | Copyright CiviCRM LLC. All rights reserved. | |
380f3545 | 6 | | | |
7d61e75f TO |
7 | | This work is published under the GNU AGPLv3 license with some | |
8 | | permitted exceptions and without any warranty. For full license | | |
9 | | and copyright information, see https://civicrm.org/licensing | | |
380f3545 TO |
10 | +--------------------------------------------------------------------+ |
11 | */ | |
12 | ||
13 | /** | |
14 | * | |
15 | * @package CRM | |
ca5cec67 | 16 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
380f3545 TO |
17 | */ |
18 | ||
19 | ||
19b53e5b C |
20 | namespace api\v4\Action; |
21 | ||
22 | use Civi\Api4\Contact; | |
23 | use Civi\Api4\Email; | |
24 | ||
25 | /** | |
26 | * @group headless | |
27 | */ | |
28 | class ContactApiKeyTest extends \api\v4\UnitTestCase { | |
29 | ||
30 | public function testGetApiKey() { | |
31 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'add contacts', 'edit api keys', 'view all contacts', 'edit all contacts']; | |
351af6f1 TO |
32 | $key = \CRM_Utils_String::createRandom(16, \CRM_Utils_String::ALPHANUMERIC); |
33 | $isSafe = function ($mixed) use ($key) { | |
351af6f1 TO |
34 | return strpos(json_encode($mixed), $key) === FALSE; |
35 | }; | |
19b53e5b C |
36 | |
37 | $contact = Contact::create() | |
38 | ->addValue('first_name', 'Api') | |
39 | ->addValue('last_name', 'Key0') | |
40 | ->addValue('api_key', $key) | |
41 | ->addChain('email', Email::create() | |
42 | ->addValue('contact_id', '$id') | |
43 | ->addValue('email', 'test@key.get'), | |
44 | 0 | |
45 | ) | |
46 | ->execute() | |
47 | ->first(); | |
48 | ||
49 | // With sufficient permission we should see the key | |
50 | $result = Contact::get() | |
51 | ->addWhere('id', '=', $contact['id']) | |
52 | ->addSelect('api_key') | |
53 | ->execute() | |
54 | ->first(); | |
55 | $this->assertEquals($key, $result['api_key']); | |
351af6f1 | 56 | $this->assertFalse($isSafe($result), "Should reveal secret details ($key): " . var_export($result, 1)); |
19b53e5b C |
57 | |
58 | // Can also be fetched via join | |
59 | $email = Email::get() | |
60 | ->addSelect('contact.api_key') | |
61 | ->addWhere('id', '=', $contact['email']['id']) | |
62 | ->execute()->first(); | |
63 | $this->assertEquals($key, $email['contact.api_key']); | |
351af6f1 | 64 | $this->assertFalse($isSafe($email), "Should reveal secret details ($key): " . var_export($email, 1)); |
19b53e5b C |
65 | |
66 | // Remove permission and we should not see the key | |
a689294c | 67 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'view debug output', 'view all contacts']; |
19b53e5b C |
68 | $result = Contact::get() |
69 | ->addWhere('id', '=', $contact['id']) | |
70 | ->addSelect('api_key') | |
a689294c CW |
71 | ->setDebug(TRUE) |
72 | ->execute(); | |
73 | $this->assertContains('api_key', $result->debug['undefined_fields']); | |
74 | $this->assertArrayNotHasKey('api_key', $result[0]); | |
75 | $this->assertTrue($isSafe($result[0]), "Should NOT reveal secret details ($key): " . var_export($result[0], 1)); | |
19b53e5b C |
76 | |
77 | // Also not available via join | |
78 | $email = Email::get() | |
79 | ->addSelect('contact.api_key') | |
80 | ->addWhere('id', '=', $contact['email']['id']) | |
a689294c CW |
81 | ->setDebug(TRUE) |
82 | ->execute(); | |
83 | $this->assertContains('contact.api_key', $email->debug['undefined_fields']); | |
84 | $this->assertArrayNotHasKey('contact.api_key', $email[0]); | |
85 | $this->assertTrue($isSafe($email[0]), "Should NOT reveal secret details ($key): " . var_export($email[0], 1)); | |
19b53e5b C |
86 | |
87 | $result = Contact::get() | |
88 | ->addWhere('id', '=', $contact['id']) | |
89 | ->execute() | |
90 | ->first(); | |
a689294c | 91 | $this->assertArrayNotHasKey('api_key', $result); |
351af6f1 | 92 | $this->assertTrue($isSafe($result), "Should NOT reveal secret details ($key): " . var_export($result, 1)); |
19b53e5b C |
93 | } |
94 | ||
95 | public function testCreateWithInsufficientPermissions() { | |
96 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'add contacts']; | |
97 | $key = uniqid(); | |
98 | ||
99 | $error = ''; | |
100 | try { | |
101 | Contact::create() | |
102 | ->addValue('first_name', 'Api') | |
103 | ->addValue('last_name', 'Key1') | |
104 | ->addValue('api_key', $key) | |
105 | ->execute() | |
106 | ->first(); | |
107 | } | |
108 | catch (\Exception $e) { | |
109 | $error = $e->getMessage(); | |
110 | } | |
111 | $this->assertContains('key', $error); | |
112 | } | |
113 | ||
351af6f1 TO |
114 | public function testGetApiKeyViaJoin() { |
115 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'view all contacts']; | |
116 | $key = \CRM_Utils_String::createRandom(16, \CRM_Utils_String::ALPHANUMERIC); | |
117 | $isSafe = function ($mixed) use ($key) { | |
118 | if ($mixed instanceof Result) { | |
119 | $mixed = $mixed->getArrayCopy(); | |
120 | } | |
121 | return strpos(json_encode($mixed), $key) === FALSE; | |
122 | }; | |
123 | ||
6764a9d3 | 124 | $contact = Contact::create(FALSE) |
351af6f1 TO |
125 | ->addValue('first_name', 'Api') |
126 | ->addValue('last_name', 'Key0') | |
127 | ->addValue('api_key', $key) | |
128 | ->execute() | |
129 | ->first(); | |
130 | $this->assertFalse($isSafe($contact), "Should reveal secret details ($key): " . var_export($contact, 1)); | |
131 | ||
6764a9d3 | 132 | Email::create(FALSE) |
351af6f1 TO |
133 | ->addValue('email', 'foo@example.org') |
134 | ->addValue('contact_id', $contact['id']) | |
135 | ->execute(); | |
136 | ||
6764a9d3 | 137 | $result = Email::get(FALSE) |
351af6f1 TO |
138 | ->addWhere('contact_id', '=', $contact['id']) |
139 | ->addSelect('email') | |
140 | ->addSelect('contact.api_key') | |
141 | ->execute() | |
142 | ->first(); | |
143 | $this->assertFalse($isSafe($result), "Should reveal secret details ($key): " . var_export($result, 1)); | |
144 | ||
6764a9d3 | 145 | $result = Email::get(TRUE) |
351af6f1 TO |
146 | ->addWhere('contact_id', '=', $contact['id']) |
147 | ->addSelect('contact.api_key') | |
148 | ->execute() | |
149 | ->first(); | |
150 | $this->assertTrue($isSafe($result), "Should NOT reveal secret details ($key): " . var_export($result, 1)); | |
151 | } | |
152 | ||
19b53e5b C |
153 | public function testUpdateApiKey() { |
154 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit all contacts']; | |
155 | $key = uniqid(); | |
156 | ||
6764a9d3 | 157 | $contact = Contact::create(FALSE) |
19b53e5b C |
158 | ->addValue('first_name', 'Api') |
159 | ->addValue('last_name', 'Key2') | |
160 | ->addValue('api_key', $key) | |
161 | ->execute() | |
162 | ->first(); | |
163 | ||
164 | $error = ''; | |
165 | try { | |
166 | // Try to update the key without permissions; nothing should happen | |
167 | Contact::update() | |
168 | ->addWhere('id', '=', $contact['id']) | |
169 | ->addValue('api_key', "NotAllowed") | |
170 | ->execute(); | |
171 | } | |
172 | catch (\Exception $e) { | |
173 | $error = $e->getMessage(); | |
174 | } | |
175 | ||
6764a9d3 | 176 | $result = Contact::get(FALSE) |
19b53e5b C |
177 | ->addWhere('id', '=', $contact['id']) |
178 | ->addSelect('api_key') | |
179 | ->execute() | |
180 | ->first(); | |
181 | ||
182 | $this->assertContains('key', $error); | |
183 | ||
184 | // Assert key is still the same | |
185 | $this->assertEquals($result['api_key'], $key); | |
186 | ||
187 | // Now we can update the key | |
188 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM', 'edit all contacts']; | |
189 | ||
190 | Contact::update() | |
191 | ->addWhere('id', '=', $contact['id']) | |
192 | ->addValue('api_key', "IGotThePower!") | |
193 | ->execute(); | |
194 | ||
195 | $result = Contact::get() | |
196 | ->addWhere('id', '=', $contact['id']) | |
197 | ->addSelect('api_key') | |
198 | ->execute() | |
199 | ->first(); | |
200 | ||
201 | // Assert key was updated | |
202 | $this->assertEquals($result['api_key'], "IGotThePower!"); | |
203 | } | |
204 | ||
205 | public function testUpdateOwnApiKey() { | |
206 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit own api keys', 'edit all contacts']; | |
207 | $key = uniqid(); | |
208 | ||
6764a9d3 | 209 | $contact = Contact::create(FALSE) |
19b53e5b C |
210 | ->addValue('first_name', 'Api') |
211 | ->addValue('last_name', 'Key3') | |
212 | ->addValue('api_key', $key) | |
213 | ->execute() | |
214 | ->first(); | |
215 | ||
216 | $error = ''; | |
217 | try { | |
218 | // Try to update the key without permissions; nothing should happen | |
219 | Contact::update() | |
220 | ->addWhere('id', '=', $contact['id']) | |
221 | ->addValue('api_key', "NotAllowed") | |
222 | ->execute(); | |
223 | } | |
224 | catch (\Exception $e) { | |
225 | $error = $e->getMessage(); | |
226 | } | |
227 | ||
228 | $this->assertContains('key', $error); | |
229 | ||
6764a9d3 | 230 | $result = Contact::get(FALSE) |
19b53e5b C |
231 | ->addWhere('id', '=', $contact['id']) |
232 | ->addSelect('api_key') | |
233 | ->execute() | |
234 | ->first(); | |
235 | ||
236 | // Assert key is still the same | |
237 | $this->assertEquals($result['api_key'], $key); | |
238 | ||
239 | // Now we can update the key | |
240 | \CRM_Core_Session::singleton()->set('userID', $contact['id']); | |
241 | ||
242 | Contact::update() | |
243 | ->addWhere('id', '=', $contact['id']) | |
244 | ->addValue('api_key', "MyId!") | |
245 | ->execute(); | |
246 | ||
6764a9d3 | 247 | $result = Contact::get(FALSE) |
19b53e5b C |
248 | ->addWhere('id', '=', $contact['id']) |
249 | ->addSelect('api_key') | |
250 | ->execute() | |
251 | ->first(); | |
252 | ||
253 | // Assert key was updated | |
254 | $this->assertEquals($result['api_key'], "MyId!"); | |
255 | } | |
256 | ||
257 | public function testApiKeyWithGetFields() { | |
258 | // With sufficient permissions the field should exist | |
259 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit api keys']; | |
260 | $this->assertArrayHasKey('api_key', \civicrm_api4('Contact', 'getFields', [], 'name')); | |
261 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM']; | |
262 | $this->assertArrayHasKey('api_key', \civicrm_api4('Contact', 'getFields', [], 'name')); | |
263 | ||
264 | // Field hidden from non-privileged users... | |
265 | \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit own api keys']; | |
266 | $this->assertArrayNotHasKey('api_key', \civicrm_api4('Contact', 'getFields', [], 'name')); | |
267 | ||
268 | // ...unless you disable 'checkPermissions' | |
269 | $this->assertArrayHasKey('api_key', \civicrm_api4('Contact', 'getFields', ['checkPermissions' => FALSE], 'name')); | |
270 | } | |
271 | ||
272 | } |