]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/service/RESTAPI4Test.php
Release 6.4.0
[Github/sugarcrm.git] / tests / service / RESTAPI4Test.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38 require_once('service/v3/SugarWebServiceUtilv3.php');
39 require_once('tests/service/APIv3Helper.php');
40
41
42 class RESTAPI4Test extends Sugar_PHPUnit_Framework_TestCase
43 {
44     protected $_user;
45     protected $_admin_user;
46     protected $_lastRawResponse;
47
48     private static $helperObject;
49
50     protected $aclRole;
51     protected $aclField;
52
53     public function setUp()
54     {
55         $beanList = array();
56                 $beanFiles = array();
57                 require('include/modules.php');
58                 $GLOBALS['beanList'] = $beanList;
59                 $GLOBALS['beanFiles'] = $beanFiles;
60
61         //Reload langauge strings
62         $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
63         $GLOBALS['app_list_strings'] = return_app_list_strings_language($GLOBALS['current_language']);
64         $GLOBALS['mod_strings'] = return_module_language($GLOBALS['current_language'], 'Accounts');
65         //Create an anonymous user for login purposes/
66         $this->_user = SugarTestUserUtilities::createAnonymousUser();
67
68         $this->_admin_user = SugarTestUserUtilities::createAnonymousUser();
69         $this->_admin_user->status = 'Active';
70         $this->_admin_user->is_admin = 1;
71         $this->_admin_user->save();
72         $GLOBALS['db']->commit(); // Making sure we commit any changes before continuing
73
74         $GLOBALS['current_user'] = $this->_user;
75
76         self::$helperObject = new APIv3Helper();
77
78         //Disable access to the website field.
79         $this->aclRole = new ACLRole();
80         $this->aclRole->name = "Unit Test";
81         $this->aclRole->save();
82         $GLOBALS['db']->commit(); // Making sure we commit any changes before continuing
83
84         $this->aclRole->set_relationship('acl_roles_users', array('role_id'=>$this->aclRole->id ,'user_id'=> $this->_user->id), false);
85         $GLOBALS['db']->commit(); // Making sure we commit any changes before continuing
86     }
87
88     public function tearDown()
89         {
90             $GLOBALS['db']->query("DELETE FROM acl_roles WHERE id IN ( SELECT role_id FROM acl_roles_users WHERE user_id = '{$GLOBALS['current_user']->id}' )");
91             $GLOBALS['db']->query("DELETE FROM acl_roles_users WHERE user_id = '{$GLOBALS['current_user']->id}'");
92
93             if(isset($GLOBALS['listViewDefs'])) unset($GLOBALS['listViewDefs']);
94             if(isset($GLOBALS['viewdefs'])) unset($GLOBALS['viewdefs']);
95             unset($GLOBALS['beanList']);
96                 unset($GLOBALS['beanFiles']);
97                 unset($GLOBALS['app_list_strings']);
98             unset($GLOBALS['app_strings']);
99             unset($GLOBALS['mod_strings']);
100             unset($GLOBALS['current_user']);
101         SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
102         }
103
104     protected function _makeRESTCall($method,$parameters)
105     {
106         // specify the REST web service to interact with
107         $url = $GLOBALS['sugar_config']['site_url'].'/service/v4/rest.php';
108         // Open a curl session for making the call
109         $curl = curl_init($url);
110         // set URL and other appropriate options
111         curl_setopt($curl, CURLOPT_URL, $url);
112         curl_setopt($curl, CURLOPT_POST, 1);
113         curl_setopt($curl, CURLOPT_HEADER, 0);
114         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
115         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
116         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0);
117         curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 );
118         // build the request URL
119         $json = json_encode($parameters);
120         $postArgs = "method=$method&input_type=JSON&response_type=JSON&rest_data=$json";
121         curl_setopt($curl, CURLOPT_POSTFIELDS, $postArgs);
122         // Make the REST call, returning the result
123         $response = curl_exec($curl);
124         // Close the connection
125         curl_close($curl);
126
127         $this->_lastRawResponse = $response;
128
129         // Convert the result from JSON format to a PHP array
130         return json_decode($response,true);
131     }
132
133     protected function _returnLastRawResponse()
134     {
135         return "Error in web services call. Response was: {$this->_lastRawResponse}";
136     }
137
138     protected function _login($user = null)
139     {
140         $GLOBALS['db']->commit(); // Making sure we commit any changes before logging in
141         if($user == null)
142             $user = $this->_user;
143         return $this->_makeRESTCall('login',
144             array(
145                 'user_auth' =>
146                     array(
147                         'user_name' => $user->user_name,
148                         'password' => $user->user_hash,
149                         'version' => '.01',
150                         ),
151                 'application_name' => 'mobile',
152                 'name_value_list' => array(),
153                 )
154             );
155     }
156     /**
157      * Ensure the ability to retrieve a module list of recrods that are favorites.
158      *
159      */
160     public function testGetModuleFavoriteList()
161     {
162         $account = new Account();
163         $account->id = uniqid();
164         $account->new_with_id = TRUE;
165         $account->name = "Test " . $account->id;
166         $account->save();
167
168         $result = $this->_login($this->_admin_user); // Logging in just before the REST call as this will also commit any pending DB changes
169         $session = $result['id'];
170
171         $this->_markBeanAsFavorite($session, "Accounts", $account->id);
172
173         $whereClause = "accounts.name='{$account->name}'";
174         $module = 'Accounts';
175         $orderBy = 'name';
176         $offset = 0;
177         $returnFields = array('name');
178         $linkNameFields = "";
179         $maxResults = 50;
180         $deleted = FALSE;
181         $favorites = TRUE;
182         $result = $this->_makeRESTCall('get_entry_list', array($session, $module, $whereClause, $orderBy,$offset, $returnFields,$linkNameFields, $maxResults, $deleted, $favorites));
183
184         $this->assertEquals($account->id, $result['entry_list'][0]['id'],'Unable to retrieve account favorite list.');
185
186         $GLOBALS['db']->query("DELETE FROM accounts WHERE id = '{$account->id}'");
187         $GLOBALS['db']->query("DELETE FROM sugarfavorites WHERE record_id = '{$account->id}'");
188     }
189
190     /**
191      * Test set entries call with name value list format key=>value.
192      *
193      */
194     public function testSetEntriesCall()
195     {
196         $result = $this->_login();
197         $session = $result['id'];
198         $module = 'Contacts';
199         $c1_uuid = uniqid();
200         $c2_uuid = uniqid();
201         $contacts = array(
202             array('first_name' => 'Unit Test', 'last_name' => $c1_uuid),
203             array('first_name' => 'Unit Test', 'last_name' => $c2_uuid)
204         );
205         $results = $this->_makeRESTCall('set_entries',
206         array(
207             'session' => $session,
208             'module' => $module,
209             'name_value_lists' => $contacts,
210         ));
211         $this->assertTrue(isset($results['ids']) && count($results['ids']) == 2);
212
213         $actual_results = $this->_makeRESTCall('get_entries',
214         array(
215             'session' => $session,
216             'module' => $module,
217             'ids' => $results['ids'],
218             'select_fields' => array('first_name','last_name')
219         ));
220
221         $this->assertTrue(isset($actual_results['entry_list']) && count($actual_results['entry_list']) == 2);
222         $this->assertEquals($actual_results['entry_list'][0]['name_value_list']['last_name']['value'], $c1_uuid);
223         $this->assertEquals($actual_results['entry_list'][1]['name_value_list']['last_name']['value'], $c2_uuid);
224     }
225
226
227     /**
228      * Test search by module with favorites flag enabled.
229      *
230      */
231     public function testSearchByModuleWithFavorites()
232     {
233         $account = new Account();
234         $account->id = uniqid();
235         $account->assigned_user_id = $this->_user->id;
236         $account->team_id = 1;
237         $account->new_with_id = TRUE;
238         $account->name = "Unit Test Fav " . $account->id;
239         $account->save();
240
241         //Negative test.
242         $account2 = new Account();
243         $account2->id = uniqid();
244         $account2->new_with_id = TRUE;
245         $account2->name = "Unit Test Fav " . $account->id;
246         $account->assigned_user_id = $this->_user->id;
247         $account2->save();
248
249         $result = $this->_login($this->_admin_user); // Logging in just before the REST call as this will also commit any pending DB changes
250         $session = $result['id'];
251
252         $this->_markBeanAsFavorite($session, "Accounts", $account->id);
253
254         $searchModules = array('Accounts');
255         $searchString = "Unit Test Fav ";
256         $offSet = 0;
257         $maxResults = 10;
258
259         $results = $this->_makeRESTCall('search_by_module',
260                         array(
261                             'session' => $session,
262                             'search_string'  => $searchString,
263                             'modules' => $searchModules,
264                             'offset'  => $offSet,
265                             'max_results'     => $maxResults,
266                             'assigned_user_id'    => $this->_user->id,
267                             'select_fields' => array(),
268                             'unified_search_only' => true,
269                             'favorites' => true,
270                             )
271                         );
272
273         $GLOBALS['db']->query("DELETE FROM accounts WHERE name like 'Unit Test %' ");
274         $GLOBALS['db']->query("DELETE FROM sugarfavorites WHERE record_id = '{$account->id}'");
275         $GLOBALS['db']->query("DELETE FROM sugarfavorites WHERE record_id = '{$account2->id}'");
276
277         $this->assertTrue( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$account->id,'Accounts'), "Unable to find {$account->id} id in favorites search.");
278         $this->assertFalse( self::$helperObject->findBeanIdFromEntryList($results['entry_list'],$account2->id,'Accounts'), "Account {$account2->id} id in favorites search should not be there.");
279     }
280     /**
281      * Private helper function to mark a bean as a favorite item.
282      *
283      * @param string $session
284      * @param string $moduleName
285      * @param string $recordID
286      */
287     private function _markBeanAsFavorite($session, $moduleName, $recordID)
288     {
289         $result = $this->_makeRESTCall('set_entry',
290             array(
291                 'session' => $session,
292                 'module' => 'SugarFavorites',
293                 'name_value_list' => array(
294                     array('name' => 'record_id', 'value' => $recordID),
295                     array('name' => 'module', 'value' => $moduleName),
296                     ),
297                 )
298             );
299     }
300
301
302     public function testRelateAccountToTwoContacts()
303     {
304         $result = $this->_login();
305         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
306         $session = $result['id'];
307
308         $result = $this->_makeRESTCall('set_entry',
309             array(
310                 'session' => $session,
311                 'module' => 'Accounts',
312                 'name_value_list' => array(
313                     array('name' => 'name', 'value' => 'New Account'),
314                     array('name' => 'description', 'value' => 'This is an account created from a REST web services call'),
315                     ),
316                 )
317             );
318
319         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
320
321         $accountId = $result['id'];
322
323         $result = $this->_makeRESTCall('set_entry',
324             array(
325                 'session' => $session,
326                 'module' => 'Contacts',
327                 'name_value_list' => array(
328                     array('name' => 'last_name', 'value' => 'New Contact 1'),
329                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
330                     ),
331                 )
332             );
333
334         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
335
336         $contactId1 = $result['id'];
337
338         $result = $this->_makeRESTCall('set_entry',
339             array(
340                 'session' => $session,
341                 'module' => 'Contacts',
342                 'name_value_list' => array(
343                     array('name' => 'last_name', 'value' => 'New Contact 2'),
344                     array('name' => 'description', 'value' => 'This is a contact created from a REST web services call'),
345                     ),
346                 )
347             );
348
349         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
350
351         $contactId2 = $result['id'];
352
353         // now relate them together
354         $result = $this->_makeRESTCall('set_relationship',
355             array(
356                 'session' => $session,
357                 'module' => 'Accounts',
358                 'module_id' => $accountId,
359                 'link_field_name' => 'contacts',
360                 'related_ids' => array($contactId1,$contactId2),
361                 )
362             );
363
364         $this->assertEquals($result['created'],1,$this->_returnLastRawResponse());
365
366         // check the relationship
367         $result = $this->_makeRESTCall('get_relationships',
368             array(
369                 'session' => $session,
370                 'module' => 'Accounts',
371                 'module_id' => $accountId,
372                 'link_field_name' => 'contacts',
373                 'related_module_query' => '',
374                 'related_fields' => array('last_name','description'),
375                 'related_module_link_name_to_fields_array' => array(),
376                 'deleted' => false,
377                 )
378             );
379
380         $returnedValues = array();
381         $returnedValues[] = $result['entry_list'][0]['name_value_list']['last_name']['value'];
382         $returnedValues[] = $result['entry_list'][1]['name_value_list']['last_name']['value'];
383
384         $GLOBALS['db']->query("DELETE FROM accounts WHERE id= '{$accountId}'");
385         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId1}'");
386         $GLOBALS['db']->query("DELETE FROM contacts WHERE id= '{$contactId2}'");
387         $GLOBALS['db']->query("DELETE FROM accounts_contacts WHERE account_id= '{$accountId}'");
388
389         $this->assertContains('New Contact 1',$returnedValues,$this->_returnLastRawResponse());
390         $this->assertContains('New Contact 2',$returnedValues,$this->_returnLastRawResponse());
391     }
392
393     /**
394      * Test SQL injection bug in get_entries
395      */
396     public function testGetEntriesProspectFilter()
397     {
398         $result = $this->_login();
399         $this->assertTrue(!empty($result['id']) && $result['id'] != -1,$this->_returnLastRawResponse());
400         $session = $result['id'];
401
402         $result = $this->_makeRESTCall('get_entries',
403             array(
404                 'session' => $session,
405                 'module' => 'CampaignProspects',
406                 'ids' => array("' UNION SELECT id related_id, 'Users' related_type FROM users WHERE '1'='1")
407             )
408         );
409         $this->assertNull($result);
410
411     }
412
413 }