Compare commits

...

1 Commits

Author SHA1 Message Date
Thomas Citharel 02e4b05644
Allow to have multiple links per public calendar
Adding a public link is still the old way:

```xml
<o:publish-calendar xmlns:o="http://calendarserver.org/ns/"/>
```

Removing all public links is just like we used to unpublish
```xml
<o:unpublish-calendar xmlns:o="http://calendarserver.org/ns/"/>
```

We now have the following for unpublishing a specific link
```xml
<o:unpublish-calendar xmlns:o="http://nextcloud.com/ns/">urltounpublish</o:unpublish-calendar>
```

The public URLs are exposed this way:
```xml
<x1:publish-urls xmlns:d="DAV:" xmlns:x1="http://nextcloud.com/ns/">
	<d:href>urltopublish</d:href>
	<d:href>secondurltopublish</d:href>
</x1:publish-urls>
```

`publish-url` is still available and give the first URL
```xml
<x1:publish-url xmlns:d="DAV:" xmlns:x1="http://calendarserver.org/ns/">
	<d:href>urltopublish</d:href>
</x1:publish-url>
```

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
2020-03-28 18:25:20 +01:00
8 changed files with 254 additions and 127 deletions

View File

@ -2339,47 +2339,82 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
} }
/** /**
* @param boolean $value * @param Calendar $calendar
* @param \OCA\DAV\CalDAV\Calendar $calendar * @return string
* @return string|null
*/ */
public function setPublishStatus($value, $calendar) { public function addPublicLink(Calendar $calendar): string {
$calendarId = $calendar->getResourceId(); $calendarId = $calendar->getResourceId();
$publicUri = $this->random->generate(16, ISecureRandom::CHAR_HUMAN_READABLE);
$this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent( $this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent(
'\OCA\DAV\CalDAV\CalDavBackend::updateShares', '\OCA\DAV\CalDAV\CalDavBackend::addPublicLink',
[ [
'calendarId' => $calendarId, 'calendarId' => $calendarId,
'calendarData' => $this->getCalendarById($calendarId), 'calendarData' => $this->getCalendarById($calendarId),
'public' => $value, 'publicuri' => $publicUri,
])); ]));
$query = $this->db->getQueryBuilder(); $query = $this->db->getQueryBuilder();
if ($value) { $query->insert('dav_shares')
$publicUri = $this->random->generate(16, ISecureRandom::CHAR_HUMAN_READABLE); ->values([
$query->insert('dav_shares') 'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()),
->values([ 'type' => $query->createNamedParameter('calendar'),
'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()), 'access' => $query->createNamedParameter(self::ACCESS_PUBLIC),
'type' => $query->createNamedParameter('calendar'), 'resourceid' => $query->createNamedParameter($calendar->getResourceId()),
'access' => $query->createNamedParameter(self::ACCESS_PUBLIC), 'publicuri' => $query->createNamedParameter($publicUri)
'resourceid' => $query->createNamedParameter($calendar->getResourceId()), ]);
'publicuri' => $query->createNamedParameter($publicUri)
]);
$query->execute();
return $publicUri;
}
$query->delete('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
$query->execute(); $query->execute();
return null; return $publicUri;
} }
/** /**
* @param \OCA\DAV\CalDAV\Calendar $calendar * @param Calendar $calendar
* @return mixed * @param string $publicUri
*/ */
public function getPublishStatus($calendar) { public function removePublicLink(Calendar $calendar, string $publicUri) {
$calendarId = $calendar->getResourceId();
$this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent(
'\OCA\DAV\CalDAV\CalDavBackend::removePublicLinks',
[
'calendarId' => $calendarId,
'calendarData' => $this->getCalendarById($calendarId),
'publicuri' => $publicUri
]));
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('publicuri', $query->createNamedParameter($publicUri)))
->andWhere($query->expr()->eq('resourceid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
$query->execute();
}
/**
* @param Calendar $calendar
*/
public function removeAllPublicLinks(Calendar $calendar) {
$calendarId = $calendar->getResourceId();
$this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent(
'\OCA\DAV\CalDAV\CalDavBackend::removeAllPublicLinks',
[
'calendarId' => $calendarId,
'calendarData' => $this->getCalendarById($calendarId),
]));
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
$query->execute();
}
/**
* @param Calendar $calendar
* @return array
*/
public function getPublicURIs($calendar): array {
$query = $this->db->getQueryBuilder(); $query = $this->db->getQueryBuilder();
$result = $query->select('publicuri') $result = $query->select('publicuri')
->from('dav_shares') ->from('dav_shares')
@ -2387,9 +2422,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC))) ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
->execute(); ->execute();
$row = $result->fetch(); return $result->fetchAll(\PDO::FETCH_ASSOC);
$result->closeCursor();
return $row ? reset($row) : false;
} }
/** /**

View File

@ -350,21 +350,32 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
return $uris; return $uris;
} }
/** public function addPublicLink() {
* @param boolean $value $publicUri = $this->caldavBackend->addPublicLink($this);
* @return string|null $this->calendarInfo['publicuris'][] = $publicUri;
*/
public function setPublishStatus($value) {
$publicUri = $this->caldavBackend->setPublishStatus($value, $this);
$this->calendarInfo['publicuri'] = $publicUri;
return $publicUri; return $publicUri;
} }
public function removePublicLink(string $publicUri) {
$this->caldavBackend->removePublicLink($this, $publicUri);
}
public function removeAllPublicLinks() {
$this->caldavBackend->removeAllPublicLinks($this);
}
/** /**
* @return mixed $value * @return bool $value
*/ */
public function getPublishStatus() { public function getPublishStatus(): bool {
return $this->caldavBackend->getPublishStatus($this); return count($this->getPublicURIs()) > 0;
}
/**
* @return mixed
*/
public function getPublicURIs() : array {
return array_map(function ($publicURI) { return $publicURI['publicuri']; }, $this->caldavBackend->getPublicURIs($this));
} }
public function canWrite() { public function canWrite() {

View File

@ -41,6 +41,7 @@ use Sabre\HTTP\ResponseInterface;
class PublishPlugin extends ServerPlugin { class PublishPlugin extends ServerPlugin {
const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
const NS_NEXTCLOUD = 'http://nextcloud.com/ns/';
/** /**
* Reference to SabreDAV server object. * Reference to SabreDAV server object.
@ -121,10 +122,22 @@ class PublishPlugin extends ServerPlugin {
$propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) { $propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) {
if ($node->getPublishStatus()) { if ($node->getPublishStatus()) {
// We return the publish-url only if the calendar is published. // We return the publish-url only if the calendar is published.
$token = $node->getPublishStatus(); $token = reset($node->getPublicURIs());
$publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token; $publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token;
return new Publisher($publishUrl, true); return new Publisher([$publishUrl => true]);
}
});
$propFind->handle('{'.self::NS_NEXTCLOUD.'}publish-urls', function () use ($node) {
if ($node->getPublishStatus()) {
// We return the publish-url only if the calendar is published.
$tokens = $node->getPublicURIs();
$publishUrls = array_map(function ($token) {
return [$this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token => true];
}, $tokens);
return new Publisher($publishUrls);
} }
}); });
@ -172,65 +185,90 @@ class PublishPlugin extends ServerPlugin {
// re-populated the request body with the existing data. // re-populated the request body with the existing data.
$request->setBody($requestBody); $request->setBody($requestBody);
$this->server->xml->parse($requestBody, $request->getUrl(), $documentType); $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
switch ($documentType) { switch ($documentType) {
case '{'.self::NS_CALENDARSERVER.'}publish-calendar' : case '{'.self::NS_CALENDARSERVER.'}publish-calendar' :
// We can only deal with IShareableCalendar objects // We can only deal with IShareableCalendar objects
if (!$node instanceof Calendar) { if (!$node instanceof Calendar) {
return; return;
} }
$this->server->transactionType = 'post-publish-calendar'; $this->server->transactionType = 'post-publish-calendar';
// Getting ACL info // Getting ACL info
$acl = $this->server->getPlugin('acl'); $acl = $this->server->getPlugin('acl');
// If there's no ACL support, we allow everything // If there's no ACL support, we allow everything
if ($acl) { if ($acl) {
$acl->checkPrivileges($path, '{DAV:}write'); $acl->checkPrivileges($path, '{DAV:}write');
} }
$node->setPublishStatus(true); $node->addPublicLink();
// iCloud sends back the 202, so we will too. // iCloud sends back the 202, so we will too.
$response->setStatus(202); $response->setStatus(202);
// Adding this because sending a response body may cause issues, // Adding this because sending a response body may cause issues,
// and I wanted some type of indicator the response was handled. // and I wanted some type of indicator the response was handled.
$response->setHeader('X-Sabre-Status', 'everything-went-well'); $response->setHeader('X-Sabre-Status', 'everything-went-well');
// Breaking the event chain // Breaking the event chain
return false; return false;
case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' : case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' :
// We can only deal with IShareableCalendar objects // We can only deal with IShareableCalendar objects
if (!$node instanceof Calendar) { if (!$node instanceof Calendar) {
return; return;
} }
$this->server->transactionType = 'post-unpublish-calendar'; $this->server->transactionType = 'post-unpublish-all-calendars';
// Getting ACL info // Getting ACL info
$acl = $this->server->getPlugin('acl'); $acl = $this->server->getPlugin('acl');
// If there's no ACL support, we allow everything // If there's no ACL support, we allow everything
if ($acl) { if ($acl) {
$acl->checkPrivileges($path, '{DAV:}write'); $acl->checkPrivileges($path, '{DAV:}write');
} }
$node->setPublishStatus(false); $node->removeAllPublicLinks();
$response->setStatus(200); $response->setStatus(200);
// Adding this because sending a response body may cause issues, // Adding this because sending a response body may cause issues,
// and I wanted some type of indicator the response was handled. // and I wanted some type of indicator the response was handled.
$response->setHeader('X-Sabre-Status', 'everything-went-well'); $response->setHeader('X-Sabre-Status', 'everything-went-well');
// Breaking the event chain // Breaking the event chain
return false; return false;
case '{'.self::NS_NEXTCLOUD.'}unpublish-calendar' :
// We can only deal with IShareableCalendar objects
if (!$node instanceof Calendar) {
return;
}
$this->server->transactionType = 'post-unpublish-calendar';
// Getting ACL info
$acl = $this->server->getPlugin('acl');
// If there's no ACL support, we allow everything
if ($acl) {
$acl->checkPrivileges($path, '{DAV:}write');
}
$node->removePublicLink($message);
$response->setStatus(200);
// Adding this because sending a response body may cause issues,
// and I wanted some type of indicator the response was handled.
$response->setHeader('X-Sabre-Status', 'everything-went-well');
// Breaking the event chain
return false;
} }
} }
} }

View File

@ -30,33 +30,26 @@ use Sabre\Xml\XmlSerializable;
class Publisher implements XmlSerializable { class Publisher implements XmlSerializable {
/** /**
* @var string $publishUrl * @var string $publishUrls
*/ */
protected $publishUrl; protected $publishUrls;
/** /**
* @var boolean $isPublished * @param array $publishUrls
*/ */
protected $isPublished; function __construct(array $publishUrls) {
$this->publishUrls = $publishUrls;
/**
* @param string $publishUrl
* @param boolean $isPublished
*/
function __construct($publishUrl, $isPublished) {
$this->publishUrl = $publishUrl;
$this->isPublished = $isPublished;
} }
/** /**
* @return string * @return array
*/ */
function getValue() { function getValue(): array {
return $this->publishUrl; return array_keys($this->publishUrls);
} }
/** /**
* The xmlSerialize metod is called during xml writing. * The xmlSerialize method is called during xml writing.
* *
* Use the $writer argument to write its own xml serialization. * Use the $writer argument to write its own xml serialization.
* *
@ -75,12 +68,13 @@ class Publisher implements XmlSerializable {
* @return void * @return void
*/ */
function xmlSerialize(Writer $writer) { function xmlSerialize(Writer $writer) {
if (!$this->isPublished) { foreach ($this->publishUrls as $publishUrl => $isPublished)
if (!$isPublished) {
// for pre-publish-url // for pre-publish-url
$writer->write($this->publishUrl); $writer->write($publishUrl);
} else { } else {
// for publish-url // for publish-url
$writer->writeElement('{DAV:}href', $this->publishUrl); $writer->writeElement('{DAV:}href', $publishUrl);
} }
} }
} }

View File

@ -34,6 +34,7 @@ use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar; use OCA\DAV\CalDAV\Calendar;
use OCP\IConfig; use OCP\IConfig;
use OCP\IL10N; use OCP\IL10N;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound; use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch; use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href; use Sabre\DAV\Xml\Property\Href;
@ -280,7 +281,7 @@ EOD;
$this->assertCount(0, $calendarObjects); $this->assertCount(0, $calendarObjects);
} }
public function testMultipleCalendarObjectsWithSameUID() { public function testMultipleCalendarObjectsWithSameUID() {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class); $this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Calendar object with uid already exists in this calendar collection.'); $this->expectExceptionMessage('Calendar object with uid already exists in this calendar collection.');
@ -508,12 +509,12 @@ EOD;
$calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0]; $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject $l10n */ /** @var IL10N|MockObject $l10n */
$l10n = $this->createMock(IL10N::class); $l10n = $this->createMock(IL10N::class);
$config = $this->createMock(IConfig::class); $config = $this->createMock(IConfig::class);
$calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config); $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config);
$calendar->setPublishStatus(true); $calendar->addPublicLink();
$this->assertNotEquals(false, $calendar->getPublishStatus()); $this->assertNotEquals(false, $calendar->getPublishStatus());
$publicCalendars = $this->backend->getPublicCalendars(); $publicCalendars = $this->backend->getPublicCalendars();
@ -525,11 +526,24 @@ EOD;
$publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI); $publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI);
$this->assertEquals(true, $publicCalendar['{http://owncloud.org/ns}public']); $this->assertEquals(true, $publicCalendar['{http://owncloud.org/ns}public']);
$calendar->setPublishStatus(false); $calendar->addPublicLink();
$publicCalendarURIs = $this->backend->getPublicURIs($calendar);
$this->assertCount(2, $publicCalendarURIs);
$publicCalendarURI2 = $publicCalendarURIs[1]['publicuri'];
$publicCalendar2 = $this->backend->getPublicCalendar($publicCalendarURI2);
$this->assertEquals(true, $publicCalendar2['{http://owncloud.org/ns}public']);
$calendar->removePublicLink($publicCalendarURI2);
$publicCalendarURIs = $this->backend->getPublicURIs($calendar);
$this->assertCount(1, $publicCalendarURIs);
$calendar->removeAllPublicLinks();
$this->assertEquals(false, $calendar->getPublishStatus()); $this->assertEquals(false, $calendar->getPublishStatus());
$this->expectException(NotFound::class); $this->expectException(NotFound::class);
$this->backend->getPublicCalendar($publicCalendarURI); $this->backend->getPublicCalendar($publicCalendarURI);
$this->expectException(NotFound::class);
$this->backend->getPublicCalendar($publicCalendarURI2);
} }
public function testSubscriptions() { public function testSubscriptions() {
@ -607,21 +621,21 @@ DTSTART;TZID=Europe/Warsaw:20170325T150000
DTEND;TZID=Europe/Warsaw:20170325T160000 DTEND;TZID=Europe/Warsaw:20170325T160000
TRANSP:OPAQUE TRANSP:OPAQUE
DESCRIPTION:Magiczna treść uzyskana za pomocą magicznego proszku.\n\nę DESCRIPTION:Magiczna treść uzyskana za pomocą magicznego proszku.\n\nę
żźćńłóÓŻŹĆŁĘ€śśśŚŚ\n \,\,))))))))\;\,\n żźćńłóÓŻŹĆŁĘ€śśśŚŚ\n \,\,))))))))\;\,\n
__))))))))))))))\,\n \\|/ -\\(((((''''((((((((.\n -*-==/// __))))))))))))))\,\n \\|/ -\\(((((''''((((((((.\n -*-==///
///(('' . `))))))\,\n /|\\ ))| o \;-. '((((( ///(('' . `))))))\,\n /|\\ ))| o \;-. '(((((
\,(\,\n ( `| / ) \;))))' \,(\,\n ( `| / ) \;))))'
\,_))^\;(~\n | | | \,))((((_ _____- \,_))^\;(~\n | | | \,))((((_ _____-
-----~~~-. %\,\;(\;(>'\;'~\n o_)\; \; )))(((` ~--- -----~~~-. %\,\;(\;(>'\;'~\n o_)\; \; )))(((` ~---
~ `:: \\ %%~~)(v\;(`('~\n \; ''''```` ~ `:: \\ %%~~)(v\;(`('~\n \; ''''````
`: `:::|\\\,__\,%% )\;`'\; ~\n | _ `: `:::|\\\,__\,%% )\;`'\; ~\n | _
) / `:|`----' `-'\n ______/\\/~ | ) / `:|`----' `-'\n ______/\\/~ |
/ /\n /~\;\;.____/\;\;' / ___--\ / /\n /~\;\;.____/\;\;' / ___--\
,-( `\;\;\;/\n / // _\;______\;'------~~~~~ /\;\;/\\ /\n ,-( `\;\;\;/\n / // _\;______\;'------~~~~~ /\;\;/\\ /\n
// | | / \; \\\;\;\,\\\n (<_ | \; // | | / \; \\\;\;\,\\\n (<_ | \;
/'\,/-----' _>\n \\_| ||_ /'\,/-----' _>\n \\_| ||_
//~\;~~~~~~~~~\n `\\_| (\,~~ -Tua Xiong\n //~\;~~~~~~~~~\n `\\_| (\,~~ -Tua Xiong\n
\\~\\\n \\~\\\n
~~\n\n ~~\n\n
SEQUENCE:1 SEQUENCE:1
X-MOZ-GENERATION:1 X-MOZ-GENERATION:1

View File

@ -7,7 +7,7 @@
* @author Lukas Reschke <lukas@statuscode.ch> * @author Lukas Reschke <lukas@statuscode.ch>
* @author Morris Jobke <hey@morrisjobke.de> * @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl> * @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <tcit@tcit.fr> * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vinicius Cubas Brand <vinicius@eita.org.br> * @author Vinicius Cubas Brand <vinicius@eita.org.br>
* *
@ -41,6 +41,9 @@ use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
use OCP\IUserManager; use OCP\IUserManager;
use OCP\Security\ISecureRandom; use OCP\Security\ISecureRandom;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception;
use Sabre\DAV\Exception\NotFound;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase; use Test\TestCase;
@ -60,11 +63,11 @@ class PublicCalendarRootTest extends TestCase {
private $publicCalendarRoot; private $publicCalendarRoot;
/** @var IL10N */ /** @var IL10N */
private $l10n; private $l10n;
/** @var Principal|\PHPUnit_Framework_MockObject_MockObject */ /** @var Principal| MockObject */
private $principal; private $principal;
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ /** @var IUserManager| MockObject */
protected $userManager; protected $userManager;
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ /** @var IGroupManager| MockObject */
protected $groupManager; protected $groupManager;
/** @var IConfig */ /** @var IConfig */
protected $config; protected $config;
@ -157,13 +160,15 @@ class PublicCalendarRootTest extends TestCase {
/** /**
* @return Calendar * @return Calendar
* @throws Exception
* @throws NotFound
*/ */
protected function createPublicCalendar() { protected function createPublicCalendar() {
$this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []); $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
$calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0]; $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
$calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config); $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config);
$publicUri = $calendar->setPublishStatus(true); $publicUri = $calendar->addPublicLink();
$calendarInfo = $this->backend->getPublicCalendar($publicUri); $calendarInfo = $this->backend->getPublicCalendar($publicUri);
$calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config); $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config);

View File

@ -33,15 +33,16 @@ use Test\TestCase;
class PublisherTest extends TestCase { class PublisherTest extends TestCase {
const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
const NS_NEXTCLOUD = 'http://nextcloud.com/ns/';
public function testSerializePublished() { public function testSerializePublished() {
$publish = new Publisher('urltopublish', true); $publish = new Publisher(['urltopublish' => true]);
$xml = $this->write([ $xml = $this->write([
'{' . self::NS_CALENDARSERVER . '}publish-url' => $publish, '{' . self::NS_CALENDARSERVER . '}publish-url' => $publish,
]); ]);
$this->assertEquals('urltopublish', $publish->getValue()); $this->assertEquals(['urltopublish'], $publish->getValue());
$this->assertXmlStringEqualsXmlString( $this->assertXmlStringEqualsXmlString(
'<?xml version="1.0"?> '<?xml version="1.0"?>
@ -50,14 +51,31 @@ class PublisherTest extends TestCase {
</x1:publish-url>', $xml); </x1:publish-url>', $xml);
} }
public function testSerializeMultiplePublished() {
$publish = new Publisher(['urltopublish' => true, 'secondurltopublish' => true]);
$xml = $this->write([
'{' . self::NS_NEXTCLOUD . '}publish-urls' => $publish,
]);
$this->assertEquals(['urltopublish', 'secondurltopublish'], $publish->getValue());
$this->assertXmlStringEqualsXmlString(
'<?xml version="1.0"?>
<x1:publish-urls xmlns:d="DAV:" xmlns:x1="' . self::NS_NEXTCLOUD . '">
<d:href>urltopublish</d:href>
<d:href>secondurltopublish</d:href>
</x1:publish-urls>', $xml);
}
public function testSerializeNotPublished() { public function testSerializeNotPublished() {
$publish = new Publisher('urltopublish', false); $publish = new Publisher(['urltopublish' => false]);
$xml = $this->write([ $xml = $this->write([
'{' . self::NS_CALENDARSERVER . '}pre-publish-url' => $publish, '{' . self::NS_CALENDARSERVER . '}pre-publish-url' => $publish,
]); ]);
$this->assertEquals('urltopublish', $publish->getValue()); $this->assertEquals(['urltopublish'], $publish->getValue());
$this->assertXmlStringEqualsXmlString( $this->assertXmlStringEqualsXmlString(
'<?xml version="1.0"?> '<?xml version="1.0"?>

View File

@ -30,6 +30,7 @@ use OCA\DAV\CalDAV\Publishing\PublishPlugin;
use OCP\IConfig; use OCP\IConfig;
use OCP\IRequest; use OCP\IRequest;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server; use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection; use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request; use Sabre\HTTP\Request;
@ -42,11 +43,11 @@ class PluginTest extends TestCase {
private $plugin; private $plugin;
/** @var Server */ /** @var Server */
private $server; private $server;
/** @var Calendar | \PHPUnit_Framework_MockObject_MockObject */ /** @var Calendar | MockObject */
private $book; private $book;
/** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */ /** @var IConfig | MockObject */
private $config; private $config;
/** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */ /** @var IURLGenerator | MockObject */
private $urlGenerator; private $urlGenerator;
protected function setUp(): void { protected function setUp(): void {
@ -79,7 +80,7 @@ class PluginTest extends TestCase {
public function testPublishing() { public function testPublishing() {
$this->book->expects($this->once())->method('setPublishStatus')->with(true); $this->book->expects($this->once())->method('addPublicLink')->with();
// setup request // setup request
$request = new Request(); $request = new Request();
@ -92,7 +93,7 @@ class PluginTest extends TestCase {
public function testUnPublishing() { public function testUnPublishing() {
$this->book->expects($this->once())->method('setPublishStatus')->with(false); $this->book->expects($this->once())->method('removeAllPublicLinks')->with();
// setup request // setup request
$request = new Request(); $request = new Request();
@ -102,4 +103,17 @@ class PluginTest extends TestCase {
$response = new Response(); $response = new Response();
$this->plugin->httpPost($request, $response); $this->plugin->httpPost($request, $response);
} }
public function testUnPublishingALink() {
$this->book->expects($this->once())->method('removePublicLink')->with('urltounpublish');
// setup request
$request = new Request();
$request->addHeader('Content-Type', 'application/xml');
$request->setUrl('cal1');
$request->setBody('<o:unpublish-calendar xmlns:o="http://nextcloud.com/ns/">urltounpublish</o:unpublish-calendar>');
$response = new Response();
$this->plugin->httpPost($request, $response);
}
} }