Merge pull request #52961 from nextcloud/backport/52808/stable30
[stable30] Introduce own method for calendar unsharingpull/53259/head
commit
f2ff14e6a4
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\DAV\Command;
|
||||
|
||||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\CalDAV\Sharing\Backend;
|
||||
use OCA\DAV\CalDAV\Sharing\Service;
|
||||
use OCA\DAV\Connector\Sabre\Principal;
|
||||
use OCA\DAV\DAV\Sharing\Backend as BackendAlias;
|
||||
use OCA\DAV\DAV\Sharing\SharingMapper;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IUserManager;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'dav:clear-calendar-unshares',
|
||||
description: 'Clear calendar unshares for a user',
|
||||
hidden: false,
|
||||
)]
|
||||
class ClearCalendarUnshares extends Command {
|
||||
public function __construct(
|
||||
private IUserManager $userManager,
|
||||
private IAppConfig $appConfig,
|
||||
private Principal $principal,
|
||||
private CalDavBackend $caldav,
|
||||
private Backend $sharingBackend,
|
||||
private Service $sharingService,
|
||||
private SharingMapper $mapper,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void {
|
||||
$this->addArgument(
|
||||
'uid',
|
||||
InputArgument::REQUIRED,
|
||||
'User whose unshares to clear'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$user = (string) $input->getArgument('uid');
|
||||
if (!$this->userManager->userExists($user)) {
|
||||
throw new \InvalidArgumentException("User $user is unknown");
|
||||
}
|
||||
|
||||
$principal = $this->principal->getPrincipalByPath('principals/users/' . $user);
|
||||
if ($principal === null) {
|
||||
throw new \InvalidArgumentException("Unable to fetch principal for user $user ");
|
||||
}
|
||||
|
||||
$shares = $this->mapper->getSharesByPrincipals([$principal['uri']], 'calendar');
|
||||
$unshares = array_filter($shares, static fn ($share) => $share['access'] === BackendAlias::ACCESS_UNSHARED);
|
||||
|
||||
if (count($unshares) === 0) {
|
||||
$output->writeln("User $user has no calendar unshares");
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$rows = array_map(fn ($share) => $this->formatCalendarUnshare($share), $shares);
|
||||
|
||||
$table = new Table($output);
|
||||
$table
|
||||
->setHeaders(['Share Id', 'Calendar Id', 'Calendar URI', 'Calendar Name'])
|
||||
->setRows($rows)
|
||||
->render();
|
||||
|
||||
$output->writeln('');
|
||||
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('Please confirm to delete the above calendar unshare entries [y/n]', false);
|
||||
|
||||
if ($helper->ask($input, $output, $question)) {
|
||||
$this->mapper->deleteUnsharesByPrincipal($principal['uri'], 'calendar');
|
||||
$output->writeln("Calendar unshares for user $user deleted");
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function formatCalendarUnshare(array $share): array {
|
||||
$calendarInfo = $this->caldav->getCalendarById($share['resourceid']);
|
||||
|
||||
$resourceUri = 'Resource not found';
|
||||
$resourceName = '';
|
||||
|
||||
if ($calendarInfo !== null) {
|
||||
$resourceUri = $calendarInfo['uri'];
|
||||
$resourceName = $calendarInfo['{DAV:}displayname'];
|
||||
}
|
||||
|
||||
return [
|
||||
$share['id'],
|
||||
$share['resourceid'],
|
||||
$resourceUri,
|
||||
$resourceName,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\DAV\Command;
|
||||
|
||||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\CalDAV\Sharing\Backend;
|
||||
use OCA\DAV\Connector\Sabre\Principal;
|
||||
use OCA\DAV\DAV\Sharing\SharingMapper;
|
||||
use OCP\IUserManager;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'dav:list-calendar-shares',
|
||||
description: 'List all calendar shares for a user',
|
||||
hidden: false,
|
||||
)]
|
||||
class ListCalendarShares extends Command {
|
||||
public function __construct(
|
||||
private IUserManager $userManager,
|
||||
private Principal $principal,
|
||||
private CalDavBackend $caldav,
|
||||
private SharingMapper $mapper,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void {
|
||||
$this->addArgument(
|
||||
'uid',
|
||||
InputArgument::REQUIRED,
|
||||
'User whose calendar shares will be listed'
|
||||
);
|
||||
$this->addOption(
|
||||
'calendar-id',
|
||||
'',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'List only shares for the given calendar id id',
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$user = (string) $input->getArgument('uid');
|
||||
if (!$this->userManager->userExists($user)) {
|
||||
throw new \InvalidArgumentException("User $user is unknown");
|
||||
}
|
||||
|
||||
$principal = $this->principal->getPrincipalByPath('principals/users/' . $user);
|
||||
if ($principal === null) {
|
||||
throw new \InvalidArgumentException("Unable to fetch principal for user $user");
|
||||
}
|
||||
|
||||
$memberships = array_merge(
|
||||
[$principal['uri']],
|
||||
$this->principal->getGroupMembership($principal['uri']),
|
||||
$this->principal->getCircleMembership($principal['uri']),
|
||||
);
|
||||
|
||||
$shares = $this->mapper->getSharesByPrincipals($memberships, 'calendar');
|
||||
|
||||
$calendarId = $input->getOption('calendar-id');
|
||||
if ($calendarId !== null) {
|
||||
$shares = array_filter($shares, fn ($share) => $share['resourceid'] === (int) $calendarId);
|
||||
}
|
||||
|
||||
$rows = array_map(fn ($share) => $this->formatCalendarShare($share), $shares);
|
||||
|
||||
if (count($rows) > 0) {
|
||||
$table = new Table($output);
|
||||
$table
|
||||
->setHeaders(['Share Id', 'Calendar Id', 'Calendar URI', 'Calendar Name', 'Calendar Owner', 'Access By', 'Permissions'])
|
||||
->setRows($rows)
|
||||
->render();
|
||||
} else {
|
||||
$output->writeln("User $user has no calendar shares");
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function formatCalendarShare(array $share): array {
|
||||
$calendarInfo = $this->caldav->getCalendarById($share['resourceid']);
|
||||
|
||||
$calendarUri = 'Resource not found';
|
||||
$calendarName = '';
|
||||
$calendarOwner = '';
|
||||
|
||||
if ($calendarInfo !== null) {
|
||||
$calendarUri = $calendarInfo['uri'];
|
||||
$calendarName = $calendarInfo['{DAV:}displayname'];
|
||||
$calendarOwner = $calendarInfo['{http://nextcloud.com/ns}owner-displayname'] . ' (' . $calendarInfo['principaluri'] . ')';
|
||||
}
|
||||
|
||||
$accessBy = match (true) {
|
||||
str_starts_with($share['principaluri'], 'principals/users/') => 'Individual',
|
||||
str_starts_with($share['principaluri'], 'principals/groups/') => 'Group (' . $share['principaluri'] . ')',
|
||||
str_starts_with($share['principaluri'], 'principals/circles/') => 'Team (' . $share['principaluri'] . ')',
|
||||
default => $share['principaluri'],
|
||||
};
|
||||
|
||||
$permissions = match ($share['access']) {
|
||||
Backend::ACCESS_READ => 'Read',
|
||||
Backend::ACCESS_READ_WRITE => 'Read/Write',
|
||||
Backend::ACCESS_UNSHARED => 'Unshare',
|
||||
default => $share['access'],
|
||||
};
|
||||
|
||||
return [
|
||||
$share['id'],
|
||||
$share['resourceid'],
|
||||
$calendarUri,
|
||||
$calendarName,
|
||||
$calendarOwner,
|
||||
$accessBy,
|
||||
$permissions,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\DAV\Tests\integration\DAV\Sharing;
|
||||
|
||||
use OCA\DAV\CalDAV\Calendar;
|
||||
use OCA\DAV\Connector\Sabre\Principal;
|
||||
use OCA\DAV\DAV\Sharing\Backend;
|
||||
use OCA\DAV\DAV\Sharing\SharingMapper;
|
||||
use OCA\DAV\DAV\Sharing\SharingService;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Server;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
/**
|
||||
* @group DB
|
||||
*/
|
||||
class CalDavSharingBackendTest extends TestCase {
|
||||
|
||||
private IDBConnection $db;
|
||||
private IUserManager $userManager;
|
||||
private IGroupManager $groupManager;
|
||||
private Principal $principalBackend;
|
||||
private ICacheFactory $cacheFactory;
|
||||
private LoggerInterface $logger;
|
||||
private SharingMapper $sharingMapper;
|
||||
private SharingService $sharingService;
|
||||
private Backend $sharingBackend;
|
||||
|
||||
private $resourceIds = [10001];
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->db = Server::get(IDBConnection::class);
|
||||
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
$this->principalBackend = $this->createMock(Principal::class);
|
||||
$this->cacheFactory = $this->createMock(ICacheFactory::class);
|
||||
$this->cacheFactory->method('createInMemory')
|
||||
->willReturn(new \OC\Memcache\NullCache());
|
||||
$this->logger = new \Psr\Log\NullLogger();
|
||||
|
||||
$this->sharingMapper = new SharingMapper($this->db);
|
||||
$this->sharingService = new \OCA\DAV\CalDAV\Sharing\Service($this->sharingMapper);
|
||||
|
||||
$this->sharingBackend = new \OCA\DAV\CalDAV\Sharing\Backend(
|
||||
$this->userManager,
|
||||
$this->groupManager,
|
||||
$this->principalBackend,
|
||||
$this->cacheFactory,
|
||||
$this->sharingService,
|
||||
$this->logger
|
||||
);
|
||||
|
||||
$this->removeFixtures();
|
||||
}
|
||||
|
||||
protected function tearDown(): void {
|
||||
$this->removeFixtures();
|
||||
}
|
||||
|
||||
protected function removeFixtures(): void {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('dav_shares')
|
||||
->where($qb->expr()->in('resourceid', $qb->createNamedParameter($this->resourceIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
$qb->executeStatement();
|
||||
}
|
||||
|
||||
public function testShareCalendarWithGroup(): void {
|
||||
$calendar = $this->createMock(Calendar::class);
|
||||
$calendar->method('getResourceId')
|
||||
->willReturn(10001);
|
||||
$calendar->method('getOwner')
|
||||
->willReturn('principals/users/admin');
|
||||
|
||||
$this->principalBackend->method('findByUri')
|
||||
->willReturn('principals/groups/alice_bob');
|
||||
|
||||
$this->groupManager->method('groupExists')
|
||||
->willReturn(true);
|
||||
|
||||
$this->sharingBackend->updateShares(
|
||||
$calendar,
|
||||
[['href' => 'principals/groups/alice_bob']],
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
}
|
||||
|
||||
public function testUnshareCalendarFromGroup(): void {
|
||||
$calendar = $this->createMock(Calendar::class);
|
||||
$calendar->method('getResourceId')
|
||||
->willReturn(10001);
|
||||
$calendar->method('getOwner')
|
||||
->willReturn('principals/users/admin');
|
||||
|
||||
$this->principalBackend->method('findByUri')
|
||||
->willReturn('principals/groups/alice_bob');
|
||||
|
||||
$this->groupManager->method('groupExists')
|
||||
->willReturn(true);
|
||||
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [['href' => 'principals/groups/alice_bob']],
|
||||
remove: [],
|
||||
);
|
||||
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [],
|
||||
remove: ['principals/groups/alice_bob'],
|
||||
);
|
||||
|
||||
$this->assertCount(0, $this->sharingService->getShares(10001));
|
||||
}
|
||||
|
||||
public function testShareCalendarWithGroupAndUnshareAsUser(): void {
|
||||
$calendar = $this->createMock(Calendar::class);
|
||||
$calendar->method('getResourceId')
|
||||
->willReturn(10001);
|
||||
$calendar->method('getOwner')
|
||||
->willReturn('principals/users/admin');
|
||||
|
||||
$this->principalBackend->method('findByUri')
|
||||
->willReturnMap([
|
||||
['principals/groups/alice_bob', '', 'principals/groups/alice_bob'],
|
||||
['principals/users/bob', '', 'principals/users/bob'],
|
||||
]);
|
||||
$this->principalBackend->method('getGroupMembership')
|
||||
->willReturn([
|
||||
'principals/groups/alice_bob',
|
||||
]);
|
||||
$this->principalBackend->method('getCircleMembership')
|
||||
->willReturn([]);
|
||||
|
||||
$this->groupManager->method('groupExists')
|
||||
->willReturn(true);
|
||||
|
||||
/*
|
||||
* Owner is sharing the calendar with a group.
|
||||
*/
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [['href' => 'principals/groups/alice_bob']],
|
||||
remove: [],
|
||||
);
|
||||
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
|
||||
/*
|
||||
* Member of the group unshares the calendar.
|
||||
*/
|
||||
$this->sharingBackend->unshare(
|
||||
shareable: $calendar,
|
||||
principalUri: 'principals/users/bob'
|
||||
);
|
||||
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
$this->assertCount(1, $this->sharingService->getUnshares(10001));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the functionality of sharing a calendar with a user, then with a group (that includes the shared user),
|
||||
* and subsequently unsharing it from the individual user. Verifies that the unshare operation correctly removes the specific user share
|
||||
* without creating an additional unshare entry.
|
||||
*/
|
||||
public function testShareCalendarWithUserThenGroupThenUnshareUser(): void {
|
||||
$calendar = $this->createMock(Calendar::class);
|
||||
$calendar->method('getResourceId')
|
||||
->willReturn(10001);
|
||||
$calendar->method('getOwner')
|
||||
->willReturn('principals/users/admin');
|
||||
|
||||
$this->principalBackend->method('findByUri')
|
||||
->willReturnMap([
|
||||
['principals/groups/alice_bob', '', 'principals/groups/alice_bob'],
|
||||
['principals/users/bob', '', 'principals/users/bob'],
|
||||
]);
|
||||
$this->principalBackend->method('getGroupMembership')
|
||||
->willReturn([
|
||||
'principals/groups/alice_bob',
|
||||
]);
|
||||
$this->principalBackend->method('getCircleMembership')
|
||||
->willReturn([]);
|
||||
|
||||
$this->userManager->method('userExists')
|
||||
->willReturn(true);
|
||||
$this->groupManager->method('groupExists')
|
||||
->willReturn(true);
|
||||
|
||||
/*
|
||||
* Step 1) The owner shares the calendar with a user.
|
||||
*/
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [['href' => 'principals/users/bob']],
|
||||
remove: [],
|
||||
);
|
||||
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
|
||||
/*
|
||||
* Step 2) The owner shares the calendar with a group that includes the
|
||||
* user from step 1 as a member.
|
||||
*/
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [['href' => 'principals/groups/alice_bob']],
|
||||
remove: [],
|
||||
);
|
||||
|
||||
$this->assertCount(2, $this->sharingService->getShares(10001));
|
||||
|
||||
/*
|
||||
* Step 3) Unshare the calendar from user as owner.
|
||||
*/
|
||||
$this->sharingBackend->updateShares(
|
||||
shareable: $calendar,
|
||||
add: [],
|
||||
remove: ['principals/users/bob'],
|
||||
);
|
||||
|
||||
/*
|
||||
* The purpose of this test is to ensure that removing a user from a share, as the owner, does not result in an "unshare" row being added.
|
||||
* Instead, the actual user share should be removed.
|
||||
*/
|
||||
$this->assertCount(1, $this->sharingService->getShares(10001));
|
||||
$this->assertCount(0, $this->sharingService->getUnshares(10001));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\DAV\Tests\Command;
|
||||
|
||||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\Command\ListCalendarShares;
|
||||
use OCA\DAV\Connector\Sabre\Principal;
|
||||
use OCA\DAV\DAV\Sharing\SharingMapper;
|
||||
use OCP\IUserManager;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Test\TestCase;
|
||||
|
||||
class ListCalendarSharesTest extends TestCase {
|
||||
|
||||
private IUserManager&MockObject $userManager;
|
||||
private Principal&MockObject $principal;
|
||||
private CalDavBackend&MockObject $caldav;
|
||||
private SharingMapper $sharingMapper;
|
||||
private ListCalendarShares $command;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->principal = $this->createMock(Principal::class);
|
||||
$this->caldav = $this->createMock(CalDavBackend::class);
|
||||
$this->sharingMapper = $this->createMock(SharingMapper::class);
|
||||
|
||||
$this->command = new ListCalendarShares(
|
||||
$this->userManager,
|
||||
$this->principal,
|
||||
$this->caldav,
|
||||
$this->sharingMapper,
|
||||
);
|
||||
}
|
||||
|
||||
public function testUserUnknown(): void {
|
||||
$user = 'bob';
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage("User $user is unknown");
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($user)
|
||||
->willReturn(false);
|
||||
|
||||
$commandTester = new CommandTester($this->command);
|
||||
$commandTester->execute([
|
||||
'uid' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testPrincipalNotFound(): void {
|
||||
$user = 'bob';
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage("Unable to fetch principal for user $user");
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($user)
|
||||
->willReturn(true);
|
||||
|
||||
$this->principal->expects($this->once())
|
||||
->method('getPrincipalByPath')
|
||||
->with('principals/users/' . $user)
|
||||
->willReturn(null);
|
||||
|
||||
$commandTester = new CommandTester($this->command);
|
||||
$commandTester->execute([
|
||||
'uid' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNoCalendarShares(): void {
|
||||
$user = 'bob';
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($user)
|
||||
->willReturn(true);
|
||||
|
||||
$this->principal->expects($this->once())
|
||||
->method('getPrincipalByPath')
|
||||
->with('principals/users/' . $user)
|
||||
->willReturn([
|
||||
'uri' => 'principals/users/' . $user,
|
||||
]);
|
||||
|
||||
$this->principal->expects($this->once())
|
||||
->method('getGroupMembership')
|
||||
->willReturn([]);
|
||||
$this->principal->expects($this->once())
|
||||
->method('getCircleMembership')
|
||||
->willReturn([]);
|
||||
|
||||
$this->sharingMapper->expects($this->once())
|
||||
->method('getSharesByPrincipals')
|
||||
->willReturn([]);
|
||||
|
||||
$commandTester = new CommandTester($this->command);
|
||||
$commandTester->execute([
|
||||
'uid' => $user,
|
||||
]);
|
||||
|
||||
$this->assertStringContainsString(
|
||||
"User $user has no calendar shares",
|
||||
$commandTester->getDisplay()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilterByCalendarId(): void {
|
||||
$user = 'bob';
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($user)
|
||||
->willReturn(true);
|
||||
|
||||
$this->principal->expects($this->once())
|
||||
->method('getPrincipalByPath')
|
||||
->with('principals/users/' . $user)
|
||||
->willReturn([
|
||||
'uri' => 'principals/users/' . $user,
|
||||
]);
|
||||
|
||||
$this->principal->expects($this->once())
|
||||
->method('getGroupMembership')
|
||||
->willReturn([]);
|
||||
$this->principal->expects($this->once())
|
||||
->method('getCircleMembership')
|
||||
->willReturn([]);
|
||||
|
||||
$this->sharingMapper->expects($this->once())
|
||||
->method('getSharesByPrincipals')
|
||||
->willReturn([
|
||||
[
|
||||
'id' => 1000,
|
||||
'principaluri' => 'principals/users/bob',
|
||||
'type' => 'calendar',
|
||||
'access' => 2,
|
||||
'resourceid' => 10
|
||||
],
|
||||
[
|
||||
'id' => 1001,
|
||||
'principaluri' => 'principals/users/bob',
|
||||
'type' => 'calendar',
|
||||
'access' => 3,
|
||||
'resourceid' => 11
|
||||
],
|
||||
]);
|
||||
|
||||
$commandTester = new CommandTester($this->command);
|
||||
$commandTester->execute([
|
||||
'uid' => $user,
|
||||
'--calendar-id' => 10,
|
||||
]);
|
||||
|
||||
$this->assertStringNotContainsString(
|
||||
'1001',
|
||||
$commandTester->getDisplay()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\DAV\Tests\unit\DAV\Sharing;
|
||||
|
||||
use OCA\DAV\CalDAV\Sharing\Service;
|
||||
use OCA\DAV\DAV\Sharing\SharingMapper;
|
||||
use OCA\DAV\DAV\Sharing\SharingService;
|
||||
use Test\TestCase;
|
||||
|
||||
class SharingServiceTest extends TestCase {
|
||||
|
||||
private SharingService $service;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->service = new Service($this->createMock(SharingMapper::class));
|
||||
}
|
||||
|
||||
public function testHasGroupShare(): void {
|
||||
$oldShares = [
|
||||
[
|
||||
'href' => 'principal:principals/groups/bob',
|
||||
'commonName' => 'bob',
|
||||
'status' => 1,
|
||||
'readOnly' => true,
|
||||
'{http://owncloud.org/ns}principal' => 'principals/groups/bob',
|
||||
'{http://owncloud.org/ns}group-share' => true,
|
||||
],
|
||||
[
|
||||
'href' => 'principal:principals/users/bob',
|
||||
'commonName' => 'bob',
|
||||
'status' => 1,
|
||||
'readOnly' => true,
|
||||
'{http://owncloud.org/ns}principal' => 'principals/users/bob',
|
||||
'{http://owncloud.org/ns}group-share' => false,
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertTrue($this->service->hasGroupShare($oldShares));
|
||||
|
||||
$oldShares = [
|
||||
[
|
||||
'href' => 'principal:principals/users/bob',
|
||||
'commonName' => 'bob',
|
||||
'status' => 1,
|
||||
'readOnly' => true,
|
||||
'{http://owncloud.org/ns}principal' => 'principals/users/bob',
|
||||
'{http://owncloud.org/ns}group-share' => false,
|
||||
]
|
||||
];
|
||||
$this->assertFalse($this->service->hasGroupShare($oldShares));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue