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