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