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