Skip to content

Commit 0d28b60

Browse files
authored
Merge pull request #11979 from nextcloud/bugfix-stable14/noid/forbid_freebusy_but_allow_local_delivery
[stable14] allow local delivery of schedule message while prohibiting FreeBusy requests
2 parents d9c0801 + 4bbd3fa commit 0d28b60

File tree

7 files changed

+304
-107
lines changed

7 files changed

+304
-107
lines changed

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
'OCA\\DAV\\CalDAV\\CalendarObject' => $baseDir . '/../lib/CalDAV/CalendarObject.php',
3636
'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php',
3737
'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => $baseDir . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php',
38+
'OCA\\DAV\\CalDAV\\Outbox' => $baseDir . '/../lib/CalDAV/Outbox.php',
3839
'OCA\\DAV\\CalDAV\\Plugin' => $baseDir . '/../lib/CalDAV/Plugin.php',
3940
'OCA\\DAV\\CalDAV\\Principal\\Collection' => $baseDir . '/../lib/CalDAV/Principal/Collection.php',
4041
'OCA\\DAV\\CalDAV\\Principal\\User' => $baseDir . '/../lib/CalDAV/Principal/User.php',

apps/dav/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class ComposerStaticInitDAV
5050
'OCA\\DAV\\CalDAV\\CalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarObject.php',
5151
'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php',
5252
'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => __DIR__ . '/..' . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php',
53+
'OCA\\DAV\\CalDAV\\Outbox' => __DIR__ . '/..' . '/../lib/CalDAV/Outbox.php',
5354
'OCA\\DAV\\CalDAV\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Plugin.php',
5455
'OCA\\DAV\\CalDAV\\Principal\\Collection' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/Collection.php',
5556
'OCA\\DAV\\CalDAV\\Principal\\User' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/User.php',

apps/dav/lib/CalDAV/CalendarHome.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
use Sabre\CalDAV\Backend\SchedulingSupport;
3030
use Sabre\CalDAV\Backend\SubscriptionSupport;
3131
use Sabre\CalDAV\Schedule\Inbox;
32-
use Sabre\CalDAV\Schedule\Outbox;
3332
use Sabre\CalDAV\Subscriptions\Subscription;
3433
use Sabre\DAV\Exception\NotFound;
3534
use Sabre\DAV\Exception\MethodNotAllowed;
@@ -81,7 +80,7 @@ function getChildren() {
8180

8281
if ($this->caldavBackend instanceof SchedulingSupport) {
8382
$objects[] = new Inbox($this->caldavBackend, $this->principalInfo['uri']);
84-
$objects[] = new Outbox($this->principalInfo['uri']);
83+
$objects[] = new Outbox($this->config, $this->principalInfo['uri']);
8584
}
8685

8786
// We're adding a notifications node, if it's supported by the backend.
@@ -108,7 +107,7 @@ function getChild($name) {
108107
return new Inbox($this->caldavBackend, $this->principalInfo['uri']);
109108
}
110109
if ($name === 'outbox' && $this->caldavBackend instanceof SchedulingSupport) {
111-
return new Outbox($this->principalInfo['uri']);
110+
return new Outbox($this->config, $this->principalInfo['uri']);
112111
}
113112
if ($name === 'notifications' && $this->caldavBackend instanceof NotificationSupport) {
114113
return new \Sabre\CalDAv\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);

apps/dav/lib/CalDAV/Outbox.php

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<?php
2+
/**
3+
* @copyright Copyright (c) 2018, Georg Ehrke
4+
*
5+
* @author Georg Ehrke <[email protected]>
6+
*
7+
* @license AGPL-3.0
8+
*
9+
* This code is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License, version 3,
11+
* as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License, version 3,
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>
20+
*
21+
*/
22+
namespace OCA\DAV\CalDAV;
23+
24+
use OCP\IConfig;
25+
use Sabre\CalDAV\Plugin as CalDAVPlugin;
26+
27+
/**
28+
* Class Outbox
29+
*
30+
* @package OCA\DAV\CalDAV
31+
*/
32+
class Outbox extends \Sabre\CalDAV\Schedule\Outbox {
33+
34+
/** @var IConfig */
35+
private $config;
36+
37+
/** @var null|bool */
38+
private $disableFreeBusy = null;
39+
40+
/**
41+
* Outbox constructor.
42+
*
43+
* @param IConfig $config
44+
* @param string $principalUri
45+
*/
46+
public function __construct(IConfig $config, string $principalUri) {
47+
parent::__construct($principalUri);
48+
$this->config = $config;
49+
}
50+
51+
/**
52+
* Returns a list of ACE's for this node.
53+
*
54+
* Each ACE has the following properties:
55+
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
56+
* currently the only supported privileges
57+
* * 'principal', a url to the principal who owns the node
58+
* * 'protected' (optional), indicating that this ACE is not allowed to
59+
* be updated.
60+
*
61+
* @return array
62+
*/
63+
function getACL() {
64+
// getACL is called so frequently that we cache the config result
65+
if ($this->disableFreeBusy === null) {
66+
$this->disableFreeBusy = ($this->config->getAppValue('dav', 'disableFreeBusy', 'no') === 'yes');
67+
}
68+
69+
$commonAcl = [
70+
[
71+
'privilege' => '{DAV:}read',
72+
'principal' => $this->getOwner(),
73+
'protected' => true,
74+
],
75+
[
76+
'privilege' => '{DAV:}read',
77+
'principal' => $this->getOwner() . '/calendar-proxy-read',
78+
'protected' => true,
79+
],
80+
[
81+
'privilege' => '{DAV:}read',
82+
'principal' => $this->getOwner() . '/calendar-proxy-write',
83+
'protected' => true,
84+
],
85+
];
86+
87+
// schedule-send is an aggregate privilege for:
88+
// - schedule-send-invite
89+
// - schedule-send-reply
90+
// - schedule-send-freebusy
91+
//
92+
// If FreeBusy is disabled, we have to remove the latter privilege
93+
94+
if ($this->disableFreeBusy) {
95+
return array_merge($commonAcl, [
96+
[
97+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-invite',
98+
'principal' => $this->getOwner(),
99+
'protected' => true,
100+
],
101+
[
102+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-invite',
103+
'principal' => $this->getOwner() . '/calendar-proxy-write',
104+
'protected' => true,
105+
],
106+
[
107+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-reply',
108+
'principal' => $this->getOwner(),
109+
'protected' => true,
110+
],
111+
[
112+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-reply',
113+
'principal' => $this->getOwner() . '/calendar-proxy-write',
114+
'protected' => true,
115+
],
116+
]);
117+
}
118+
119+
return array_merge($commonAcl, [
120+
[
121+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send',
122+
'principal' => $this->getOwner(),
123+
'protected' => true,
124+
],
125+
[
126+
'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send',
127+
'principal' => $this->getOwner() . '/calendar-proxy-write',
128+
'protected' => true,
129+
],
130+
]);
131+
}
132+
}

apps/dav/lib/Connector/Sabre/Principal.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,9 @@ function updatePrincipal($path, PropPatch $propPatch) {
212212
protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
213213
$results = [];
214214

215-
// If sharing is disabled (or FreeBusy was disabled on purpose), return the empty array
215+
// If sharing is disabled, return the empty array
216216
$shareAPIEnabled = $this->shareManager->shareApiEnabled();
217-
$disableFreeBusy = $this->config->getAppValue('dav', 'disableFreeBusy', $shareAPIEnabled ? 'no' : 'yes');
218-
if ($disableFreeBusy === 'yes') {
217+
if (!$shareAPIEnabled) {
219218
return [];
220219
}
221220

@@ -298,10 +297,9 @@ function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof')
298297
* @return string
299298
*/
300299
function findByUri($uri, $principalPrefix) {
301-
// If sharing is disabled (or FreeBusy was disabled on purpose), return the empty array
300+
// If sharing is disabled, return the empty array
302301
$shareAPIEnabled = $this->shareManager->shareApiEnabled();
303-
$disableFreeBusy = $this->config->getAppValue('dav', 'disableFreeBusy', $shareAPIEnabled ? 'no' : 'yes');
304-
if ($disableFreeBusy === 'yes') {
302+
if (!$shareAPIEnabled) {
305303
return null;
306304
}
307305

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
/**
3+
* @copyright Copyright (c) 2018, Georg Ehrke
4+
*
5+
* @author Georg Ehrke <[email protected]>
6+
*
7+
* @license AGPL-3.0
8+
*
9+
* This code is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License, version 3,
11+
* as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License, version 3,
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>
20+
*
21+
*/
22+
23+
namespace OCA\DAV\Tests\unit\CalDAV;
24+
25+
use OCA\DAV\CalDAV\Outbox;
26+
use OCP\IConfig;
27+
use Test\TestCase;
28+
29+
class OutboxTest extends TestCase {
30+
31+
/** @var IConfig */
32+
private $config;
33+
34+
/** @var Outbox */
35+
private $outbox;
36+
37+
protected function setUp() {
38+
parent::setUp();
39+
40+
$this->config = $this->createMock(IConfig::class);
41+
$this->outbox = new Outbox($this->config, 'user-principal-123');
42+
}
43+
44+
public function testGetACLFreeBusyEnabled() {
45+
$this->config->expects($this->once())
46+
->method('getAppValue')
47+
->with('dav', 'disableFreeBusy', 'no')
48+
->will($this->returnValue('no'));
49+
50+
$this->assertEquals([
51+
[
52+
'privilege' => '{DAV:}read',
53+
'principal' => 'user-principal-123',
54+
'protected' => true,
55+
],
56+
[
57+
'privilege' => '{DAV:}read',
58+
'principal' => 'user-principal-123/calendar-proxy-read',
59+
'protected' => true,
60+
],
61+
[
62+
'privilege' => '{DAV:}read',
63+
'principal' => 'user-principal-123/calendar-proxy-write',
64+
'protected' => true,
65+
],
66+
[
67+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send',
68+
'principal' => 'user-principal-123',
69+
'protected' => true,
70+
],
71+
[
72+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send',
73+
'principal' => 'user-principal-123/calendar-proxy-write',
74+
'protected' => true,
75+
],
76+
], $this->outbox->getACL());
77+
}
78+
79+
public function testGetACLFreeBusyDisabled() {
80+
$this->config->expects($this->once())
81+
->method('getAppValue')
82+
->with('dav', 'disableFreeBusy', 'no')
83+
->will($this->returnValue('yes'));
84+
85+
$this->assertEquals([
86+
[
87+
'privilege' => '{DAV:}read',
88+
'principal' => 'user-principal-123',
89+
'protected' => true,
90+
],
91+
[
92+
'privilege' => '{DAV:}read',
93+
'principal' => 'user-principal-123/calendar-proxy-read',
94+
'protected' => true,
95+
],
96+
[
97+
'privilege' => '{DAV:}read',
98+
'principal' => 'user-principal-123/calendar-proxy-write',
99+
'protected' => true,
100+
],
101+
[
102+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-invite',
103+
'principal' => 'user-principal-123',
104+
'protected' => true,
105+
],
106+
[
107+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-invite',
108+
'principal' => 'user-principal-123/calendar-proxy-write',
109+
'protected' => true,
110+
],
111+
[
112+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-reply',
113+
'principal' => 'user-principal-123',
114+
'protected' => true,
115+
],
116+
[
117+
'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-reply',
118+
'principal' => 'user-principal-123/calendar-proxy-write',
119+
'protected' => true,
120+
],
121+
], $this->outbox->getACL());
122+
}
123+
}

0 commit comments

Comments
 (0)