diff options
author | Michael Gapczynski <mtgap@owncloud.com> | 2012-07-14 09:35:39 -0400 |
---|---|---|
committer | Michael Gapczynski <mtgap@owncloud.com> | 2012-07-14 09:35:39 -0400 |
commit | 51a451839671f14ad84b7db8d091ae451006d5f7 (patch) | |
tree | 7012b91dba615bf7930bc36cf89f731ebf775a9e | |
parent | f638340d1fb5d70e6776949d3cdc72597deba4ca (diff) | |
download | nextcloud-server-51a451839671f14ad84b7db8d091ae451006d5f7.tar.gz nextcloud-server-51a451839671f14ad84b7db8d091ae451006d5f7.zip |
Add support for CRUDS permissions
-rw-r--r-- | lib/public/share.php | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/lib/public/share.php b/lib/public/share.php index 9743edd4a63..43ce5b8211f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -27,15 +27,21 @@ namespace OCP; */ class Share { - const SHARE_TYPE_USER = 0; const SHARE_TYPE_GROUP = 1; const SHARE_TYPE_PRIVATE_LINK = 3; - const PERMISSION_READ = 0; - const PERMISSION_UPDATE = 1; - const PERMISSION_DELETE = 2; - const PERMISSION_SHARE = 3; + /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask + * Construct permissions for share() and setPermissions with Or (|) e.g. Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE + * Check if permission is granted with And (&) e.g. Check if delete is granted: if ($permissions & PERMISSION_DELETE) + * Remove permissions with And (&) and Not (~) e.g. Remove the update permission: $permissions &= ~PERMISSION_UPDATE + * Apps are required to handle permissions on their own, this class only stores and manages the permissions of shares + */ + const PERMISSION_CREATE = 4; + const PERMISSION_READ = 1; + const PERMISSION_UPDATE = 2; + const PERMISSION_DELETE = 8; + const PERMISSION_SHARE = 16; const FORMAT_NONE = -1; const FORMAT_STATUSES = -2; @@ -134,7 +140,7 @@ class Share { * @param string Item * @param int SHARETYPE_USER | SHARETYPE_GROUP | SHARETYPE_PRIVATE_LINK * @param string User or group the item is being shared with - * @param string + * @param int CRUDS permissions * @return Returns true on success or false on failure */ public static function share($itemType, $item, $shareType, $shareWith, $permissions) { @@ -309,7 +315,7 @@ class Share { * @param string Item * @param int SHARETYPE_USER | SHARETYPE_GROUP | SHARETYPE_PRIVATE_LINK * @param string User or group the item is being shared with - * @param + * @param int CRUDS permissions * @return Returns true on success or false on failure */ public static function setPermissions($itemType, $item, $shareType, $shareWith, $permissions) { @@ -318,33 +324,47 @@ class Share { if (isset($item['parent'])) { $query = \OC_DB::prepare('SELECT permissions FROM *PREFIX*share WHERE id = ? LIMIT 1'); $result = $query->execute(array($item['parent']))->fetchRow(); - if (!isset($result['permissions']) || $permissions > $result['permissions']) { - \OC_Log::write('OCP\Share', '', \OC_Log::ERROR); + if (~(int)$result['permissions'] & $permissions) { + \OC_Log::write('OCP\Share', 'Setting permissions for '.$item.' failed, because the permissions exceed permissions granted to the parent item', \OC_Log::ERROR); return false; } } $query = \OC_DB::prepare('UPDATE *PREFIX*share SET permissions = ? WHERE id = ?'); $query->execute(array($permissions, $item['id'])); - // Check if permissions were reduced - if ($permissions < $item['permissions']) { - // Reduce the permissions for all reshares of this item - $ids = array($item['id']); - $query = \OC_DB::prepare('SELECT id, parent, permissions FROM *PREFIX*share WHERE item_source = ?'); - $result = $query->execute(array($item['item_source'])); - while ($item = $result->fetchRow()) { - if (in_array($item['parent'], $ids) && $item['permissions'] > $permissions) { - $ids[] = $item['id']; + // Check if permissions were removed + if ($item['permissions'] & ~$permissions) { + // If share permission is removed all reshares must be deleted + if (($item['permissions'] & self::PERMISSION_SHARE) && (~$permissions & self::PERMISSION_SHARE)) { + self::delete($item['id'], true); + } else { + $ids = array(); + $parents = array($item['id']); + while (!empty($parents)) { + $parents = "'".implode("','", $parents)."'"; + $query = \OC_DB::prepare('SELECT id, permissions FROM *PREFIX*share WHERE parent IN ('.$parents.')'); + $result = $query->execute(); + // Reset parents array, only go through loop again if items are found that need permissions removed + $parents = array(); + while ($item = $result->fetchRow()) { + // Check if permissions need to be removed + if ($item['permissions'] & ~$permissions) { + // Add to list of items that need permissions removed + $ids[] = $item['id']; + $parents[] = $item['id']; + } + } + } + // Remove the permissions for all reshares of this item + if (!empty($ids)) { + $ids = "'".implode("','", $ids)."'"; + $query = \OC_DB::prepare('UPDATE *PREFIX*share SET permissions = permissions & ? WHERE id IN ('.$ids.')'); + $query->execute(array($permissions)); } - } - // Remove parent item from array, this item's permissions already got updated - unset($ids[0]); - if (!empty($ids)) { - $query = \OC_DB::prepare('UPDATE *PREFIX*share SET permissions = ? WHERE id IN (?)'); - $query->execute(array($permissions, implode(',', $ids))); } } return true; } + \OC_Log::write('OCP\Share', 'Setting permissions for '.$item.' failed, because the item was not found', \OC_Log::ERROR); return false; } @@ -479,7 +499,7 @@ class Share { $select = 'id, item_type, item, item_source, share_type'; } else { if (isset($uidOwner)) { - $select = 'id, item_type, item, item_source, share_type, share_with, permissions, stime, file_source'; + $select = 'id, item_type, item, item_source, parent, share_type, share_with, permissions, stime, file_source'; } else { $select = '*'; } @@ -556,12 +576,16 @@ class Share { if ($backend = self::getBackend($itemType)) { // Check if this is a reshare if ($checkReshare = self::getItemSharedWith($itemType, $item)) { - // TODO Check if resharing is allowed - // TODO Don't check if inside folder - $parent = $checkReshare['id']; - $itemSource = $checkReshare['item_source']; - $fileSource = $checkReshare['file_source']; - $fileTarget = $checkReshare['file_target']; + if ($checkReshare['permissions'] & self::PERMISSION_SHARE) { + // TODO Don't check if inside folder + $parent = $checkReshare['id']; + $itemSource = $checkReshare['item_source']; + $fileSource = $checkReshare['file_source']; + $fileTarget = $checkReshare['file_target']; + } else { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because resharing is not allowed', \OC_Log::ERROR); + return false; + } } else { $parent = null; $source = $backend->getSource($item, $uidOwner); |