Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add public-files to DAV including ACL handling
  • Loading branch information
DeepDiver1975 committed Mar 26, 2018
commit f3ab5b9d8b7ac5b5383d3856fcf1b9535b73b52c
1 change: 1 addition & 0 deletions apps/dav/lib/DAV/PublicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class PublicAuth implements BackendInterface {
public function __construct() {
$this->publicURLs = [
'public-calendars',
'public-files',
'principals/system/public'
];
}
Expand Down
88 changes: 88 additions & 0 deletions apps/dav/lib/Files/PublicFiles/RootCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
/**
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
* @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\Files\PublicFiles;

use OC\Share\Constants;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Sabre\DAV\Collection;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\SimpleCollection;
use Sabre\DAV\SimpleFile;

class RootCollection extends Collection {

/** @var IManager */
private $shareManager;
/** @var \OCP\IL10N */
protected $l10n;

/**
* If this value is set to true, it effectively disables listing of users
* it still allows user to find other users if they have an exact url.
*
* @var bool
*/
public $disableListing = false;

function __construct() {
$this->l10n = \OC::$server->getL10N('dav');
$this->shareManager = \OC::$server->getShareManager();
Copy link
Contributor

Choose a reason for hiding this comment

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

use DI ?

}

/**
* @inheritdoc
*/
function getName() {
return 'public-files';
}

/**
* @inheritdoc
*/
function getChild($name) {
try {
$share = $this->shareManager->getShareByToken($name);
$password = $share->getPassword();
// TODO: check password
return new ShareNode($share);
} catch (ShareNotFound $ex) {
throw new NotFound();
}
}

/**
* @inheritdoc
*/
function getChildren() {
if ($this->disableListing) {
throw new MethodNotAllowed('Listing members of this collection is disabled');
}

$shares = $this->shareManager->getAllSharedWith(null, [Constants::SHARE_TYPE_LINK]);
return array_map(function(IShare $share) {
return new ShareNode($share);
}, $shares);
}
}
55 changes: 55 additions & 0 deletions apps/dav/lib/Files/PublicFiles/ShareNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* Created by PhpStorm.
* User: deepdiver
* Date: 26.10.17
* Time: 14:40
*/

namespace OCA\DAV\Files\PublicFiles;


use OCP\Files\FileInfo;
use OCP\Files\Node;
use OCP\Share\IShare;
use Sabre\DAV\Collection;
use Sabre\DAV\INode;

class ShareNode extends Collection {
Copy link
Contributor

Choose a reason for hiding this comment

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

PHPDoc, what is this node about ?


/** @var IShare */
private $share;

public function __construct(IShare $share) {
$this->share = $share;
}
/**
* Returns an array with all the child nodes
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest clarifying and saying we are returning both SharedFolder and SharedFile nodes depending on child types

*
* @return INode[]
*/
function getChildren() {
if ($this->share->getNodeType() === 'folder') {
$nodes = $this->share->getNode()->getDirectoryListing();
} else {
$nodes = [$this->share->getNode()];
}
return array_map(function(Node $node) {
if ($node->getType() === FileInfo::TYPE_FOLDER) {
return new SharedFolder($node, $this->share);
}
return new SharedFile($node, $this->share);
}, $nodes);
}

/**
* Returns the name of the node.
*
* This is used to generate the url.
*
* @return string
*/
function getName() {
return $this->share->getToken();
}
}
104 changes: 104 additions & 0 deletions apps/dav/lib/Files/PublicFiles/SharedFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
* @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\Files\PublicFiles;


use OCP\Share\IShare;
use Sabre\DAV\File;
use Sabre\DAVACL\ACLTrait;
use Sabre\DAVACL\IACL;

/**
* Class MetaFile
Copy link
Contributor

Choose a reason for hiding this comment

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

please adjust, smells like copy-pasted from another PR 😉

* This is a Sabre based implementation of a file living in the /meta resource.
*
* @package OCA\DAV\Meta
*/
class SharedFile extends File implements IACL {

use ACLTrait;

/** @var \OCP\Files\File */
private $file;

/**
* MetaFolder constructor.
*
* @param \OCP\Files\File $file
* @param IShare $share
*/
public function __construct(\OCP\Files\File $file, IShare $share) {
$this->file = $file;
}

/**
* @inheritdoc
*/
function getName() {
return $this->file->getName();
}

public function getSize() {
return $this->file->getSize();
}

public function getContentType() {
return $this->file->getMimeType();
}

public function getETag() {
return $this->file->getETag();
}

function getLastModified() {
return $this->file->getMTime();
}

function delete() {
// TODO: check permissions - via ACL?
$this->file->delete();
}

// function setName($name) {
// $this->file->setName($name);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can forbid renaming share file here. This is because the name itself isn't visible anyway but someone might attempt to hack the API to try it out.

For local shares the file name is a received mount point. But here for link shares this is no mount point.

Throw Forbidden ?

// }

function getOwner() {
return '';
}

function getACL() {
return [
[
'privilege' => '{DAV:}all',
'principal' => '{DAV:}owner',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => 'principals/system/public',
'protected' => true,
]
];
}
}
128 changes: 128 additions & 0 deletions apps/dav/lib/Files/PublicFiles/SharedFolder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php
/**
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
* @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\Files\PublicFiles;


use OCP\Constants;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\Share\IShare;
use Sabre\DAV\Collection;
use Sabre\DAVACL\ACLTrait;
use Sabre\DAVACL\IACL;

/**
* Class MetaFolder
Copy link
Contributor

Choose a reason for hiding this comment

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

phpdoc

* This is a Sabre based implementation of a folder living in the /meta resource.
*
* @package OCA\DAV\Meta
*/
class SharedFolder extends Collection implements IACL {
use ACLTrait;

/** @var Folder */
private $folder;
/** @var IShare */
private $share;

/**
* MetaFolder constructor.
*
* @param Folder $folder
*/
public function __construct(Folder $folder, IShare $share) {
$this->folder = $folder;
$this->share = $share;
}

/**
* @inheritdoc
*/
function getChildren() {
$nodes = $this->folder->getDirectoryListing();
return array_map(function($node) {
return $this->nodeFactory($node);
}, $nodes);
}

/**
* @inheritdoc
*/
function getName() {
return $this->folder->getName();
}

function getLastModified() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add getEtag() maybe.

We'll likely do a PROPFIND on this folder so it's good to get the etag to know if there were changes inside the folder.

Also add this to SharedFile.

Sounds like we might need a custom INode interface which has the getEtag method ? Or does Sabre retrieve the Etag differently ? (I forgot)

return $this->folder->getMTime();
}

function createDirectory($name) {
$this->folder->newFolder($name);
}

function createFile($name, $data = null) {
$file = $this->folder->newFile($name);
$file->putContent($data);

}

private function nodeFactory(Node $node) {
if ($node instanceof Folder) {
return new SharedFolder($node, $this->share);
}
if ($node instanceof File) {
return new SharedFile($node, $this->share);
}
throw new \InvalidArgumentException();
}

function getACL() {
$acl = [
[
'privilege' => '{DAV:}all',
'principal' => '{DAV:}owner',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => 'principals/system/public',
'protected' => true,
]
];

// TODO: add more acl to convert the logic
if ($this->share->getPermissions() & Constants::PERMISSION_DELETE === Constants::PERMISSION_DELETE) {
$acl[]= [
[
'privilege' => '{DAV:}unbind',
'principal' => 'principals/system/public',
'protected' => true,
]
];
}

return $acl;
}

}
Loading