Browse Source

Fix carddav sharing plugin + adding unit tests

tags/v9.0beta1
Thomas Müller 8 years ago
parent
commit
aac06a33f1

+ 1
- 2
apps/dav/lib/carddav/carddavbackend.php View File

@@ -800,8 +800,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @param string $element
*/
private function unshare($addressBookUri, $element) {
$user = $element['href'];
$parts = explode(':', $user, 2);
$parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
}

+ 18
- 60
apps/dav/lib/carddav/sharing/plugin.php View File

@@ -9,11 +9,24 @@ use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\XMLUtil;
use Sabre\DAVACL\IACL;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;

class Plugin extends ServerPlugin {

/** @var Auth */
private $auth;

/** @var IRequest */
private $request;

/**
* Plugin constructor.
*
* @param Auth $authBackEnd
* @param IRequest $request
*/
public function __construct(Auth $authBackEnd, IRequest $request) {
$this->auth = $authBackEnd;
$this->request = $request;
@@ -68,6 +81,7 @@ class Plugin extends ServerPlugin {
function initialize(Server $server) {
$this->server = $server;
$server->resourceTypeMapping['OCA\\DAV\CardDAV\\ISharedAddressbook'] = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}shared';
$this->server->xml->elementMap['{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share'] = 'OCA\\DAV\\CardDAV\\Sharing\\Xml\\ShareRequest';

$this->server->on('method:POST', [$this, 'httpPost']);
}
@@ -109,9 +123,7 @@ class Plugin extends ServerPlugin {
// re-populated the request body with the existing data.
$request->setBody($requestBody);

$dom = XMLUtil::loadDOMDocument($requestBody);

$documentType = XMLUtil::toClarkNotation($dom->firstChild);
$message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);

switch ($documentType) {

@@ -124,19 +136,18 @@ class Plugin extends ServerPlugin {
return;
}

$this->server->transactionType = 'post-calendar-share';
$this->server->transactionType = 'post-oc-addressbook-share';

// Getting ACL info
$acl = $this->server->getPlugin('acl');

// If there's no ACL support, we allow everything
if ($acl) {
/** @var \Sabre\DAVACL\Plugin $acl */
$acl->checkPrivileges($path, '{DAV:}write');
}

$mutations = $this->parseShareRequest($dom);

$node->updateShares($mutations[0], $mutations[1]);
$node->updateShares($message->set, $message->remove);

$response->setStatus(200);
// Adding this because sending a response body may cause issues,
@@ -148,59 +159,6 @@ class Plugin extends ServerPlugin {
}
}

/**
* Parses the 'share' POST request.
*
* This method returns an array, containing two arrays.
* The first array is a list of new sharees. Every element is a struct
* containing a:
* * href element. (usually a mailto: address)
* * commonName element (often a first and lastname, but can also be
* false)
* * readOnly (true or false)
* * summary (A description of the share, can also be false)
*
* The second array is a list of sharees that are to be removed. This is
* just a simple array with 'hrefs'.
*
* @param \DOMDocument $dom
* @return array
*/
function parseShareRequest(\DOMDocument $dom) {

$xpath = new \DOMXPath($dom);
$xpath->registerNamespace('cs', \Sabre\CardDAV\Plugin::NS_CARDDAV);
$xpath->registerNamespace('d', 'urn:DAV');

$set = [];
$elems = $xpath->query('cs:set');

for ($i = 0; $i < $elems->length; $i++) {

$xset = $elems->item($i);
$set[] = [
'href' => $xpath->evaluate('string(d:href)', $xset),
'commonName' => $xpath->evaluate('string(cs:common-name)', $xset),
'summary' => $xpath->evaluate('string(cs:summary)', $xset),
'readOnly' => $xpath->evaluate('boolean(cs:read)', $xset) !== false
];

}

$remove = [];
$elems = $xpath->query('cs:remove');

for ($i = 0; $i < $elems->length; $i++) {

$xremove = $elems->item($i);
$remove[] = $xpath->evaluate('string(d:href)', $xremove);

}

return [$set, $remove];

}

private function protectAgainstCSRF() {
$user = $this->auth->getCurrentUser();
if ($this->auth->isDavAuthenticated($user)) {

+ 65
- 0
apps/dav/lib/carddav/sharing/xml/sharerequest.php View File

@@ -0,0 +1,65 @@
<?php

namespace OCA\DAV\CardDAV\Sharing\Xml;

use Sabre\Xml\Reader;
use Sabre\Xml\XmlDeserializable;

class ShareRequest implements XmlDeserializable {

public $set = [];

public $remove = [];

/**
* Constructor
*
* @param array $set
* @param array $remove
*/
function __construct(array $set, array $remove) {

$this->set = $set;
$this->remove = $remove;

}

static function xmlDeserialize(Reader $reader) {

$elems = $reader->parseInnerTree([
'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV. '}set' => 'Sabre\\Xml\\Element\\KeyValue',
'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
]);

$set = [];
$remove = [];

foreach ($elems as $elem) {
switch ($elem['name']) {

case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}set' :
$sharee = $elem['value'];

$sumElem = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}summary';
$commonName = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}common-name';

$set[] = [
'href' => $sharee['{DAV:}href'],
'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
'summary' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
'readOnly' => !array_key_exists('{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}read-write', $sharee),
];
break;

case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' :
$remove[] = $elem['value']['{DAV:}href'];
break;

}
}

return new self($set, $remove);

}

}

+ 1
- 1
apps/dav/tests/unit/carddav/carddavbackendtest.php View File

@@ -263,7 +263,7 @@ class CardDavBackendTest extends TestCase {
$books = $this->backend->getAddressBooksForUser('principals/best-friend');
$this->assertEquals(1, count($books));

$this->backend->updateShares('Example', [], [['href' => 'principal:principals/best-friend']]);
$this->backend->updateShares('Example', [], ['principal:principals/best-friend']);

$shares = $this->backend->getShares('Example');
$this->assertEquals(0, count($shares));

+ 81
- 0
apps/dav/tests/unit/carddav/sharing/plugintest.php View File

@@ -0,0 +1,81 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2015, 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\Tests\Unit\CardDAV;


use OCA\DAV\CardDAV\Sharing\IShareableAddressBook;
use OCA\DAV\CardDAV\Sharing\Plugin;
use OCA\DAV\Connector\Sabre\Auth;
use OCP\IRequest;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
use Sabre\HTTP\Response;
use Test\TestCase;

class PluginTest extends TestCase {

/** @var Plugin */
private $plugin;
/** @var Server */
private $server;
/** @var IShareableAddressBook | \PHPUnit_Framework_MockObject_MockObject */
private $book;

public function setUp() {
parent::setUp();
/** @var Auth | \PHPUnit_Framework_MockObject_MockObject $authBackend */
$authBackend = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Auth')->disableOriginalConstructor()->getMock();
$authBackend->method('isDavAuthenticated')->willReturn(true);

/** @var IRequest $request */
$request = $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock();
$this->plugin = new Plugin($authBackend, $request);

$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
/** @var SimpleCollection $node */
$this->book = $this->getMockBuilder('OCA\DAV\CardDAV\Sharing\IShareableAddressBook')->disableOriginalConstructor()->getMock();
$this->book->method('getName')->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
}

public function testSharing() {

$this->book->expects($this->once())->method('updateShares')->with([[
'href' => 'principal:principals/admin',
'commonName' => null,
'summary' => null,
'readOnly' => false
]], ['mailto:wilfredo@example.com']);

// setup request
$request = new Request();
$request->addHeader('Content-Type', 'application/xml');
$request->setUrl('addressbook1.vcf');
$request->setBody('<?xml version="1.0" encoding="utf-8" ?><CS:share xmlns:D="DAV:" xmlns:CS="urn:ietf:params:xml:ns:carddav"><CS:set><D:href>principal:principals/admin</D:href><CS:read-write/></CS:set> <CS:remove><D:href>mailto:wilfredo@example.com</D:href></CS:remove></CS:share>');
$response = new Response();
$this->plugin->httpPost($request, $response);
}
}

Loading…
Cancel
Save