Skip to content

Commit

Permalink
Classic share permissions can be set via share attributes now as well
Browse files Browse the repository at this point in the history
  • Loading branch information
DeepDiver1975 committed Aug 20, 2019
1 parent 1321566 commit 2ef190a
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 131 deletions.
144 changes: 105 additions & 39 deletions apps/files_sharing/lib/Controller/Share20OcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@

namespace OCA\Files_Sharing\Controller;

use Exception;
use OC\Files\Filesystem;
use OCP\Constants;
use OC\OCS\Result;
use OCP\AppFramework\OCSController;
use OCP\Defaults;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IConfig;
Expand Down Expand Up @@ -134,6 +139,8 @@ private function getAdditionalUserInfo(IUser $user) {
* @param bool $received whether it's formatting received shares
* @return array
* @throws NotFoundException In case the node can't be resolved.
* @throws \OCP\Files\InvalidPathException
* @throws \OCP\Files\StorageNotAvailableException
*/
protected function formatShare(IShare $share, $received = false) {
$sharedBy = $this->userManager->get($share->getSharedBy());
Expand Down Expand Up @@ -176,7 +183,7 @@ protected function formatShare(IShare $share, $received = false) {
$node = $nodes[0];

$result['path'] = $userFolder->getRelativePath($node->getPath());
if ($node instanceof \OCP\Files\Folder) {
if ($node instanceof Folder) {
$result['item_type'] = 'folder';
} else {
$result['item_type'] = 'file';
Expand Down Expand Up @@ -274,6 +281,9 @@ public function getShare($id) {
*
* @param string $id
* @return Result
* @throws LockedException
* @throws NotFoundException
* @throws ShareNotFound
*/
public function deleteShare($id) {
if (!$this->shareManager->shareApiEnabled()) {
Expand Down Expand Up @@ -309,6 +319,9 @@ public function deleteShare($id) {
* @NoAdminRequired
*
* @return Result
* @throws LockedException
* @throws NotFoundException
* @throws \OCP\Files\InvalidPathException
*/
public function createShare() {
$share = $this->shareManager->newShare();
Expand Down Expand Up @@ -344,7 +357,7 @@ public function createShare() {
$shareType = (int)$this->request->getParam('shareType', '-1');

// Parse permissions (if available)
$permissions = $this->request->getParam('permissions', null);
$permissions = $this->getPermissionsFromRequest();
if ($permissions === null) {
if ($shareType !== Share::SHARE_TYPE_LINK) {
$permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
Expand Down Expand Up @@ -423,7 +436,7 @@ public function createShare() {
}

// Public upload can only be set for folders
if ($path instanceof \OCP\Files\File) {
if ($path instanceof File) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders'));
}
Expand All @@ -437,9 +450,9 @@ public function createShare() {
Constants::PERMISSION_UPDATE |
Constants::PERMISSION_DELETE
);
} elseif ($permissions === \OCP\Constants::PERMISSION_CREATE ||
$permissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) ||
$permissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE)) {
} elseif ($permissions === Constants::PERMISSION_CREATE ||
$permissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE) ||
$permissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE)) {
$share->setPermissions($permissions);
} else {
// because when "publicUpload" is passed usually no permissions are set,
Expand All @@ -466,7 +479,7 @@ public function createShare() {
try {
$expireDate = $this->parseDate($expireDate);
$share->setExpirationDate($expireDate);
} catch (\Exception $e) {
} catch (Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD'));
}
Expand Down Expand Up @@ -510,20 +523,20 @@ public function createShare() {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, $code, $e->getHint());
} catch (\Exception $e) {
} catch (Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 403, $e->getMessage());
}

$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);

$formattedShareAfterCreate = $this->formatShare($share);

return new Result($formattedShareAfterCreate);
}

/**
* @param \OCP\Files\File|\OCP\Files\Folder $node
* @param File|Folder $node
* @param boolean $includeTags include tags in response
* @param int|null $stateFilter state filter or empty for all, defaults to 0 (accepted)
* @return Result
Expand Down Expand Up @@ -569,11 +582,12 @@ private function getSharedWithMe($node = null, $includeTags, $stateFilter = 0) {
}

/**
* @param \OCP\Files\Folder $folder
* @param Folder $folder
* @return Result
* @throws NotFoundException
*/
private function getSharesInDir($folder) {
if (!($folder instanceof \OCP\Files\Folder)) {
if (!($folder instanceof Folder)) {
return new Result(null, 400, $this->l->t('Not a directory'));
}

Expand Down Expand Up @@ -614,6 +628,7 @@ private function getSharesInDir($folder) {
* - Get all shares in a folder (?subfiles=true&path=..)
*
* @return Result
* @throws LockedException
*/
public function getShares() {
if (!$this->shareManager->shareApiEnabled()) {
Expand All @@ -632,7 +647,7 @@ public function getShares() {
try {
$path = $userFolder->get($path);
$path->lock(ILockingProvider::LOCK_SHARED);
} catch (\OCP\Files\NotFoundException $e) {
} catch (NotFoundException $e) {
return new Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist'));
} catch (LockedException $e) {
return new Result(null, 404, $this->l->t('Could not lock path'));
Expand Down Expand Up @@ -706,6 +721,8 @@ public function getShares() {
*
* @param int $id
* @return Result
* @throws LockedException
* @throws NotFoundException
*/
public function updateShare($id) {
if (!$this->shareManager->shareApiEnabled()) {
Expand All @@ -718,14 +735,14 @@ public function updateShare($id) {
return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}

$share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$share->getNode()->lock(ILockingProvider::LOCK_SHARED);

if (!$this->canAccessShare($share)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}

$permissions = $this->request->getParam('permissions', null);
$permissions = $this->getPermissionsFromRequest();
$password = $this->request->getParam('password', null);
$publicUpload = $this->request->getParam('publicUpload', null);
$expireDate = $this->request->getParam('expireDate', null);
Expand Down Expand Up @@ -775,7 +792,7 @@ public function updateShare($id) {
return new Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
}

if (!($share->getNode() instanceof \OCP\Files\Folder)) {
if (!($share->getNode() instanceof Folder)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders'));
}
Expand All @@ -790,7 +807,7 @@ public function updateShare($id) {
return new Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
}

if (!($share->getNode() instanceof \OCP\Files\Folder)) {
if (!($share->getNode() instanceof Folder)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders'));
}
Expand All @@ -810,7 +827,7 @@ public function updateShare($id) {
} elseif ($expireDate !== null) {
try {
$expireDate = $this->parseDate($expireDate);
} catch (\Exception $e) {
} catch (Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 400, $e->getMessage());
}
Expand Down Expand Up @@ -841,12 +858,12 @@ public function updateShare($id) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, $code, $e->getHint());
} catch (\Exception $e) {
} catch (Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 400, $e->getMessage());
}

$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);

return new Result($this->formatShare($share));
}
Expand Down Expand Up @@ -900,7 +917,7 @@ public function notifyRecipients($itemSource, $itemType, $shareType, $recipient)
return $user->getUID() !== $this->userSession->getUser()->getUID();
});

$defaults = new \OCP\Defaults();
$defaults = new Defaults();
$mailNotification = new \OC\Share\MailNotifications(
$this->shareManager,
$this->userSession->getUser(),
Expand Down Expand Up @@ -961,6 +978,8 @@ public function notifyRecipientsDisabled($itemSource, $itemType, $shareType, $re
* @param $id
* @param $state
* @return Result
* @throws LockedException
* @throws NotFoundException
*/
private function updateShareState($id, $state) {
$eventName = '';
Expand All @@ -982,7 +1001,7 @@ private function updateShareState($id, $state) {
}

$node = $share->getNode();
$node->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$node->lock(ILockingProvider::LOCK_SHARED);

// this checks that we are either the owner or recipient
if (!$this->canAccessShare($share)) {
Expand All @@ -1002,7 +1021,7 @@ private function updateShareState($id, $state) {
$this->eventDispatcher->dispatch('share.after' . $eventName, new GenericEvent(null, ['share' => $share]));
}
// if there are no changes in the state, just return the share as if the change was successful
$node->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$node->unlock(ILockingProvider::LOCK_SHARED);
return new Result([$this->formatShare($share, true)]);
}

Expand All @@ -1024,15 +1043,15 @@ private function updateShareState($id, $state) {
$aShare->setTarget($share->getTarget());
$this->shareManager->updateShareForRecipient($aShare, $this->userSession->getUser()->getUID());
}
} catch (\Exception $e) {
} catch (Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 400, $e->getMessage());
}

$node->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$node->unlock(ILockingProvider::LOCK_SHARED);

// FIXME: needs public API!
\OC\Files\Filesystem::tearDown();
Filesystem::tearDown();
// FIXME: trigger mount for user to make sure the new node is mounted already
// before formatShare resolves it
$this->rootFolder->getUserFolder($this->userSession->getUser()->getUID());
Expand All @@ -1057,18 +1076,18 @@ private function deduplicateShareTarget(IShare $share) {
$parentDir = \dirname($share->getTarget());
if (!$userFolder->nodeExists($parentDir)) {
$parentDir = Helper::getShareFolder();
$pathAttempt = \OC\Files\Filesystem::normalizePath($parentDir . '/' . $share->getTarget());
$pathAttempt = Filesystem::normalizePath($parentDir . '/' . $share->getTarget());
} else {
$pathAttempt = \OC\Files\Filesystem::normalizePath($share->getTarget());
$pathAttempt = Filesystem::normalizePath($share->getTarget());
}

$pathinfo = \pathinfo($pathAttempt);
$ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : '';
$ext = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
$name = $pathinfo['filename'];

$i = 2;
while ($userFolder->nodeExists($pathAttempt)) {
$pathAttempt = \OC\Files\Filesystem::normalizePath($parentDir . '/' . $name . ' ('.$i.')' . $ext);
$pathAttempt = Filesystem::normalizePath($parentDir . '/' . $name . ' ('.$i.')' . $ext);
$i++;
}

Expand Down Expand Up @@ -1119,18 +1138,18 @@ protected function canAccessShare(IShare $share) {
*
* @param string $expireDate
*
* @throws \Exception
* @throws Exception
* @return \DateTime
*/
private function parseDate($expireDate) {
try {
$date = new \DateTime($expireDate);
} catch (\Exception $e) {
throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
} catch (Exception $e) {
throw new Exception('Invalid date. Format must be YYYY-MM-DD');
}

if ($date === false) {
throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
throw new Exception('Invalid date. Format must be YYYY-MM-DD');
}

$date->setTime(0, 0, 0);
Expand All @@ -1143,6 +1162,7 @@ private function parseDate($expireDate) {
* not support this we need to check all backends.
*
* @param string $id
* @param null $recipient
* @return IShare
* @throws ShareNotFound
*/
Expand Down Expand Up @@ -1172,15 +1192,61 @@ private function setShareAttributes(IShare $share, $formattedShareAttributes) {
$newShareAttributes = $this->shareManager->newShare()->newAttributes();
if ($formattedShareAttributes !== null) {
foreach ($formattedShareAttributes as $formattedAttr) {
$newShareAttributes->setAttribute(
$formattedAttr['scope'],
$formattedAttr['key'],
(bool) \json_decode($formattedAttr['enabled'])
);
$value = isset($formattedAttr['value']) ? $formattedAttr['value'] : null;
if (isset($formattedAttr['enabled'])) {
$value = (bool) \json_decode($formattedAttr['enabled']);
}
if ($value) {
$newShareAttributes->setAttribute(
$formattedAttr['scope'],
$formattedAttr['key'],
$value
);
}
}
}
$share->setAttributes($newShareAttributes);

return $share;
}

/**
* @return mixed
*/
private function getPermissionsFromRequest() {
// int-based permissions are set -> use them
$permissions = $this->request->getParam('permissions', null);
if ($permissions !== null) {
return $permissions;
}
// have permissions been set via attributes?
$attributes = $this->request->getParam('attributes', null);
if ($attributes === null) {
return null;
}
$permission = 0;
foreach ($attributes as $attribute) {
if ($attribute['scope'] === 'ownCloud') {
$key = $attribute['key'];
$value = $attribute['value'];
if ($key === 'create' && $value === 'true') {
$permission |= Constants::PERMISSION_CREATE;
}
if ($key === 'read' && $value === 'true') {
$permission |= Constants::PERMISSION_READ;
}
if ($key === 'update' && $value === 'true') {
$permission |= Constants::PERMISSION_UPDATE;
}
if ($key === 'delete' && $value === 'true') {
$permission |= Constants::PERMISSION_DELETE;
}
if ($key === 'share' && $value === 'true') {
$permission |= Constants::PERMISSION_SHARE;
}
}
}

return $permission;
}
}
Loading

0 comments on commit 2ef190a

Please sign in to comment.