@@ -22,18 +22,16 @@ | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\CardDAV\SyncService; | |||
\OC::$server->registerService('CardDAVSyncService', function() { | |||
$app = new \OCA\Dav\AppInfo\Application(); | |||
$app->registerHooks(); | |||
$app = new \OCA\Dav\AppInfo\Application(); | |||
/** @var CardDavBackend */ | |||
$backend = $app->getContainer()->query('CardDavBackend'); | |||
\OC::$server->registerService('CardDAVSyncService', function() use ($app) { | |||
return new SyncService($backend); | |||
return $app->getSyncService(); | |||
}); | |||
$cm = \OC::$server->getContactsManager(); | |||
$cm->register(function() use ($cm) { | |||
$cm->register(function() use ($cm, $app) { | |||
$userId = \OC::$server->getUserSession()->getUser()->getUID(); | |||
$app = new \OCA\Dav\AppInfo\Application(); | |||
$app->setupContactsProvider($cm, $userId); | |||
}); |
@@ -20,7 +20,10 @@ | |||
*/ | |||
namespace OCA\Dav\AppInfo; | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\CardDAV\ContactsManager; | |||
use OCA\DAV\CardDAV\SyncService; | |||
use OCA\DAV\HookManager; | |||
use \OCP\AppFramework\App; | |||
use OCP\AppFramework\IAppContainer; | |||
use OCP\Contacts\IManager; | |||
@@ -43,6 +46,22 @@ class Application extends App { | |||
); | |||
}); | |||
$container->registerService('HookManager', function($c) { | |||
/** @var IAppContainer $c */ | |||
return new HookManager( | |||
$c->getServer()->getUserManager(), | |||
$c->query('SyncService') | |||
); | |||
}); | |||
$container->registerService('SyncService', function($c) { | |||
/** @var IAppContainer $c */ | |||
return new SyncService( | |||
$c->query('CardDavBackend'), | |||
$c->getServer()->getUserManager() | |||
); | |||
}); | |||
$container->registerService('CardDavBackend', function($c) { | |||
/** @var IAppContainer $c */ | |||
$db = $c->getServer()->getDatabaseConnection(); | |||
@@ -65,4 +84,14 @@ class Application extends App { | |||
$cm->setupContactsProvider($contactsManager, $userID); | |||
} | |||
public function registerHooks() { | |||
/** @var HookManager $hm */ | |||
$hm = $this->getContainer()->query('HookManager'); | |||
$hm->setup(); | |||
} | |||
public function getSyncService() { | |||
return $this->getContainer()->query('SyncService'); | |||
} | |||
} |
@@ -22,6 +22,7 @@ namespace OCA\DAV\Command; | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\CardDAV\Converter; | |||
use OCA\DAV\CardDAV\SyncService; | |||
use OCA\DAV\Connector\Sabre\Principal; | |||
use OCP\IConfig; | |||
use OCP\IDBConnection; | |||
@@ -39,28 +40,16 @@ use Symfony\Component\Console\Output\OutputInterface; | |||
class SyncSystemAddressBook extends Command { | |||
/** @var IUserManager */ | |||
protected $userManager; | |||
/** @var \OCP\IDBConnection */ | |||
protected $dbConnection; | |||
/** @var IConfig */ | |||
protected $config; | |||
/** @var CardDavBackend */ | |||
private $backend; | |||
/** @var SyncService */ | |||
private $syncService; | |||
/** | |||
* @param IUserManager $userManager | |||
* @param IDBConnection $dbConnection | |||
* @param IConfig $config | |||
* @param SyncService $syncService | |||
*/ | |||
function __construct(IUserManager $userManager, IDBConnection $dbConnection, IConfig $config) { | |||
function __construct(SyncService $syncService) { | |||
parent::__construct(); | |||
$this->userManager = $userManager; | |||
$this->dbConnection = $dbConnection; | |||
$this->config = $config; | |||
$this->syncService = $syncService; | |||
} | |||
protected function configure() { | |||
@@ -74,63 +63,15 @@ class SyncSystemAddressBook extends Command { | |||
* @param OutputInterface $output | |||
*/ | |||
protected function execute(InputInterface $input, OutputInterface $output) { | |||
$principalBackend = new Principal( | |||
$this->userManager | |||
); | |||
$this->backend = new CardDavBackend($this->dbConnection, $principalBackend); | |||
// ensure system addressbook exists | |||
$systemAddressBook = $this->ensureSystemAddressBookExists(); | |||
$converter = new Converter(); | |||
$output->writeln('Syncing users ...'); | |||
$progress = new ProgressBar($output); | |||
$progress->start(); | |||
$this->userManager->callForAllUsers(function($user) use ($systemAddressBook, $converter, $progress) { | |||
/** @var IUser $user */ | |||
$name = $user->getBackendClassName(); | |||
$userId = $user->getUID(); | |||
$cardId = "$name:$userId.vcf"; | |||
$card = $this->backend->getCard($systemAddressBook['id'], $cardId); | |||
if ($card === false) { | |||
$vCard = $converter->createCardFromUser($user); | |||
$this->backend->createCard($systemAddressBook['id'], $cardId, $vCard->serialize()); | |||
} else { | |||
$vCard = Reader::read($card['carddata']); | |||
if ($converter->updateCard($vCard, $user)) { | |||
$this->backend->updateCard($systemAddressBook['id'], $cardId, $vCard->serialize()); | |||
} | |||
} | |||
$this->syncService->syncInstance(function() use ($progress) { | |||
$progress->advance(); | |||
}); | |||
// remove no longer existing | |||
$allCards = $this->backend->getCards($systemAddressBook['id']); | |||
foreach($allCards as $card) { | |||
$vCard = Reader::read($card['carddata']); | |||
$uid = $vCard->UID->getValue(); | |||
// load backend and see if user exists | |||
if (!$this->userManager->userExists($uid)) { | |||
$this->backend->deleteCard($systemAddressBook['id'], $card['uri']); | |||
} | |||
} | |||
$progress->finish(); | |||
$output->writeln(''); | |||
} | |||
protected function ensureSystemAddressBookExists() { | |||
$book = $this->backend->getAddressBooksByUri('system'); | |||
if (!is_null($book)) { | |||
return $book; | |||
} | |||
$systemPrincipal = "principals/system/system"; | |||
$this->backend->createAddressBook($systemPrincipal, 'system', [ | |||
'{' . Plugin::NS_CARDDAV . '}addressbook-description' => 'System addressbook which holds all users of this instance' | |||
]); | |||
return $this->backend->getAddressBooksByUri('system'); | |||
} | |||
} |
@@ -21,18 +21,27 @@ | |||
namespace OCA\DAV\CardDAV; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use Sabre\DAV\Client; | |||
use Sabre\DAV\Xml\Response\MultiStatus; | |||
use Sabre\DAV\Xml\Service; | |||
use Sabre\HTTP\ClientException; | |||
use Sabre\VObject\Reader; | |||
class SyncService { | |||
/** @var CardDavBackend */ | |||
private $backend; | |||
public function __construct(CardDavBackend $backend) { | |||
/** @var IUserManager */ | |||
private $userManager; | |||
/** @var array */ | |||
private $localSystemAddressBook; | |||
public function __construct(CardDavBackend $backend, IUserManager $userManager) { | |||
$this->backend = $backend; | |||
$this->userManager = $userManager; | |||
} | |||
/** | |||
@@ -80,7 +89,7 @@ class SyncService { | |||
* @return array|null | |||
* @throws \Sabre\DAV\Exception\BadRequest | |||
*/ | |||
protected function ensureSystemAddressBookExists($principal, $id, $properties) { | |||
public function ensureSystemAddressBookExists($principal, $id, $properties) { | |||
$book = $this->backend->getAddressBooksByUri($id); | |||
if (!is_null($book)) { | |||
return $book; | |||
@@ -180,5 +189,75 @@ class SyncService { | |||
return ['response' => $result, 'token' => $multiStatus->getSyncToken()]; | |||
} | |||
/** | |||
* @param IUser $user | |||
*/ | |||
public function updateUser($user) { | |||
$systemAddressBook = $this->getLocalSystemAddressBook(); | |||
$addressBookId = $systemAddressBook['id']; | |||
$converter = new Converter(); | |||
$name = $user->getBackendClassName(); | |||
$userId = $user->getUID(); | |||
$cardId = "$name:$userId.vcf"; | |||
$card = $this->backend->getCard($addressBookId, $cardId); | |||
if ($card === false) { | |||
$vCard = $converter->createCardFromUser($user); | |||
$this->backend->createCard($addressBookId, $cardId, $vCard->serialize()); | |||
} else { | |||
$vCard = Reader::read($card['carddata']); | |||
if ($converter->updateCard($vCard, $user)) { | |||
$this->backend->updateCard($addressBookId, $cardId, $vCard->serialize()); | |||
} | |||
} | |||
} | |||
/** | |||
* @param IUser|string $userOrCardId | |||
*/ | |||
public function deleteUser($userOrCardId) { | |||
$systemAddressBook = $this->getLocalSystemAddressBook(); | |||
if ($userOrCardId instanceof IUser){ | |||
$name = $userOrCardId->getBackendClassName(); | |||
$userId = $userOrCardId->getUID(); | |||
$userOrCardId = "$name:$userId.vcf"; | |||
} | |||
$this->backend->deleteCard($systemAddressBook['id'], $userOrCardId); | |||
} | |||
/** | |||
* @return array|null | |||
*/ | |||
public function getLocalSystemAddressBook() { | |||
if (is_null($this->localSystemAddressBook)) { | |||
$systemPrincipal = "principals/system/system"; | |||
$this->localSystemAddressBook = $this->ensureSystemAddressBookExists($systemPrincipal, 'system', [ | |||
'{' . Plugin::NS_CARDDAV . '}addressbook-description' => 'System addressbook which holds all users of this instance' | |||
]); | |||
} | |||
return $this->localSystemAddressBook; | |||
} | |||
public function syncInstance(\Closure $progressCallback) { | |||
$systemAddressBook = $this->getLocalSystemAddressBook(); | |||
$this->userManager->callForAllUsers(function($user) use ($systemAddressBook, $progressCallback) { | |||
$this->updateUser($user); | |||
$progressCallback(); | |||
}); | |||
// remove no longer existing | |||
$allCards = $this->backend->getCards($systemAddressBook['id']); | |||
foreach($allCards as $card) { | |||
$vCard = Reader::read($card['carddata']); | |||
$uid = $vCard->UID->getValue(); | |||
// load backend and see if user exists | |||
if (!$this->userManager->userExists($uid)) { | |||
$this->deleteUser($card['uri']); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,74 @@ | |||
<?php | |||
/** | |||
* @author Thomas Müller <thomas.mueller@tmit.eu> | |||
* | |||
* @copyright Copyright (c) 2016, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV; | |||
use OCA\DAV\CardDAV\SyncService; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use OCP\Util; | |||
class HookManager { | |||
/** @var IUserManager */ | |||
private $userManager; | |||
/** @var SyncService */ | |||
private $syncService; | |||
/** @var IUser[] */ | |||
private $usersToDelete; | |||
public function __construct(IUserManager $userManager, SyncService $syncService) { | |||
$this->userManager = $userManager; | |||
$this->syncService = $syncService; | |||
} | |||
public function setup() { | |||
Util::connectHook('OC_User', | |||
'post_createUser', | |||
$this, | |||
'postCreateUser'); | |||
Util::connectHook('OC_User', | |||
'pre_deleteUser', | |||
$this, | |||
'preDeleteUser'); | |||
Util::connectHook('OC_User', | |||
'post_deleteUser', | |||
$this, | |||
'postDeleteUser'); | |||
} | |||
public function postCreateUser($params) { | |||
$user = $this->userManager->get($params['uid']); | |||
$this->syncService->updateUser($user); | |||
} | |||
public function preDeleteUser($params) { | |||
$this->usersToDelete[$params['uid']] = $this->userManager->get($params['uid']); | |||
} | |||
public function postDeleteUser($params) { | |||
$uid = $params['uid']; | |||
if (isset($this->usersToDelete[$uid])){ | |||
$this->syncService->deleteUser($this->usersToDelete[$uid]); | |||
} | |||
} | |||
} |
@@ -77,8 +77,9 @@ class SyncServiceTest extends TestCase { | |||
* @return SyncService|\PHPUnit_Framework_MockObject_MockObject | |||
*/ | |||
private function getSyncServiceMock($backend, $response) { | |||
$userManager = $this->getMockBuilder('OCP\IUserManager')->disableOriginalConstructor()->getMock(); | |||
/** @var SyncService | \PHPUnit_Framework_MockObject_MockObject $ss */ | |||
$ss = $this->getMock('OCA\DAV\CardDAV\SyncService', ['ensureSystemAddressBookExists', 'requestSyncReport', 'download'], [$backend]); | |||
$ss = $this->getMock('OCA\DAV\CardDAV\SyncService', ['ensureSystemAddressBookExists', 'requestSyncReport', 'download'], [$backend, $userManager]); | |||
$ss->method('requestSyncReport')->withAnyParameters()->willReturn(['response' => $response, 'token' => 'sync-token-1']); | |||
$ss->method('ensureSystemAddressBookExists')->willReturn(['id' => 1]); | |||
$ss->method('download')->willReturn([ |