2e62373c9574772bf941c2ac963eb5cb3b12cf92
[tine20] / tests / tine20 / Tinebase / User / EmailUser / Imap / DovecotTest.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Tinebase
6  * @subpackage  User
7  * @license     http://www.gnu.org/licenses/agpl.html
8  * @copyright   Copyright (c) 2009-2016 Metaways Infosystems GmbH (http://www.metaways.de)
9  * @author      Philipp Schüle <p.schuele@metaways.de>
10  */
11
12 /**
13  * Test helper
14  */
15 require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
16
17 /**
18  * Test class for Tinebase_DovecotTest
19  */
20 class Tinebase_User_EmailUser_Imap_DovecotTest extends PHPUnit_Framework_TestCase
21 {
22     /**
23      * email user backend
24      *
25      * @var Tinebase_User_Plugin_Abstract
26      */
27     protected $_backend = NULL;
28     
29     /**
30      * @var array test objects
31      */
32     protected $_objects = array();
33     
34     /**
35      * @var array config
36      */
37     protected $_config;
38     
39     /**
40      * Sets up the fixture.
41      * This method is called before a test is executed.
42      *
43      * @access protected
44      */
45     protected function setUp()
46     {
47         $this->_config = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray();
48         if (!isset($this->_config['backend']) || !('Imap_' . ucfirst($this->_config['backend']) == Tinebase_EmailUser::IMAP_DOVECOT) || $this->_config['active'] != true) {
49             $this->markTestSkipped('Dovecot MySQL backend not configured or not enabled');
50         }
51
52         if (Tinebase_User::getConfiguredBackend() === Tinebase_User::ACTIVEDIRECTORY) {
53             // error: Zend_Ldap_Exception: 0x44 (Already exists; 00002071: samldb: Account name (sAMAccountName)
54             // 'tine20phpunituser' already in use!): adding: cn=PHPUnit User Tine 2.0,cn=Users,dc=example,dc=org
55             $this->markTestSkipped('skipped for ad backends as it does not allow duplicate CNs');
56         }
57
58         $this->_backend = Tinebase_EmailUser::getInstance(Tinebase_Config::IMAP);
59         
60         $personas = Zend_Registry::get('personas');
61         $this->_objects['user'] = clone $personas['jsmith'];
62         //$this->_objects['user']->setId(Tinebase_Record_Abstract::generateUID());
63
64         $this->_objects['addedUsers'] = array();
65         $this->_objects['fullUsers'] = array();
66     }
67
68     /**
69      * Tears down the fixture
70      * This method is called after a test is executed.
71      *
72      * @access protected
73      */
74     protected function tearDown()
75     {
76         // delete email account
77         foreach ($this->_objects['addedUsers'] as $user) {
78             $this->_backend->inspectDeleteUser($user);
79         }
80         
81         foreach ($this->_objects['fullUsers'] as $user) {
82             Tinebase_User::getInstance()->deleteUser($user);
83         }
84     }
85     
86     /**
87      * try to add an email account
88      */
89     public function testAddEmailAccount()
90     {
91         $emailUser = clone $this->_objects['user'];
92         $emailUser->imapUser = new Tinebase_Model_EmailUser(array(
93             'emailPassword' => Tinebase_Record_Abstract::generateUID(),
94             'emailUID'      => '1000',
95             'emailGID'      => '1000'
96         ));
97         
98         $this->_backend->inspectAddUser($this->_objects['user'], $emailUser);
99         $this->_objects['addedUsers']['emailUser'] = $this->_objects['user'];
100
101         $this->_assertImapUser();
102         return $this->_objects['user'];
103     }
104     
105     /**
106      * try to update an email account
107      */
108     public function testUpdateAccount()
109     {
110         // add smtp user
111         $user = $this->testAddEmailAccount();
112         
113         // update user
114         $user->imapUser->emailMailQuota = 600;
115         
116         $this->_backend->inspectUpdateUser($this->_objects['user'], $user);
117         $this->_assertImapUser(array('emailMailQuota'   => '600'));
118     }
119
120     /**
121      * asserts that imapUser object contains the correct data
122      *
123      * @param array $additionalExpectations
124      */
125     protected function _assertImapUser($additionalExpectations = array())
126     {
127         $this->assertEquals(array_merge(array(
128             'emailUserId'      => $this->_objects['user']->getId(),
129             'emailUsername'    => $this->_objects['user']->imapUser->emailUsername,
130             'emailMailQuota'   => null,
131             'emailUID'         => !empty($this->_config['dovecot']['uid']) ? $this->_config['dovecot']['uid'] : '1000',
132             'emailGID'         => !empty($this->_config['dovecot']['gid']) ? $this->_config['dovecot']['gid'] : '1000',
133             'emailLastLogin'   => null,
134             'emailMailSize'    => 0,
135             'emailSieveSize'   => null,
136             'emailPort'        => $this->_config['port'],
137             'emailSecure'      => $this->_config['ssl'],
138             'emailHost'        => $this->_config['host']
139         ), $additionalExpectations), $this->_objects['user']->imapUser->toArray());
140     }
141     
142     /**
143      * testSavingDuplicateAccount
144      * 
145      * @see 0006546: saving user with duplicate imap/smtp user entry fails
146      */
147     public function testSavingDuplicateAccount()
148     {
149         $user = $this->_addUser();
150         $userId = $user->getId();
151         
152         // delete user in tine accounts table
153         $userBackend = new Tinebase_User_Sql();
154         $userBackend->deleteUserInSqlBackend($userId);
155         
156         // create user again
157         unset($user->accountId);
158         $newUser = Tinebase_User::getInstance()->addUser($user);
159         $this->_objects['fullUsers'] = array($newUser);
160         
161         $this->assertNotEquals($userId, $newUser->getId());
162         $this->assertTrue(isset($newUser->imapUser), 'imapUser data not found: ' . print_r($newUser->toArray(), TRUE));
163     }
164     
165     /**
166      * add user with email data
167      * 
168      * @param string $username
169      * @return Tinebase_Model_FullUser
170      */
171     protected function _addUser($username = NULL)
172     {
173         $user = TestCase::getTestUser();
174         if ($username) {
175             $user->accountLoginName = $username;
176         }
177         $user->imapUser = new Tinebase_Model_EmailUser(array(
178             'emailPassword' => Tinebase_Record_Abstract::generateUID(),
179             'emailUID'      => '1000',
180             'emailGID'      => '1000'
181         ));
182         $user = Tinebase_User::getInstance()->addUser($user);
183         $this->_objects['fullUsers'] = array($user);
184         
185         return $user;
186     }
187     
188     /**
189      * try to set password
190      */
191     public function testSetPassword()
192     {
193         $user = $this->testAddEmailAccount();
194         
195         $newPassword = Tinebase_Record_Abstract::generateUID();
196         $this->_backend->inspectSetPassword($this->_objects['user']->getId(), $newPassword);
197         
198         // fetch email pw from db
199         $queryResult = $this->_fetchUserFromDovecotUsersTable($user->getId());
200         $hashPw = new Hash_Password();
201         $this->assertTrue($hashPw->validate($queryResult[0]['password'], $newPassword), 'password mismatch');
202     }
203     
204     /**
205      * fetch dovecot user data
206      *
207      * @param string $userId
208      * @return array
209      */
210     protected function _fetchUserFromDovecotUsersTable($userId)
211     {
212         $db = $this->_backend->getDb();
213         $select = $db->select()
214             ->from(array('dovecot_users'))
215             ->where($db->quoteIdentifier('userid') . ' = ?', $userId);
216         $stmt = $db->query($select);
217         $queryResult = $stmt->fetchAll();
218         $stmt->closeCursor();
219         
220         $this->assertTrue(! empty($queryResult), 'user not found in dovecot users table');
221         $this->assertEquals(1, count($queryResult));
222         
223         return $queryResult;
224     }
225     
226     /**
227      * testDuplicateUserId
228      * 
229      * @see 0007218: Duplicate userid in dovecot_users
230      */
231     public function testDuplicateUserId()
232     {
233         $emailDomain = TestServer::getPrimaryMailDomain();
234         $user = $this->_addUser('testuser@' . $emailDomain);
235         
236         // update user loginname
237         $user->accountLoginName = 'testuser';
238         $user = Tinebase_User::getInstance()->updateUser($user);
239         
240         $queryResult = $this->_fetchUserFromDovecotUsersTable($user->getId());
241         $this->assertEquals('testuser@' . $emailDomain, $queryResult[0]['username'], 'username has not been updated in dovecot user table');
242     }
243 }