Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/dav/appinfo/v1/carddav.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* @author Morris Jobke <[email protected]>
* @author Thomas Citharel <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Anna Larch <[email protected]>
*
* @license AGPL-3.0
*
Expand Down Expand Up @@ -72,7 +73,7 @@
$principalCollection->disableListing = !$debugging; // Disable listing

$pluginManager = new PluginManager(\OC::$server, \OC::$server->query(IAppManager::class));
$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend, $pluginManager);
$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend, $pluginManager, \OC::$server->getUserSession()->getUser(), \OC::$server->get(\OCP\IGroupManager::class));

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OC\Server::getUserSession has been marked as deprecated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\OCP\Server::get(…) … but can be added in a follow up

$addressBookRoot->disableListing = !$debugging; // Disable listing

$nodes = [
Expand Down
13 changes: 11 additions & 2 deletions apps/dav/lib/CardDAV/AddressBookRoot.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* @author Christoph Wurst <[email protected]>
* @author Joas Schilling <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Anna Larch <[email protected]>
*
* @license AGPL-3.0
*
Expand All @@ -24,11 +25,15 @@
namespace OCA\DAV\CardDAV;

use OCA\DAV\AppInfo\PluginManager;
use OCP\IGroupManager;
use OCP\IUser;

class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot {

/** @var PluginManager */
private $pluginManager;
private ?IUser $user;
private ?IGroupManager $groupManager;

/**
* @param \Sabre\DAVACL\PrincipalBackend\BackendInterface $principalBackend
Expand All @@ -38,9 +43,13 @@ class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot {
public function __construct(\Sabre\DAVACL\PrincipalBackend\BackendInterface $principalBackend,
\Sabre\CardDAV\Backend\BackendInterface $carddavBackend,
PluginManager $pluginManager,
$principalPrefix = 'principals') {
?IUser $user,
?IGroupManager $groupManager,
string $principalPrefix = 'principals') {
parent::__construct($principalBackend, $carddavBackend, $principalPrefix);
$this->pluginManager = $pluginManager;
$this->user = $user;
$this->groupManager = $groupManager;
}

/**
Expand All @@ -55,7 +64,7 @@ public function __construct(\Sabre\DAVACL\PrincipalBackend\BackendInterface $pri
* @return \Sabre\DAV\INode
*/
public function getChildForPrincipal(array $principal) {
return new UserAddressBooks($this->carddavBackend, $principal['uri'], $this->pluginManager);
return new UserAddressBooks($this->carddavBackend, $principal['uri'], $this->pluginManager, $this->user, $this->groupManager);
}

public function getName() {
Expand Down
5 changes: 5 additions & 0 deletions apps/dav/lib/CardDAV/CardDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ public function getAddressBooksByUri(string $principal, string $addressBookUri):
'{http://sabredav.org/ns}sync-token' => $row['synctoken'] ?: '0',
];

// system address books are always read only
if ($principal === 'principals/system/system') {
$addressBook['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only'] = true;
}

$this->addOwnerPrincipal($addressBook);

return $addressBook;
Expand Down
18 changes: 11 additions & 7 deletions apps/dav/lib/CardDAV/SyncService.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* @author Morris Jobke <[email protected]>
* @author Thomas Citharel <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Anna Larch <[email protected]>
*
* @license AGPL-3.0
*
Expand Down Expand Up @@ -209,10 +210,8 @@ private function parseMultiStatus($body) {
public function updateUser(IUser $user) {
$systemAddressBook = $this->getLocalSystemAddressBook();
$addressBookId = $systemAddressBook['id'];
$name = $user->getBackendClassName();
$userId = $user->getUID();

$cardId = "$name:$userId.vcf";
$cardId = self::getCardUri($user);
if ($user->isEnabled()) {
$card = $this->backend->getCard($addressBookId, $cardId);
if ($card === false) {
Expand All @@ -239,10 +238,7 @@ public function updateUser(IUser $user) {
public function deleteUser($userOrCardId) {
$systemAddressBook = $this->getLocalSystemAddressBook();
if ($userOrCardId instanceof IUser) {
$name = $userOrCardId->getBackendClassName();
$userId = $userOrCardId->getUID();

$userOrCardId = "$name:$userId.vcf";
$userOrCardId = self::getCardUri($userOrCardId);
}
$this->backend->deleteCard($systemAddressBook['id'], $userOrCardId);
}
Expand Down Expand Up @@ -281,4 +277,12 @@ public function syncInstance(\Closure $progressCallback = null) {
}
}
}

/**
* @param IUser $user
* @return string
*/
public static function getCardUri(IUser $user): string {
return $user->getBackendClassName() . ':' . $user->getUID() . '.vcf';
}
}
79 changes: 75 additions & 4 deletions apps/dav/lib/CardDAV/SystemAddressbook.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @author Joas Schilling <[email protected]>
* @author Julius Härtl <[email protected]>
* @author Roeland Jago Douma <[email protected]>
* @author Anna Larch <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
Expand All @@ -31,38 +32,97 @@
use OCA\Federation\TrustedServers;
use OCP\Accounts\IAccountManager;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use Sabre\CardDAV\Backend\SyncSupport;
use Sabre\CardDAV\Backend\BackendInterface;
use Sabre\CardDAV\Card;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Reader;
use function array_unique;

class SystemAddressbook extends AddressBook {
public const URI_SHARED = 'z-server-generated--system';
/** @var IConfig */
private $config;
private IUserSession $userSession;
private ?TrustedServers $trustedServers;
private ?IRequest $request;
private ?IGroupManager $groupManager;

public function __construct(BackendInterface $carddavBackend, array $addressBookInfo, IL10N $l10n, IConfig $config, ?IRequest $request = null, ?TrustedServers $trustedServers = null) {
public function __construct(BackendInterface $carddavBackend,
array $addressBookInfo,
IL10N $l10n,
IConfig $config,
IUserSession $userSession,
?IRequest $request = null,
?TrustedServers $trustedServers = null,
?IGroupManager $groupManager) {
parent::__construct($carddavBackend, $addressBookInfo, $l10n);
$this->config = $config;
$this->userSession = $userSession;
$this->request = $request;
$this->trustedServers = $trustedServers;
$this->groupManager = $groupManager;

$this->addressBookInfo['{DAV:}displayname'] = $l10n->t('Accounts');
$this->addressBookInfo['{' . Plugin::NS_CARDDAV . '}addressbook-description'] = $l10n->t('System address book which holds all accounts');
}

public function getChildren(): array {
/**
* No checkbox checked -> Show only the same user
* 'Allow username autocompletion in share dialog' -> show everyone
* 'Allow username autocompletion in share dialog' + 'Allow username autocompletion to users within the same groups' -> show only users in intersecting groups
* 'Allow username autocompletion in share dialog' + 'Allow username autocompletion to users based on phone number integration' -> show only the same user
* 'Allow username autocompletion in share dialog' + 'Allow username autocompletion to users within the same groups' + 'Allow username autocompletion to users based on phone number integration' -> show only users in intersecting groups
*/
public function getChildren() {
$shareEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$shareEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$shareEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
if (!$shareEnumeration || $shareEnumerationGroup || $shareEnumerationPhone) {
$user = $this->userSession->getUser();
if (!$user) {
// Should never happen because we don't allow anonymous access
return [];
}
if (!$shareEnumeration || !$shareEnumerationGroup && $shareEnumerationPhone) {
$name = SyncService::getCardUri($user);
try {
return [parent::getChild($name)];
} catch (NotFound $e) {
return [];
}
}
if ($shareEnumerationGroup) {
if ($this->groupManager === null) {
// Group manager is not available, so we can't determine which data is safe
return [];
}
$groups = $this->groupManager->getUserGroups($user);
$names = [];
foreach ($groups as $group) {
$users = $group->getUsers();
foreach ($users as $groupUser) {
if ($groupUser->getBackendClassName() === 'Guests') {
continue;
}
$names[] = SyncService::getCardUri($groupUser);
}
}
return parent::getMultipleChildren(array_unique($names));
}

return parent::getChildren();
$children = parent::getChildren();
return array_filter($children, function (Card $child) {
// check only for URIs that begin with Guests:
return strpos($child->getName(), 'Guests:') !== 0;
});
}

/**
Expand Down Expand Up @@ -225,4 +285,15 @@ private function extractCarddata(array $obj): ?string {

return $vCard->serialize();
}

/**
* @return mixed
* @throws Forbidden
*/
public function delete() {
if ($this->isFederation()) {
parent::delete();
}
throw new Forbidden();
}
}
53 changes: 44 additions & 9 deletions apps/dav/lib/CardDAV/UserAddressBooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* @author Joas Schilling <[email protected]>
* @author Roeland Jago Douma <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Anna Larch <[email protected]>
*
* @license AGPL-3.0
*
Expand All @@ -33,8 +34,11 @@
use OCA\Federation\TrustedServers;
use OCP\AppFramework\QueryException;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Sabre\CardDAV\Backend;
Expand All @@ -44,7 +48,6 @@
use Sabre\DAV\MkCol;

class UserAddressBooks extends \Sabre\CardDAV\AddressBookHome {

/** @var IL10N */
protected $l10n;

Expand All @@ -53,12 +56,18 @@ class UserAddressBooks extends \Sabre\CardDAV\AddressBookHome {

/** @var PluginManager */
private $pluginManager;
private ?IUser $user;
private ?IGroupManager $groupManager;

public function __construct(Backend\BackendInterface $carddavBackend,
string $principalUri,
PluginManager $pluginManager) {
PluginManager $pluginManager,
?IUser $user,
?IGroupManager $groupManager) {
parent::__construct($carddavBackend, $principalUri);
$this->pluginManager = $pluginManager;
$this->user = $user;
$this->groupManager = $groupManager;
}

/**
Expand All @@ -74,10 +83,25 @@ public function getChildren() {
$this->config = \OC::$server->getConfig();
}

/** @var string|array $principal */
$principal = $this->principalUri;
$addressBooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
/** @var IAddressBook[] $objects */
$objects = array_map(function (array $addressBook) {
if ($addressBook['principaluri'] === 'principals/system/system') {
// add the system address book
$systemAddressBook = null;
if (is_string($principal) && $principal !== 'principals/system/system' && $this->carddavBackend instanceof CardDavBackend) {
$systemAddressBook = $this->carddavBackend->getAddressBooksByUri('principals/system/system', 'system');
if ($systemAddressBook !== null) {
$systemAddressBook['uri'] = SystemAddressbook::URI_SHARED;
}
}
if (!is_null($systemAddressBook)) {
$addressBooks[] = $systemAddressBook;
}

$objects = [];
if (!empty($addressBooks)) {
/** @var IAddressBook[] $objects */
$objects = array_map(function (array $addressBook) {
$trustedServers = null;
$request = null;
try {
Expand All @@ -86,11 +110,22 @@ public function getChildren() {
} catch (NotFoundExceptionInterface | ContainerExceptionInterface $e) {
// nothing to do, the request / trusted servers don't exist
}
return new SystemAddressbook($this->carddavBackend, $addressBook, $this->l10n, $this->config, $request, $trustedServers);
}
if ($addressBook['principaluri'] === 'principals/system/system') {
return new SystemAddressbook(
$this->carddavBackend,
$addressBook,
$this->l10n,
$this->config,
\OCP\Server::get(IUserSession::class),
$request,
$trustedServers,
$this->groupManager
);
}

return new AddressBook($this->carddavBackend, $addressBook, $this->l10n);
}, $addressBooks);
return new AddressBook($this->carddavBackend, $addressBook, $this->l10n);
}, $addressBooks);
}
/** @var IAddressBook[][] $objectsFromPlugins */
$objectsFromPlugins = array_map(function (IAddressBookProvider $plugin): array {
return $plugin->fetchAllForAddressBookHome($this->principalUri);
Expand Down
5 changes: 3 additions & 2 deletions apps/dav/lib/RootCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\IGroupManager;
use Psr\Log\LoggerInterface;
use Sabre\DAV\SimpleCollection;

Expand Down Expand Up @@ -144,11 +145,11 @@ public function __construct() {

$pluginManager = new PluginManager(\OC::$server, \OC::$server->query(IAppManager::class));
$usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, $pluginManager, 'principals/users');
$usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, $pluginManager, $userSession->getUser(), $groupManager, 'principals/users');
$usersAddressBookRoot->disableListing = $disableListing;

$systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, $pluginManager, 'principals/system');
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, $pluginManager, $userSession->getUser(), $groupManager, 'principals/system');
$systemAddressBookRoot->disableListing = $disableListing;

$uploadCollection = new Upload\RootCollection(
Expand Down
Loading