From 07a5c2658373f310c707a184e40201685cb04622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 22 Dec 2015 16:12:44 +0100 Subject: [PATCH] Add app to migrate contacts and calendars Add group sharing migration Migrate all users --- .gitignore | 3 - apps/dav/appinfo/application.php | 26 ++++ apps/dav/appinfo/install.php | 1 + apps/dav/appinfo/register_command.php | 8 ++ apps/dav/command/createaddressbook.php | 2 +- apps/dav/command/migrateaddressbooks.php | 65 ++++++++++ apps/dav/command/syncsystemaddressbook.php | 1 - .../dav/lib/migration/migrateaddressbooks.php | 118 ++++++++++++++++++ 8 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 apps/dav/command/migrateaddressbooks.php create mode 100644 apps/dav/lib/migration/migrateaddressbooks.php diff --git a/.gitignore b/.gitignore index 7d42be773b..237f0f44e8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,16 +11,13 @@ /apps*/* !/apps/dav !/apps/files -!/apps/files_encryption !/apps/federation !/apps/encryption -!/apps/encryption_dummy !/apps/files_external !/apps/files_sharing !/apps/files_trashbin !/apps/files_versions !/apps/user_ldap -!/apps/user_webdavauth !/apps/provisioning_api !/apps/systemtags /apps/files_external/3rdparty/irodsphp/PHPUnitTest diff --git a/apps/dav/appinfo/application.php b/apps/dav/appinfo/application.php index d8cf2a3411..b771bf2b3a 100644 --- a/apps/dav/appinfo/application.php +++ b/apps/dav/appinfo/application.php @@ -24,9 +24,11 @@ use OCA\DAV\CardDAV\ContactsManager; use OCA\DAV\CardDAV\SyncJob; use OCA\DAV\CardDAV\SyncService; use OCA\DAV\HookManager; +use OCA\Dav\Migration\MigrateAddressbooks; use \OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; use OCP\Contacts\IManager; +use OCP\IUser; class Application extends App { @@ -73,6 +75,14 @@ class Application extends App { return new \OCA\DAV\CardDAV\CardDavBackend($db, $principal, $logger); }); + $container->registerService('MigrateAddressbooks', function($c) { + /** @var IAppContainer $c */ + $db = $c->getServer()->getDatabaseConnection(); + return new MigrateAddressbooks( + $db, + $c->query('CardDavBackend') + ); + }); } /** @@ -100,4 +110,20 @@ class Application extends App { $jl->add(new SyncJob()); } + public function migrateAddressbooks() { + + try { + $migration = $this->getContainer()->query('MigrateAddressbooks'); + $migration->setup(); + $userManager = $this->getContainer()->getServer()->getUserManager(); + + $userManager->callForAllUsers(function($user) use($migration) { + /** @var IUser $user */ + $migration->migrateForUser($user->getUID()); + }); + } catch (\Exception $ex) { + $this->getContainer()->getServer()->getLogger()->logException($ex); + } + } + } diff --git a/apps/dav/appinfo/install.php b/apps/dav/appinfo/install.php index aaa36052cd..f6ef533958 100644 --- a/apps/dav/appinfo/install.php +++ b/apps/dav/appinfo/install.php @@ -23,3 +23,4 @@ use OCA\Dav\AppInfo\Application; $app = new Application(); $app->setupCron(); +$app->migrateAddressbooks(); diff --git a/apps/dav/appinfo/register_command.php b/apps/dav/appinfo/register_command.php index 8ef1979aa0..e8fea5daf2 100644 --- a/apps/dav/appinfo/register_command.php +++ b/apps/dav/appinfo/register_command.php @@ -22,6 +22,7 @@ use OCA\Dav\AppInfo\Application; use OCA\DAV\Command\CreateAddressBook; use OCA\DAV\Command\CreateCalendar; +use OCA\Dav\Command\MigrateAddressbooks; use OCA\DAV\Command\SyncSystemAddressBook; $config = \OC::$server->getConfig(); @@ -37,3 +38,10 @@ $app = new Application(); $application->add(new CreateAddressBook($userManager, $groupManager, $dbConnection, $logger)); $application->add(new CreateCalendar($userManager, $dbConnection)); $application->add(new SyncSystemAddressBook($app->getSyncService())); + +// the occ tool is *for now* only available in debug mode for developers to test +if ($config->getSystemValue('debug', false)){ + $app = new \OCA\Dav\AppInfo\Application(); + $migration = $app->getContainer()->query('MigrateAddressbooks'); + $application->add(new MigrateAddressbooks($userManager, $migration)); +} diff --git a/apps/dav/command/createaddressbook.php b/apps/dav/command/createaddressbook.php index 201101d17f..3d99afd4ba 100644 --- a/apps/dav/command/createaddressbook.php +++ b/apps/dav/command/createaddressbook.php @@ -88,7 +88,7 @@ class CreateAddressBook extends Command { ); $name = $input->getArgument('name'); - $carddav = new CardDavBackend($this->dbConnection, $principalBackend); + $carddav = new CardDavBackend($this->dbConnection, $principalBackend, $this->logger); $carddav->createAddressBook("principals/users/$user", $name, []); } } diff --git a/apps/dav/command/migrateaddressbooks.php b/apps/dav/command/migrateaddressbooks.php new file mode 100644 index 0000000000..22f5efebf2 --- /dev/null +++ b/apps/dav/command/migrateaddressbooks.php @@ -0,0 +1,65 @@ +userManager = $userManager; + $this->service = $service; + } + + protected function configure() { + $this + ->setName('dav:migrate-addressbooks') + ->setDescription('Migrate addressbooks from the contacts app to core') + ->addArgument('user', + InputArgument::OPTIONAL, + 'User for whom all addressbooks will be migrated'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $this->service->setup(); + + $user = $input->getArgument('user'); + if (!is_null($user)) { + if (!$this->userManager->userExists($user)) { + throw new \InvalidArgumentException("User <$user> in unknown."); + } + $output->writeln("Start migration for $user"); + $this->service->migrateForUser($user); + } + $output->writeln("Start migration of all known users ..."); + $p = new ProgressBar($output); + $p->start(); + $this->userManager->callForAllUsers(function($user) use ($p) { + $p->advance(); + /** @var IUser $user */ + $this->service->migrateForUser($user->getUID()); + }); + + $p->finish(); + $output->writeln(''); + } +} diff --git a/apps/dav/command/syncsystemaddressbook.php b/apps/dav/command/syncsystemaddressbook.php index 50f570ec93..b83a37131c 100644 --- a/apps/dav/command/syncsystemaddressbook.php +++ b/apps/dav/command/syncsystemaddressbook.php @@ -53,7 +53,6 @@ class SyncSystemAddressBook extends Command { * @param OutputInterface $output */ protected function execute(InputInterface $input, OutputInterface $output) { - $output->writeln('Syncing users ...'); $progress = new ProgressBar($output); $progress->start(); diff --git a/apps/dav/lib/migration/migrateaddressbooks.php b/apps/dav/lib/migration/migrateaddressbooks.php new file mode 100644 index 0000000000..3bc255571e --- /dev/null +++ b/apps/dav/lib/migration/migrateaddressbooks.php @@ -0,0 +1,118 @@ +dbConnection = $dbConnection; + $this->backend = $backend; + } + + private function verifyPreconditions() { + if (!$this->dbConnection->tableExists('contacts_addressbooks')) { + throw new \DomainException('Contacts tables are missing. Nothing to do.'); + } + } + + /** + * @param string $user + */ + public function migrateForUser($user) { + // get all addressbooks of that user + $query = $this->dbConnection->getQueryBuilder(); + $books = $query->select()->from('contacts_addressbooks') + ->where($query->expr()->eq('user', $query->createNamedParameter($user))) + ->execute() + ->fetchAll(); + + $principal = "principals/users/$user"; + foreach($books as $book) { + + $knownBooks = $this->backend->getAddressBooksByUri($principal, $book['uri']); + if (!is_null($knownBooks)) { + continue; + } + + $newId = $this->backend->createAddressBook($principal, $book['uri'], [ + '{DAV:}displayname' => $book['displayname'], + '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $book['description'] + ]); + + $this->migrateBook($book['id'], $newId); + $this->migrateShares($book['id'], $newId); + } + } + + public function setup() { + $this->verifyPreconditions(); + } + + /** + * @param int $addressBookId + * @param int $newAddressBookId + */ + private function migrateBook($addressBookId, $newAddressBookId) { + $query = $this->dbConnection->getQueryBuilder(); + $cards = $query->select()->from('contacts_cards') + ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) + ->execute() + ->fetchAll(); + + foreach ($cards as $card) { + $this->backend->createCard($newAddressBookId, $card['uri'], $card['carddata']); + } + } + + /** + * @param int $addressBookId + * @param int $newAddressBookId + */ + private function migrateShares($addressBookId, $newAddressBookId) { + $query = $this->dbConnection->getQueryBuilder(); + $shares = $query->select()->from('share') + ->where($query->expr()->eq('item_source', $query->createNamedParameter($addressBookId))) + ->andWhere($query->expr()->eq('item_type', $query->expr()->literal('addressbook'))) + ->andWhere($query->expr()->in('share_type', [ $query->expr()->literal(0), $query->expr()->literal(1)])) + ->execute() + ->fetchAll(); + + $add = array_map(function($s) { + $prefix = 'principal:principals/users/'; + if ($s['share_type'] === 1) { + $prefix = 'principal:principals/groups/'; + } + return [ + 'href' => $prefix . $s['share_with'] + ]; + }, $shares); + + $newAddressBook = $this->backend->getAddressBookById($newAddressBookId); + $book = new AddressBook($this->backend, $newAddressBook); + $this->backend->updateShares($book, $add, []); + } +}