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