0011192: LDAP sync should delete contacts
authorPhilipp Schüle <p.schuele@metaways.de>
Wed, 5 Aug 2015 16:05:27 +0000 (18:05 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 6 Aug 2015 08:37:40 +0000 (10:37 +0200)
* adds new option 'syncdeletedusers' to user sync
* adds a test

https://forge.tine20.org/view.php?id=11192

Change-Id: I4f39bdcdb914deac0832892a02d6c79a75dbf530
Reviewed-on: http://gerrit.tine20.com/customers/2093
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/TestCase.php
tests/tine20/Tinebase/User/LdapTest.php
tine20/Setup/Frontend/Cli.php
tine20/Setup/Server/Cli.php
tine20/Tinebase/User.php
tine20/Tinebase/User/Sql.php

index 86d516b..a20f38c 100644 (file)
@@ -106,8 +106,10 @@ abstract class TestCase extends PHPUnit_Framework_TestCase
         }
         
         Addressbook_Controller_Contact::getInstance()->setGeoDataForContacts(true);
-        
-        Tinebase_Core::set(Tinebase_Core::USER, $this->_originalTestUser);
+
+        if ($this->_originalTestUser instanceof Tinebase_Model_User) {
+            Tinebase_Core::set(Tinebase_Core::USER, $this->_originalTestUser);
+        }
         
         Tinebase_Cache_PerRequest::getInstance()->resetCache();
     }
@@ -155,12 +157,17 @@ abstract class TestCase extends PHPUnit_Framework_TestCase
      */
     protected function _deleteUsers()
     {
+
+
         foreach ($this->_usernamesToDelete as $username) {
             try {
+                if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
+                    . ' Trying to delete user: ' . $username);
+
                 Tinebase_User::getInstance()->deleteUser(Tinebase_User::getInstance()->getUserByLoginName($username));
             } catch (Exception $e) {
                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
-                    . ' error while deleting user: ' . $e->getMessage());
+                    . ' Error while deleting user: ' . $e->getMessage());
             }
         }
     }
index 28f1080..916de42 100644 (file)
@@ -17,7 +17,7 @@ require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHe
 /**
  * Test class for Tinebase_User_Ldap
  */
-class Tinebase_User_LdapTest extends PHPUnit_Framework_TestCase
+class Tinebase_User_LdapTest extends TestCase
 {
     /**
      * ldap group backend
@@ -27,11 +27,6 @@ class Tinebase_User_LdapTest extends PHPUnit_Framework_TestCase
     protected $_backend = NULL;
         
     /**
-     * @var array test objects
-     */
-    protected $objects = array();
-
-    /**
      * Sets up the fixture.
      * This method is called before a test is executed.
      *
@@ -43,21 +38,6 @@ class Tinebase_User_LdapTest extends PHPUnit_Framework_TestCase
             $this->markTestSkipped('LDAP backend not enabled');
         }
         $this->_backend = Tinebase_User::factory(Tinebase_User::LDAP);
-        
-        $this->objects['users'] = array();
-    }
-    
-    /**
-     * Tears down the fixture
-     * This method is called after a test is executed.
-     *
-     * @access protected
-     */
-    protected function tearDown()
-    {
-        foreach ($this->objects['users'] as $user) {
-            $this->_backend->deleteUser($user);
-        }
     }
     
     /**
@@ -68,10 +48,10 @@ class Tinebase_User_LdapTest extends PHPUnit_Framework_TestCase
     public function testAddUser()
     {
         $user = $this->getTestRecord();
-        
+
+        $this->_usernamesToDelete[] = $user->accountLoginName;
         $testUser = $this->_backend->addUser($user);
-        $this->objects['users']['testUser'] = $testUser;
-        
+
         $this->assertEquals($user->accountLoginName, $testUser->accountLoginName);
         $this->assertEquals('Tinebase_Model_FullUser', get_class($testUser), 'wrong type');
         
@@ -263,4 +243,31 @@ class Tinebase_User_LdapTest extends PHPUnit_Framework_TestCase
         
         return $user;
     }
+
+    /**
+     * @see 0011192: LDAP sync should delete contacts
+     */
+    public function testSyncDeleted()
+    {
+        $user = $this->testAddUser();
+
+        // delete user in ldap
+        Tinebase_User::getInstance()->deleteUserInSyncBackend($user->getId());
+
+        // check if still in tine20 db
+        $sqlUser = Tinebase_User::getInstance()->getUserByPropertyFromSqlBackend('accountId', $user->getId());
+        $this->assertEquals($user->getId(), $sqlUser->getId());
+
+        // set sync config/option + start user sync
+        $syncOptions = array('deleteUsers' => true);
+        Tinebase_User::syncUsers($syncOptions);
+
+        // check if user is deleted in tine, too
+        try {
+            Tinebase_User::getInstance()->getUserByPropertyFromSqlBackend('accountId', $user->getId());
+            $this->fail('user should be deleted from tine20 db');
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            $this->assertContains('User with accountId = ' . $sqlUser->getId(), $tenf->getMessage());
+        }
+    }
 }
index dd98feb..353e55e 100644 (file)
@@ -309,6 +309,11 @@ class Setup_Frontend_Cli
                 new Tinebase_EmailUser_Smtp_LdapDbmailSchema()
             );
         }
+
+        if ($_opts->syncdeletedusers) {
+            $options['deleteUsers'] = true;
+        }
+
         Tinebase_User::syncUsers($options);
     }
     
index 4eb1ad9..1d5af2f 100644 (file)
@@ -48,6 +48,7 @@ class Setup_Server_Cli implements Tinebase_Server_Interface
                 'sync_accounts_from_ldap'   => 'Import user and groups from ldap',
                     'dbmailldap'            => 'Only usable with sync_accounts_from_ldap. Fetches dbmail email user data from LDAP.',
                     'onlyusers'             => 'Only usable with sync_accounts_from_ldap. Fetches only users and no groups from LDAP.',
+                    'syncdeletedusers'      => 'Only usable with sync_accounts_from_ldap. Removes users from Tine 2.0 DB that no longer exist in LDAP',
                 'sync_passwords_from_ldap'  => 'Synchronize user passwords from ldap',
                 'egw14import'               => 'Import user and groups from egw14
                          Examples: 
index 0b7992c..b6174ae 100644 (file)
@@ -700,7 +700,7 @@ class Tinebase_User
     public static function syncUsers($options)
     {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
-            .' Start synchronizing users ...');
+            .' Start synchronizing users with options ' . print_r($options, true));
         
         $users = Tinebase_User::getInstance()->getUsersFromSyncBackend(NULL, NULL, 'ASC', NULL, NULL, 'Tinebase_Model_FullUser');
         
@@ -715,6 +715,10 @@ class Tinebase_User
                     . $ten->getMessage());
             }
         }
+
+        if (isset($options['deleteUsers']) && $options['deleteUsers']) {
+            self::_syncDeletedUsers($users);
+        }
         
         // @todo this should be improved: only the cache of synced users + group memberships should be cleaned
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
@@ -723,6 +727,24 @@ class Tinebase_User
     }
 
     /**
+     * deletes user in tine20 db that no longer exist in sync backend
+     *
+     * @param Tinebase_Record_RecordSet $usersInSyncBackend
+     */
+    protected static function _syncDeletedUsers(Tinebase_Record_RecordSet $usersInSyncBackend)
+    {
+        $userIdsInSqlBackend = Tinebase_User::getInstance()->getAllUserIdsFromSqlBackend();
+        $deletedInSyncBackend = array_diff($userIdsInSqlBackend, $usersInSyncBackend->getArrayOfIds());
+
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
+            . ' About to delete ' . count($deletedInSyncBackend) . ' users in SQL backend...');
+
+        foreach ($deletedInSyncBackend as $userToDelete) {
+            Tinebase_User::getInstance()->deleteUserInSqlBackend($userToDelete);
+        }
+    }
+
+    /**
      * get all user passwords from ldap
      * - set pw for user (in sql and sql plugins)
      * - do not encrypt the pw again as it is encrypted in LDAP
@@ -771,6 +793,7 @@ class Tinebase_User
      *
      * @param array $_options [hash that may contain override values for admin user name and password]
      * @return void
+     * @throws Tinebase_Exception_InvalidArgument
      */
     public static function createInitialAccounts($_options)
     {
index 79f7a16..912ef5c 100644 (file)
@@ -1038,4 +1038,20 @@ class Tinebase_User_Sql extends Tinebase_User_Abstract
         
         return $result;
     }
+
+    /**
+     * fetch all user ids from accounts table
+     *
+     * @return array
+     */
+    public function getAllUserIdsFromSqlBackend()
+    {
+        $sqlbackend = new Tinebase_Backend_Sql(array(
+            'modelName' => 'Tinebase_Model_FullUser',
+            'tableName' => $this->_tableName,
+        ));
+
+        $userIds = $sqlbackend->search(null, null, Tinebase_Backend_Sql_Abstract::IDCOL);
+        return $userIds;
+    }
 }