Merge branch '2014.11-develop' into 2015.11
[tine20] / tests / tine20 / Admin / JsonTest.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Admin
6  * @license     http://www.gnu.org/licenses/agpl.html
7  * @copyright   Copyright (c) 2008-2014 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Philipp Schüle <p.schuele@metaways.de>
9  */
10
11 /**
12  * Test class for Tinebase_Admin json frontend
13  */
14 class Admin_JsonTest extends TestCase
15 {
16     /**
17      * Backend
18      *
19      * @var Admin_Frontend_Json
20      */
21     protected $_json;
22     
23     /**
24      * @var array test objects
25      */
26     protected $objects = array();
27
28     /**
29      * Sets up the fixture.
30      * This method is called before a test is executed.
31      *
32      * @access protected
33      */
34     protected function setUp()
35     {
36         parent::setUp();
37         
38         $this->_json = new Admin_Frontend_Json();
39         
40         $this->objects['initialGroup'] = new Tinebase_Model_Group(array(
41             'name'          => 'tine20phpunit',
42             'description'   => 'initial group'
43         ));
44         
45         $this->objects['updatedGroup'] = new Tinebase_Model_Group(array(
46             'name'          => 'tine20phpunit',
47             'description'   => 'updated group'
48         ));
49         
50         $this->objects['user'] = new Tinebase_Model_FullUser(array(
51             'accountLoginName'      => 'tine20phpunit',
52             'accountDisplayName'    => 'tine20phpunit',
53             'accountStatus'         => 'enabled',
54             'accountExpires'        => NULL,
55             'accountPrimaryGroup'   => Tinebase_Group::getInstance()->getGroupByName('Users')->getId(),
56             'accountLastName'       => 'Tine 2.0',
57             'accountFirstName'      => 'PHPUnit',
58             'accountEmailAddress'   => 'phpunit@' . $this->_getMailDomain()
59         ));
60         
61         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
62             $internalAddressbook = Tinebase_Container::getInstance()->getContainerByName('Addressbook', 'Internal Contacts', Tinebase_Model_Container::TYPE_SHARED);
63
64             $this->objects['initialGroup']->container_id = $internalAddressbook->getId();
65             $this->objects['updatedGroup']->container_id = $internalAddressbook->getId();
66             $this->objects['user']->container_id = $internalAddressbook->getId();
67         }
68
69         $this->objects['application'] = Tinebase_Application::getInstance()->getApplicationByName('Crm');
70        
71         $this->objects['role'] = new Tinebase_Model_Role(array(
72             'name'                  => 'phpunit test role',
73             'description'           => 'phpunit test role',
74         ));
75     }
76     
77     protected function tearDown()
78     {
79         parent::tearDown();
80         Tinebase_Config::getInstance()->set(Tinebase_Config::ANYONE_ACCOUNT_DISABLED, false);
81     }
82     
83     /**
84      * try to save group data
85      * 
86      * @return array
87      */
88     public function testAddGroup()
89     {
90         $result = $this->_json->saveGroup($this->objects['initialGroup']->toArray(), array());
91         $this->_groupIdsToDelete[] = $result['id'];
92         
93         $this->assertEquals($this->objects['initialGroup']->description, $result['description']);
94         
95         return $result;
96     }
97     
98     /**
99      * try to save an account
100      * 
101      * @return array
102      */
103     public function testSaveAccount()
104     {
105         $this->testAddGroup();
106         
107         $accountData = $this->objects['user']->toArray();
108         $accountData['accountPrimaryGroup'] = Tinebase_Group::getInstance()->getGroupByName('tine20phpunit')->getId();
109         $accountData['accountPassword'] = 'test';
110         $accountData['accountPassword2'] = 'test';
111         $accountData['accountFirstName'] = 'PHPUnitup';
112         
113         $account = $this->_createUser($accountData);
114         
115         $this->assertTrue(is_array($account));
116         $this->assertEquals('PHPUnitup', $account['accountFirstName']);
117         $this->assertEquals(Tinebase_Group::getInstance()->getGroupByName('tine20phpunit')->getId(), $account['accountPrimaryGroup']['id']);
118         $this->assertTrue(! empty($account['accountId']), 'no account id');
119         // check password
120         $authResult = Tinebase_Auth::getInstance()->authenticate($account['accountLoginName'], 'test');
121         $this->assertTrue($authResult->isValid());
122         
123         $account['accountPrimaryGroup'] = $accountData['accountPrimaryGroup'];
124         return $account;
125     }
126     
127     /**
128      * create user account
129      * 
130      * @param array $data
131      * @return array
132      */
133     protected function _createUser($data = null)
134     {
135         if ($data === null) {
136             $data = $this->objects['user']->toArray();
137         }
138         $this->_usernamesToDelete[] = $data['accountLoginName'];
139         $user = $this->_json->saveUser($data);
140
141         return $user;
142     }
143     
144     /**
145      * try to get all accounts
146      */
147     public function testGetAccounts()
148     {
149         $this->testSaveAccount();
150         
151         $accounts = $this->_json->getUsers('tine20phpunit', 'accountDisplayName', 'ASC', 0, 10);
152         
153         $this->assertGreaterThan(0, $accounts['totalcount']);
154     }
155     
156     /**
157      * testGetUserCount
158      * 
159      * @see 0006544: fix paging in admin/users grid
160      */
161     public function testGetUserCount()
162     {
163         $this->testSetAccountState();
164         $accounts = $this->_json->getUsers('tine20phpunit', 'accountDisplayName', 'ASC', 0, 100);
165         $this->assertEquals(count($accounts['results']), $accounts['totalcount'], print_r($accounts['results'], TRUE));
166     }
167     
168     /**
169      * get account that doesn't exist (by id)
170      */
171     public function testGetNonExistentAccountById()
172     {
173         Tinebase_Translation::getTranslation('Tinebase');
174         $id = 12334567;
175         
176         $this->setExpectedException('Tinebase_Exception_NotFound');
177         Tinebase_User::getInstance()->getUserById($id);
178     }
179
180     /**
181      * get account that doesn't exist (by login name)
182      */
183     public function testGetNonExistentAccountByLoginName()
184     {
185         $translate = Tinebase_Translation::getTranslation('Tinebase');
186         $loginName = 'something';
187         
188         $this->setExpectedException('Tinebase_Exception_NotFound');
189         $user = Tinebase_User::getInstance()->getUserByLoginName($loginName);
190     }
191     
192     /**
193      * try to create an account with existing login name 
194      * 
195      * @return array
196      * 
197      * @see 0006770: check if username already exists when creating new user / changing username
198      */
199     public function testSaveAccountWithExistingName()
200     {
201         $accountData = $this->testSaveAccount();
202         unset($accountData['accountId']);
203         
204         try {
205             $account = $this->_json->saveUser($accountData);
206             $this->fail('Creating an account with existing login name should throw exception: ' . print_r($account, TRUE));
207         } catch (Tinebase_Exception_SystemGeneric $tesg) {
208         }
209         
210         $this->assertEquals('Login name already exists. Please choose another one.', $tesg->getMessage());
211         
212         $accountData = $this->objects['user']->toArray();
213         $accountData['accountId'] = $this->objects['user']->getId();
214         $accountData['accountLoginName'] = Tinebase_Core::getUser()->accountLoginName;
215         
216         try {
217             $account = $this->_json->saveUser($accountData);
218             $this->fail('Updating an account with existing login name should throw exception: ' . print_r($account, TRUE));
219         } catch (Tinebase_Exception_SystemGeneric $tesg) {
220         }
221         
222         $this->assertEquals('Login name already exists. Please choose another one.', $tesg->getMessage());
223     }
224     
225     /**
226      * try to save a hidden account
227      */
228     public function testSaveHiddenAccount()
229     {
230         $accountData = $this->objects['user']->toArray();
231         $accountData['visibility'] = Tinebase_Model_User::VISIBILITY_HIDDEN;
232         $accountData['container_id'] = 0;
233         
234         $account = $this->_createUser($accountData);
235         
236         $this->assertTrue(is_array($account));
237         $this->assertTrue(! empty($account['contact_id']));
238         $appConfigDefaults = Admin_Controller::getInstance()->getConfigSettings();
239         $this->assertEquals($appConfigDefaults[Admin_Model_Config::DEFAULTINTERNALADDRESSBOOK], $account['container_id']['id']);
240     }    
241     
242     /**
243      * testUpdateUserWithoutContainerACL
244      * 
245      * @see 0006254: edit/create user is not possible
246      */
247     public function testUpdateUserWithoutContainerACL()
248     {
249         $account = $this->testSaveAccount();
250         $internalContainer = Tinebase_Container::getInstance()->get($account['container_id']['id']);
251         Tinebase_Container::getInstance()->setGrants($internalContainer, new Tinebase_Record_RecordSet('Tinebase_Model_Grants'), TRUE, FALSE);
252         
253         $account['groups'] = array($account['accountPrimaryGroup'], Tinebase_Group::getInstance()->getDefaultAdminGroup()->getId());
254         $account['container_id'] = $internalContainer->getId();
255         $account = $this->_json->saveUser($account);
256         
257         $this->assertEquals(2, $account['groups']['totalcount']);
258     }
259     
260     /**
261      * testUpdateUserRemoveGroup
262      * 
263      * @see 0006762: user still in admin role when admin group is removed
264      */
265     public function testUpdateUserRemoveGroup()
266     {
267         $account = $this->testSaveAccount();
268         $internalContainer = Tinebase_Container::getInstance()->get($account['container_id']['id']);
269         Tinebase_Container::getInstance()->setGrants($internalContainer, new Tinebase_Record_RecordSet('Tinebase_Model_Grants'), TRUE, FALSE);
270         
271         $adminGroupId = Tinebase_Group::getInstance()->getDefaultAdminGroup()->getId();
272         $account['groups'] = array($account['accountPrimaryGroup'], $adminGroupId);
273         $account['container_id'] = $account['container_id']['id'];
274         $account = $this->_json->saveUser($account);
275         
276         $roles = Tinebase_Acl_Roles::getInstance()->getRoleMemberships($account['accountId']);
277         $adminRole = Tinebase_Acl_Roles::getInstance()->getRoleByName('admin role');
278         $this->assertEquals(array($adminRole->getId()), $roles);
279         
280         $account['accountPrimaryGroup'] = $account['accountPrimaryGroup']['id'];
281         $account['groups'] = array($account['accountPrimaryGroup']);
282         
283         if (is_array($account['container_id']) && is_array($account['container_id']['id'])) {
284             $account['container_id'] = $account['container_id']['id'];
285         }
286         
287         $account = $this->_json->saveUser($account);
288         
289         $roles = Tinebase_Acl_Roles::getInstance()->getRoleMemberships($account['accountId']);
290         $this->assertEquals(array(), $roles);
291         $this->assertTrue(isset($account['last_modified_by']), 'modlog fields missing from account: ' . print_r($account, true));
292         $this->assertEquals(Tinebase_Core::getUser()->accountId, $account['last_modified_by']);
293     }
294
295     /**
296      * testUpdateUserRemovedPrimaryGroup
297      * 
298      * @see 0006710: save user fails if primary group no longer exists
299      */
300     public function testUpdateUserRemovedPrimaryGroup()
301     {
302         $this->testAddGroup();
303         
304         $accountData = $this->objects['user']->toArray();
305         $accountData['accountPrimaryGroup'] = Tinebase_Group::getInstance()->getGroupByName('tine20phpunit')->getId();
306         
307         Admin_Controller_Group::getInstance()->delete(array($accountData['accountPrimaryGroup']));
308         
309         $savedAccount = $this->_createUser($accountData);
310         
311         $this->assertEquals(Tinebase_Group::getInstance()->getDefaultGroup()->getId(), $savedAccount['accountPrimaryGroup']['id']);
312     }
313     
314     /**
315      * try to delete accounts 
316      */
317     public function testDeleteAccounts()
318     {
319         Admin_Controller_User::getInstance()->delete($this->objects['user']->accountId);
320         
321         $this->setExpectedException('Tinebase_Exception_NotFound');
322         Tinebase_User::getInstance()->getUserById($this->objects['user']->getId());
323     }
324
325     /**
326      * try to set account state
327      */
328     public function testSetAccountState()
329     {
330         $userArray = $this->testSaveAccount();
331         
332         $this->_json->setAccountState(array($userArray['accountId']), 'disabled');
333         
334         $account = Tinebase_User::getInstance()->getFullUserById($userArray['accountId']);
335         
336         $this->assertEquals('disabled', $account->accountStatus);
337     }
338
339     /**
340      * test send deactivation notification
341      * 
342      * @see 0009956: send mail on account deactivation
343      */
344     public function testAccountDeactivationNotification()
345     {
346         $smtpConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::SMTP);
347         if (! isset($smtpConfig->from) && ! isset($smtpConfig->primarydomain)) {
348             $this->markTestSkipped('no notification service address configured.');
349         }
350         
351         Tinebase_Config::getInstance()->set(Tinebase_Config::ACCOUNT_DEACTIVATION_NOTIFICATION, true);
352         
353         $userArray = $this->testSaveAccount();
354         
355         self::flushMailer();
356         
357         $this->_json->setAccountState(array($userArray['accountId']), 'disabled');
358         
359         $messages = self::getMessages();
360         
361         $this->assertEquals(1, count($messages), 'did not get notification message');
362         
363         $message = $messages[0];
364         $bodyText = $message->getBodyText(/* textOnly = */ true);
365         
366         $translate = Tinebase_Translation::getTranslation('Tinebase');
367         $this->assertEquals($translate->_('Your Tine 2.0 account has been deactivated'), $message->getSubject());
368         // @todo make this work. currently it does not work in de translation as the user name is cropped (tine20phpuni=)
369         //$this->assertContains($userArray['accountLoginName'], $bodyText);
370         $this->assertContains(Tinebase_Core::getHostname(), $bodyText);
371     }
372     
373     /**
374      * try to reset password
375      */
376     public function testResetPassword()
377     {
378         $userArray = $this->testSaveAccount();
379         
380         $this->_json->resetPassword($userArray, 'password', false);
381         
382         $authResult = Tinebase_Auth::getInstance()->authenticate($this->objects['user']->accountLoginName, 'password');
383         $this->assertTrue($authResult->isValid());
384     }
385     
386     /**
387      * testAccountContactModlog
388      * 
389      * @see 0006688: contact of new user should have modlog information
390      */
391     public function testAccountContactModlog()
392     {
393         $user = $this->_createUser(array(
394             'accountLoginName'      => 'tine20phpunit',
395             'accountDisplayName'    => 'tine20phpunit',
396             'accountStatus'         => 'enabled',
397             'accountExpires'        => NULL,
398             'accountPrimaryGroup'   => Tinebase_Group::getInstance()->getGroupByName('Users')->getId(),
399             'accountLastName'       => 'Tine 2.0',
400             'accountFirstName'      => 'PHPUnit',
401             'accountEmailAddress'   => 'phpunit@' . $this->_getMailDomain()
402         ));
403         
404         $contact = Addressbook_Controller_Contact::getInstance()->getContactByUserId($user['accountId']);
405         
406         $this->assertTrue(! empty($contact->creation_time));
407         $this->assertEquals(Tinebase_Core::getUser()->getId(), $contact->created_by);
408     }
409     
410     /**
411      * try to get all groups
412      *
413      */
414     public function testGetGroups()
415     {
416         $groups = $this->_json->getGroups(NULL, 'id', 'ASC', 0, 10);
417         
418         $this->assertGreaterThan(0, $groups['totalcount']);
419     }
420
421     /**
422      * try to update group data
423      */
424     public function testUpdateGroup()
425     {
426         $this->testAddGroup();
427         $group = Tinebase_Group::getInstance()->getGroupByName($this->objects['initialGroup']->name);
428         
429         // set data array
430         $data = $this->objects['updatedGroup']->toArray();
431         $data['id'] = $group->getId();
432         
433         // add group members array
434         $userArray = $this->_createUser();
435         $groupMembers = array($userArray['accountId']);
436         
437         $result = $this->_json->saveGroup($data, $groupMembers);
438
439         $this->assertGreaterThan(0,sizeof($result['groupMembers']));
440         $this->assertEquals($this->objects['updatedGroup']->description, $result['description']);
441         $this->assertEquals(Tinebase_Core::getUser()->accountId, $result['last_modified_by'], 'last_modified_by not matching');
442     }
443
444     /**
445      * try to get group members
446      */
447     public function testGetGroupMembers()
448     {
449         $this->testAddGroup();
450         $group = Tinebase_Group::getInstance()->getGroupByName($this->objects['updatedGroup']->name);
451         
452         // set group members
453         $userArray = $this->_createUser();
454         Tinebase_Group::getInstance()->setGroupMembers($group->getId(), array($userArray['accountId']));
455         
456         // get group members with json
457         $getGroupMembersArray = $this->_json->getGroupMembers($group->getId());
458         
459         $contact = Addressbook_Controller_Contact::getInstance()->getContactByUserId($userArray['accountId']);
460         
461         $this->assertTrue(isset($getGroupMembersArray['results'][0]));
462         $this->assertEquals($contact->n_fileas, $getGroupMembersArray['results'][0]['name']);
463         $this->assertGreaterThan(0, $getGroupMembersArray['totalcount']);
464     }
465     
466     /**
467      * try to delete group
468      *
469      */
470     public function testDeleteGroup()
471     {
472         $this->testAddGroup();
473         // delete group with json.php function
474         $group = Tinebase_Group::getInstance()->getGroupByName($this->objects['initialGroup']->name);
475         $result = $this->_json->deleteGroups(array($group->getId()));
476         
477         $this->assertTrue($result['success']);
478         
479         // try to get deleted group
480         $this->setExpectedException('Tinebase_Exception_Record_NotDefined');
481         
482         // get group by name
483         $group = Tinebase_Group::getInstance()->getGroupByName($this->objects['initialGroup']->name);
484     }
485     
486     /**
487      * try to get all access log entries
488      */
489     public function testGetAccessLogs()
490     {
491         $this->_addAccessLog($this->objects['user'], 'Unittest');
492         $accessLogs = $this->_json->searchAccessLogs($this->_getAccessLogFilter(), array());
493       
494         // check total count
495         $this->assertGreaterThan(0, sizeof($accessLogs['results']));
496         $this->assertGreaterThan(0, $accessLogs['totalcount']);
497     }
498     
499     /**
500      * add access log entry
501      * 
502      * @param Tinebase_Model_FullUser $_user
503      * @param String $_clienttype
504      */
505     protected function _addAccessLog($_user, $_clienttype)
506     {
507         Tinebase_AccessLog::getInstance()->create(new Tinebase_Model_AccessLog(array(
508             'sessionid'     => 'test_session_id',
509             'login_name'    => $_user->accountLoginName,
510             'ip'            => '127.0.0.1',
511             'li'            => Tinebase_DateTime::now()->get(Tinebase_Record_Abstract::ISO8601LONG),
512             'result'        => Zend_Auth_Result::SUCCESS,
513             'account_id'    => $_user->getId(),
514             'clienttype'    => $_clienttype,
515         )));
516     }
517     
518     /**
519      * get access log filter helper
520      * 
521      * @param string $_loginname
522      * @param string $_clienttype
523      * @return array
524      */
525     protected function _getAccessLogFilter($_loginname = NULL, $_clienttype = NULL)
526     {
527         $result = array(
528             array(
529                 'field' => 'li', 
530                 'operator' => 'within', 
531                 'value' => 'dayThis'
532             ),
533         );
534         
535         if ($_loginname !== NULL) {
536             $result[] = array(
537                 'field' => 'query', 
538                 'operator' => 'contains', 
539                 'value' => $_loginname
540             );
541         }
542
543         if ($_clienttype !== NULL) {
544             $result[] = array(
545                 'field' => 'clienttype', 
546                 'operator' => 'equals', 
547                 'value' => $_clienttype
548             );
549         }
550         
551         return $result;
552     }
553     
554     /**
555      * try to get all access log entries
556      */
557     public function testGetAccessLogsWithDeletedUser()
558     {
559         $clienttype = 'Unittest';
560         $user = $this->testSaveAccount();
561         $this->_addAccessLog(new Tinebase_Model_FullUser($user), $clienttype);
562         
563         Admin_Controller_User::getInstance()->delete($user['accountId']);
564         $accessLogs = $this->_json->searchAccessLogs($this->_getAccessLogFilter($user['accountLoginName'], $clienttype), array());
565
566         $this->assertGreaterThan(0, sizeof($accessLogs['results']));
567         $this->assertGreaterThan(0, $accessLogs['totalcount']);
568         $testLogEntry = $accessLogs['results'][0];
569         $this->assertEquals(Tinebase_User::getInstance()->getNonExistentUser()->accountDisplayName, $testLogEntry['account_id']['accountDisplayName']);
570         $this->assertEquals($clienttype, $testLogEntry['clienttype']);
571         
572         $this->_json->deleteAccessLogs(array($testLogEntry['id']));
573     }
574     
575     /**
576      * try to delete access log entries
577      */
578     public function testDeleteAccessLogs()
579     {
580         $accessLogs = $this->_json->searchAccessLogs($this->_getAccessLogFilter('tine20admin'), array());
581         
582         $deleteLogIds = array();
583         foreach ($accessLogs['results'] as $log) {
584             $deleteLogIds[] = $log['id'];
585         }
586         
587         // delete logs
588         if (!empty($deleteLogIds)) {
589             $this->_json->deleteAccessLogs($deleteLogIds);
590         }
591         
592         $accessLogs = $this->_json->searchAccessLogs($this->_getAccessLogFilter('tine20admin'), array());
593         $this->assertEquals(0, sizeof($accessLogs['results']), 'results not matched');
594         $this->assertEquals(0, $accessLogs['totalcount'], 'totalcount not matched');
595     }
596     
597     /**
598      * try to get an application
599      */
600     public function testGetApplication()
601     {
602         $application = $this->_json->getApplication($this->objects['application']->getId());
603         
604         $this->assertEquals($application['status'], $this->objects['application']->status);
605         
606     }
607
608     /**
609      * try to get applications
610      */
611     public function testGetApplications()
612     {
613         $applications = $this->_json->getApplications(NULL, NULL, 'ASC', 0, 10);
614         
615         $this->assertGreaterThan(0, $applications['totalcount']);
616     }
617
618     /**
619      * try to set application state
620      */
621     public function testSetApplicationState()
622     {
623         $this->_json->setApplicationState(array($this->objects['application']->getId()), 'disabled');
624         
625         $application = $this->_json->getApplication($this->objects['application']->getId());
626
627         $this->assertEquals($application['status'], 'disabled');
628
629         // enable again
630         $this->_json->setApplicationState(array($this->objects['application']->getId()), 'enabled');
631     }
632
633     /**
634      * try to add role and set members/rights
635      */
636     public function testAddRole()
637     {
638         // account to add as role member
639         $user = $this->testSaveAccount();
640         $account = Tinebase_User::getInstance()->getUserById($user['accountId']);
641         
642         $roleData = $this->objects['role']->toArray();
643         $roleMembers = array(
644             array(
645                 "id"    => $account->getId(),
646                 "type"  => "user",
647                 "name"  => $account->accountDisplayName,
648             )
649         );
650         $roleRights = array(
651             array(
652                 "application_id"    => $this->objects['application']->getId(),
653                 "right"  => Tinebase_Acl_Rights::RUN,
654             )
655         );
656         
657         $result = $this->_json->saveRole($roleData, $roleMembers, $roleRights);
658         
659         // get role id from result
660         $roleId = $result['id'];
661         
662         $role = Tinebase_Acl_Roles::getInstance()->getRoleByName($this->objects['role']->name);
663         
664         $this->assertEquals($role->getId(), $roleId);
665         // check role members
666         $result = $this->_json->getRoleMembers($role->getId());
667         $this->assertGreaterThan(0, $result['totalcount']);
668     }
669
670     /**
671      * try to get role rights
672      *
673      */
674     public function testGetRoleRights()
675     {
676         $this->testAddRole();
677         $role = Tinebase_Acl_Roles::getInstance()->getRoleByName($this->objects['role']->name);
678         $rights = $this->_json->getRoleRights($role->getId());
679         
680         //print_r ($rights);
681         $this->assertGreaterThan(0, $rights['totalcount']);
682         $this->assertEquals(Tinebase_Acl_Rights::RUN, $rights['results'][0]['right']);
683     }
684     
685     /**
686      * try to save role
687      */
688     public function testUpdateRole()
689     {
690         $this->testAddRole();
691         $role = Tinebase_Acl_Roles::getInstance()->getRoleByName($this->objects['role']->name);
692         $role->description = "updated description";
693         $roleArray = $role->toArray();
694         
695         $result = $this->_json->saveRole($roleArray, array(),array());
696         
697         $this->assertEquals("updated description", $result['description']);
698     }
699
700     /**
701      * try to get roles
702      */
703     public function testGetRoles()
704     {
705         $roles = $this->_json->getRoles(NULL, NULL, 'ASC', 0, 10);
706         
707         $this->assertGreaterThan(0, $roles['totalcount']);
708     }
709     
710     /**
711      * try to delete roles
712      */
713     public function testDeleteRoles()
714     {
715         $this->testAddRole();
716         $role = Tinebase_Acl_Roles::getInstance()->getRoleByName($this->objects['role']->name);
717         
718         $result = $this->_json->deleteRoles(array($role->getId()));
719         
720         $this->assertTrue($result['success']);
721         
722         // try to get it, shouldn't be found
723         $this->setExpectedException('Tinebase_Exception_NotFound');
724         $role = Tinebase_Acl_Roles::getInstance()->getRoleByName($this->objects['role']->name);
725         
726     }    
727
728     /**
729      * try to get all role rights
730      */
731     public function testGetAllRoleRights()
732     {
733         $allRights = $this->_json->getAllRoleRights();
734         
735         $this->assertGreaterThan(0, $allRights);
736         $this->assertTrue(isset($allRights[0]['text']));
737         $this->assertTrue(isset($allRights[0]['application_id']));
738         $this->assertGreaterThan(0, $allRights[0]['children']);
739     }
740
741     /**
742     * try to get role rights for app
743     * 
744     * @see 0006374: if app has no own rights, tinebase rights are shown
745     */
746     public function testGetRoleRightsForActiveSyncAndTinebase()
747     {
748         $allRights = $this->_json->getAllRoleRights();
749         
750         $appRightsFound = NULL;
751         $tinebaseRights = NULL;
752         foreach ($allRights as $appRights) {
753             if ($appRights['text'] === 'ActiveSync' || $appRights['text'] === 'Tinebase') {
754                 $appRightsFound[$appRights['text']] = array();
755                 foreach($appRights['children'] as $right) {
756                     $appRightsFound[$appRights['text']][] = $right['right'];
757                 }
758             }
759         }
760         
761         $this->assertTrue(! empty($appRightsFound));
762         
763         $expectedTinebaseRights = array(
764             'report_bugs',
765             'check_version',
766             'manage_own_profile',
767             'manage_own_state'
768         );
769         
770         $tinebaseRightsFound = array_intersect($appRightsFound['ActiveSync'], $expectedTinebaseRights);
771         $this->assertEquals(0, count($tinebaseRightsFound), 'found Tinebase_Rights: ' . print_r($tinebaseRightsFound, TRUE));
772         $tinebaseRightsFound = array_intersect($appRightsFound['Tinebase'], $expectedTinebaseRights);
773         $this->assertEquals(4, count($tinebaseRightsFound), 'did not find Tinebase_Rights: ' . print_r($appRightsFound['Tinebase'], TRUE));
774     }
775     
776     /**
777      * testDeleteGroupBelongingToRole
778      * 
779      * @see 0007578: Deleting a group belonging to a role => can not use the role anymore !
780      */
781     public function testDeleteGroupBelongingToRole()
782     {
783         $group = $this->testAddGroup();
784         $roleData = $this->objects['role']->toArray();
785         $roleMembers = array(
786             array(
787                 "id"    => $group['id'],
788                 "type"  => "group",
789             )
790         );
791         
792         $result = $this->_json->saveRole($roleData, $roleMembers, array());
793         $this->_json->deleteGroups(array($group['id']));
794         
795         $role = $this->_json->getRole($result['id']);
796         
797         $this->assertEquals(0, $role['roleMembers']['totalcount'], 'role members should be empty: ' . print_r($role['roleMembers'], TRUE));
798     }
799     
800     /**
801      * try to save tag and update without rights
802      */
803     public function testSaveTagAndUpdateWithoutRights()
804     {
805         $tagData = $this->_getTagData();
806         $this->objects['tag'] = $this->_json->saveTag($tagData);
807         $this->assertEquals($tagData['name'], $this->objects['tag']['name']);
808         
809         $this->objects['tag']['rights'] = array();
810         $this->setExpectedException('Tinebase_Exception_InvalidArgument');
811         $this->objects['tag'] = $this->_json->saveTag($this->objects['tag']);
812     }
813
814     /**
815      * try to save tag without view right
816      */
817     public function testSaveTagWithoutViewRight()
818     {
819         $tagData = $this->_getTagData();
820         $tagData['rights'] = array(array(
821             'account_id' => 0,
822             'account_type' => 'anyone',
823             'account_name' => 'Anyone',
824             'view_right' => false,
825             'use_right' => false
826         ));
827         $this->setExpectedException('Tinebase_Exception_InvalidArgument');
828         $this->objects['tag'] = $this->_json->saveTag($tagData);
829     }
830     
831     /**
832      * get tag data
833      * 
834      * @return array
835      */
836     protected function _getTagData()
837     {
838         return array(
839             'rights' => array(
840                 array(
841                     'account_id' => 0,
842                     'account_type' => 'anyone',
843                     'account_name' => 'Anyone',
844                     'view_right' => true,
845                     'use_right' => true
846                 )
847             ),
848             'contexts' => array('any'),
849             'name' => 'supertag',
850             'description' => 'xxxx',
851             'color' => '#003300'
852         );
853     }
854     
855     /**
856      * testSaveTagWithoutAnyone
857      * 
858      * @see 0009934: can't save shared tag with anyoneAccountDisabled
859      */
860     public function testSaveTagWithoutAnyone()
861     {
862         Tinebase_Config::getInstance()->set(Tinebase_Config::ANYONE_ACCOUNT_DISABLED, true);
863         
864         $defaultUserGroup = Tinebase_Group::getInstance()->getDefaultGroup();
865         $tagData = $this->_getTagData();
866         $tagData['rights'] = array(array(
867             'account_id' => $defaultUserGroup->getId(),
868             'account_type' => Tinebase_Acl_Rights::ACCOUNT_TYPE_GROUP,
869             'view_right' => true,
870             'use_right' => true
871         ));
872         $this->objects['tag'] = $this->_json->saveTag($tagData);
873         
874         $this->assertEquals('supertag', $this->objects['tag']['name']);
875         $this->assertEquals(1, count($this->objects['tag']['rights']));
876     }
877     
878     /**
879      * test searchContainers
880      */
881     public function testSearchContainers()
882     {
883         $personalAdb = Addressbook_Controller_Contact::getInstance()->getDefaultAddressbook();
884         
885         $addressbook = Tinebase_Application::getInstance()->getApplicationByName('Addressbook');
886         $filter = array(
887             array('field' => 'application_id',  'operator' => 'equals',     'value' => $addressbook->getId()),
888             array('field' => 'type',            'operator' => 'equals',     'value' => Tinebase_Model_Container::TYPE_PERSONAL),
889             array('field' => 'name',            'operator' => 'contains',   'value' => Tinebase_Core::getUser()->accountFirstName),
890         );
891         
892         $result = $this->_json->searchContainers($filter, array());
893         
894         $this->assertGreaterThan(0, $result['totalcount']);
895         $this->assertEquals(3, count($result['filter']));
896         
897         $found = FALSE;
898         foreach ($result['results'] as $container) {
899             if ($container['id'] === $personalAdb->getId()) {
900                 $found = TRUE;
901             }
902         }
903         $this->assertTrue($found);
904     }
905
906     /**
907      * test saveUpdateDeleteContainer
908      */
909     public function testSaveUpdateDeleteContainer()
910     {
911         $container = $this->_saveContainer();
912         $this->assertEquals(Tinebase_Core::getUser()->getId(), $container['created_by']);
913         
914         // update container
915         $container['name'] = 'testcontainerupdated';
916         $container['account_grants'] = $this->_getContainerGrants();
917         
918         $containerUpdated = $this->_json->saveContainer($container);
919         $this->assertEquals('testcontainerupdated', $containerUpdated['name']);
920         $this->assertTrue($containerUpdated['account_grants'][0][Tinebase_Model_Grants::GRANT_ADMIN]);
921         
922         $deleteResult = $this->_json->deleteContainers(array($container['id']));
923         $this->assertEquals('success', $deleteResult['status']);
924     }
925     
926     /**
927      * try to change container app
928      */
929     public function testChangeContainerApp()
930     {
931         $container = $this->_saveContainer();
932         
933         $container['application_id'] = Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId();
934         $this->setExpectedException('Tinebase_Exception_Record_NotAllowed');
935         $containerUpdated = $this->_json->saveContainer($container);
936     }
937     
938     /**
939      * testContainerNotification
940      */
941     public function testContainerNotification()
942     {
943         // prepare smtp transport
944         $smtpConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::SMTP, new Tinebase_Config_Struct())->toArray();
945         if (empty($smtpConfig)) {
946              $this->markTestSkipped('No SMTP config found: this is needed to send notifications.');
947         }
948         $mailer = Tinebase_Smtp::getDefaultTransport();
949         // make sure all messages are sent if queue is activated
950         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
951             Tinebase_ActionQueue::getInstance()->processQueue(100);
952         }
953         $mailer->flush();
954         
955         // create and update container
956         $container = $this->_saveContainer();
957         $container['type'] = Tinebase_Model_Container::TYPE_PERSONAL;
958         $container['note'] = 'changed to personal';
959         $container['account_grants'] = $this->_getContainerGrants();
960         $containerUpdated = $this->_json->saveContainer($container);
961         
962         // make sure messages are sent if queue is activated
963         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
964             Tinebase_ActionQueue::getInstance()->processQueue();
965         }
966
967         // check notification message
968         $messages = $mailer->getMessages();
969         $this->assertGreaterThan(0, count($messages));
970         $notification = $messages[0];
971         
972         $translate = Tinebase_Translation::getTranslation('Admin');
973         $body = quoted_printable_decode($notification->getBodyText(TRUE));
974         $this->assertContains($container['note'],  $body, $body);
975         
976         $subject = $notification->getSubject();
977         if (strpos($subject, 'UTF-8') !== FALSE) {
978             $this->assertEquals(iconv_mime_encode('Subject', $translate->_('Your container has been changed'), array(
979                 'scheme'        => 'Q',
980                 'line-length'   => 500,
981             )), 'Subject: ' . $subject);
982         } else {
983             $this->assertEquals($translate->_('Your container has been changed'), $subject);
984         }
985         $this->assertTrue(in_array(Tinebase_Core::getUser()->accountEmailAddress, $notification->getRecipients()));
986     }
987     
988     /**
989      * testContainerCheckOwner
990      */
991     public function testContainerCheckOwner()
992     {
993         $container = $this->_saveContainer(Tinebase_Model_Container::TYPE_PERSONAL);
994         
995         $personas = Zend_Registry::get('personas');
996         $container['account_grants'] = $this->_getContainerGrants();
997         $container['account_grants'][] = array(
998             'account_id'     => $personas['jsmith']->getId(),
999             'account_type'   => 'user',
1000             Tinebase_Model_Grants::GRANT_ADMIN     => true
1001         );
1002         $this->setExpectedException('Tinebase_Exception_Record_NotAllowed');
1003         $containerUpdated = $this->_json->saveContainer($container);
1004     }
1005     
1006     /**
1007      * test create container
1008      */
1009     public function testCreateContainerAndDeleteContents()
1010     {
1011         $container = $this->_json->saveContainer(array(
1012             "type" => Tinebase_Model_Container::TYPE_SHARED,
1013             "backend" => "Sql",
1014             "name" => "asdfgsadfg",
1015             "color" => "#008080",
1016             "application_id" => Tinebase_Application::getInstance()->getApplicationByName('Addressbook')->getId(),
1017             "model" => "",
1018             "note" => ""
1019         ));
1020         // check if the model was set
1021         $this->assertEquals($container['model'], 'Addressbook_Model_Contact');
1022         $contact = new Addressbook_Model_Contact(array('n_given' => 'max', 'n_family' => 'musterman', 'container_id' => $container['id']));
1023         $contact = Addressbook_Controller_Contact::getInstance()->create($contact);
1024         
1025         $this->_json->deleteContainers(array($container['id']));
1026         
1027         $cb = new Addressbook_Backend_Sql();
1028         $del = $cb->get($contact->getId(), true);
1029         // record should be deleted
1030         $this->assertEquals($del->is_deleted, 1);
1031         
1032         try {
1033             Addressbook_Controller_Contact::getInstance()->get($contact->getId(), $container['id']);
1034             $this->fail('The expected exception was not thrown');
1035         } catch (Tinebase_Exception_NotFound $e) {
1036             // ok;
1037         }
1038         // record should not be found
1039         $this->assertEquals($e->getMessage(), 'Addressbook_Model_Contact record with id = ' . $contact->getId().' not found!');
1040         
1041         
1042     }
1043     
1044     /**
1045      * saves and returns container
1046      * 
1047      * @param string $_type
1048      * @return array
1049      */
1050     protected function _saveContainer($_type = Tinebase_Model_Container::TYPE_SHARED)
1051     {
1052         $data = array(
1053             'name'              => 'testcontainer',
1054             'type'              => $_type,
1055             'backend'           => 'Sql',
1056             'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Addressbook')->getId(),
1057         );
1058         
1059         $container = $this->_json->saveContainer($data);
1060         $this->objects['container'] = $container['id'];
1061         
1062         $this->assertEquals($data['name'], $container['name']);
1063         
1064         return $container;
1065     }
1066     
1067     /**
1068      * get container grants
1069      * 
1070      * @return array
1071      */
1072     protected function _getContainerGrants()
1073     {
1074         return array(array(
1075             'account_id'     => Tinebase_Core::getUser()->getId(),
1076             'account_type'   => 'user',
1077             Tinebase_Model_Grants::GRANT_READ      => true,
1078             Tinebase_Model_Grants::GRANT_ADD       => true,
1079             Tinebase_Model_Grants::GRANT_EDIT      => true,
1080             Tinebase_Model_Grants::GRANT_DELETE    => false,
1081             Tinebase_Model_Grants::GRANT_ADMIN     => true
1082         ));
1083     }
1084
1085     /**
1086      * testUpdateGroupMembershipAndContainerGrants
1087      * 
1088      * @see 0007150: container grants are not updated if group memberships change
1089      */
1090     public function testUpdateGroupMembershipAndContainerGrants()
1091     {
1092         $container = $this->_saveContainer();
1093         $adminGroup = Tinebase_Group::getInstance()->getDefaultAdminGroup();
1094         $container['account_grants'] = array(array(
1095             'account_id'     => $adminGroup->getId(),
1096             'account_type'   => 'group',
1097             Tinebase_Model_Grants::GRANT_READ      => true,
1098             Tinebase_Model_Grants::GRANT_ADD       => true,
1099             Tinebase_Model_Grants::GRANT_EDIT      => true,
1100             Tinebase_Model_Grants::GRANT_DELETE    => false,
1101             Tinebase_Model_Grants::GRANT_ADMIN     => true
1102         ));
1103         $containerUpdated = $this->_json->saveContainer($container);
1104         
1105         $userArray = $this->_createUser();
1106         Tinebase_Group::getInstance()->setGroupMembers($adminGroup->getId(), array($userArray['accountId']));
1107         
1108         $containers = Tinebase_Container::getInstance()->getContainerByACL($userArray['accountId'], 'Addressbook', Tinebase_Model_Grants::GRANT_ADD);
1109         $this->assertTrue(count($containers->filter('name', 'testcontainer')) === 1, 'testcontainer ' . print_r($containerUpdated, TRUE) . ' not found: ' . print_r($containers->toArray(), TRUE));
1110     }
1111     
1112     /**
1113      * testPhpinfo
1114      * 
1115      * @see 0007182: add "server info" section to admin
1116      */
1117     public function testPhpinfo()
1118     {
1119         $info = $this->_json->getServerInfo();
1120         $this->assertContains("phpinfo()", $info['html']);
1121         $this->assertContains("PHP Version =>", $info['html']);
1122     }
1123
1124     /**
1125      * Check for smtp domains in registry
1126      *
1127      * @see 0010305: Undefined value in user edit dialog
1128      */
1129     public function testRegistryForSMTP()
1130     {
1131         $smtpConfig = Tinebase_EmailUser::getConfig(Tinebase_Config::SMTP);
1132         $primaryDomainConfig = Tinebase_EmailUser::manages(Tinebase_Config::SMTP) && isset($smtpConfig['primarydomain'])
1133             ? $smtpConfig['primarydomain'] : '';
1134         $secondaryDomainConfig = Tinebase_EmailUser::manages(Tinebase_Config::SMTP) && isset($smtpConfig['secondarydomains'])
1135             ? $smtpConfig['secondarydomains'] : '';
1136
1137         $afj = new Admin_Frontend_Json();
1138         $registryData = $afj->getRegistryData();
1139
1140         $this->assertEquals($registryData['primarydomain'],  $primaryDomainConfig);
1141         $this->assertEquals($registryData['secondarydomains'], $secondaryDomainConfig);
1142     }
1143
1144 //    public function testGetConfig()
1145 //    {
1146 //        $afj = new Admin_Frontend_Json();
1147 //        $config = $afj->getConfig('Calendar');
1148 //
1149 //        $this->assertGreaterThanOrEqual(2, count($config));
1150 //        $this->assertArrayHasKey('attendeeRoles', $config);
1151 //        $this->assertArrayHasKey('records', $config['attendeeRoles']);
1152 //        $this->assertGreaterThanOrEqual(1, $config['attendeeRoles']['records']);
1153 //    }
1154 //
1155 //    public function testSetConfig()
1156 //    {
1157 //        $afj = new Admin_Frontend_Json();
1158 //        $config = $afj->getConfig('Calendar');
1159 //
1160 //        $attendeeRoles = $config['attendeeRoles'];
1161 //        $attendeeRoles['records'][] = array(
1162 //            'id'    => 'CHAIR',
1163 //            'value' => 'Chair'
1164 //        );
1165 //
1166 //        $afj->setConfig('Calendar', 'attendeeRoles', $attendeeRoles);
1167 //
1168 //        $updatedConfig = $afj->getConfig('Calendar');
1169 //        $this->assertEquals(count($attendeeRoles['records']), count($updatedConfig['attendeeRoles']['records']));
1170 //    }
1171
1172     public function testSearchConfigs()
1173     {
1174         $afj = new Admin_Frontend_Json();
1175
1176         $result = $afj->searchConfigs(array(
1177             'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId()
1178         ), array());
1179
1180         $this->assertGreaterThanOrEqual(2, $result['totalcount']);
1181
1182         $attendeeRoles = NULL;
1183         foreach($result['results'] as $configData) {
1184             if ($configData['name'] == 'attendeeRoles') {
1185                 $attendeeRoles = $configData;
1186                 break;
1187             }
1188         }
1189
1190         $this->assertNotNull($attendeeRoles);
1191         $this->assertContains('{', $attendeeRoles);
1192
1193         return $attendeeRoles;
1194     }
1195
1196     public function testGetConfig()
1197     {
1198         $attendeeRoles = $this->testUpdateConfig();
1199
1200         $afj = new Admin_Frontend_Json();
1201         $fetchedAttendeeRoles = $afj->getConfig($attendeeRoles['id']);
1202
1203         $this->assertEquals($attendeeRoles['value'], $fetchedAttendeeRoles['value']);
1204     }
1205
1206     public function testUpdateConfig()
1207     {
1208         $attendeeRoles = $this->testSearchConfigs();
1209
1210         $keyFieldConfig = json_decode($attendeeRoles['value'], true);
1211         $keyFieldConfig['records'][] = array(
1212             'id'    => 'CHAIR',
1213             'value' => 'Chair'
1214         );
1215         $attendeeRoles['value'] = json_encode($keyFieldConfig);
1216         $attendeeRoles['id'] = '';
1217
1218
1219         $afj = new Admin_Frontend_Json();
1220         $afj->saveConfig($attendeeRoles);
1221
1222         $updatedAttendeeRoles = $this->testSearchConfigs();
1223
1224         $this->assertEquals($attendeeRoles['value'], $updatedAttendeeRoles['value']);
1225         return $updatedAttendeeRoles;
1226     }
1227 }