APIv4 - Use non-deprecated join syntax internally
[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 */
18
19
19b53e5b
C
20namespace api\v4\Action;
21
22use Civi\Api4\Contact;
23use Civi\Api4\Email;
24
25/**
26 * @group headless
27 */
28class 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()
84ad7693 60 ->addSelect('contact_id.api_key')
19b53e5b
C
61 ->addWhere('id', '=', $contact['email']['id'])
62 ->execute()->first();
84ad7693 63 $this->assertEquals($key, $email['contact_id.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()
84ad7693 79 ->addSelect('contact_id.api_key')
19b53e5b 80 ->addWhere('id', '=', $contact['email']['id'])
a689294c
CW
81 ->setDebug(TRUE)
82 ->execute();
84ad7693
CW
83 $this->assertContains('contact_id.api_key', $email->debug['undefined_fields']);
84 $this->assertArrayNotHasKey('contact_id.api_key', $email[0]);
a689294c 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 }
df347a8c 111 $this->assertStringContainsString('key', $error);
19b53e5b
C
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')
84ad7693 140 ->addSelect('contact_id.api_key')
351af6f1
TO
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 146 ->addWhere('contact_id', '=', $contact['id'])
84ad7693 147 ->addSelect('contact_id.api_key')
351af6f1
TO
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
df347a8c 182 $this->assertStringContainsString('key', $error);
19b53e5b
C
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
df347a8c 228 $this->assertStringContainsString('key', $error);
19b53e5b 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}