/** * get list of users with access to the file * * @param string $path to the file * @return array */ public function getAccessList($path) { // Make sure that a share key is generated for the owner too list($owner, $ownerPath) = $this->util->getUidAndFilename($path); // always add owner to the list of users with access to the file $userIds = array($owner); if (!$this->util->isFile($ownerPath)) { return array('users' => $userIds, 'public' => false); } $ownerPath = substr($ownerPath, strlen('/files')); $ownerPath = $this->util->stripPartialFileExtension($ownerPath); // Find out who, if anyone, is sharing the file $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner); $userIds = \array_merge($userIds, $result['users']); $public = $result['public'] || $result['remote']; // check if it is a group mount if (\OCP\App::isEnabled("files_external")) { $mounts = \OC_Mount_Config::getSystemMountPoints(); foreach ($mounts as $mount) { if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) { $mountedFor = $this->util->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']); $userIds = array_merge($userIds, $mountedFor); } } } // Remove duplicate UIDs $uniqueUserIds = array_unique($userIds); return array('users' => $uniqueUserIds, 'public' => $public); }
/** * decrypt given file with recovery key and encrypt it again to the owner and his new key * @param string $file * @param string $privateKey recovery key to decrypt the file */ private function recoverFile($file, $privateKey) { $sharingEnabled = \OCP\Share::isEnabled(); // Find out who, if anyone, is sharing the file if ($sharingEnabled) { $result = \OCP\Share::getUsersSharingFile($file, $this->userId, true); $userIds = $result['users']; $userIds[] = $this->recoveryKeyId; if ($result['public']) { $userIds[] = $this->publicShareKeyId; } } else { $userIds = array($this->userId, $this->recoveryKeyId); } $filteredUids = $this->filterShareReadyUsers($userIds); //decrypt file key $encKeyfile = Keymanager::getFileKey($this->view, $this, $file); $shareKey = Keymanager::getShareKey($this->view, $this->recoveryKeyId, $this, $file); $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); // encrypt file key again to all users, this time with the new public key for the recovered use $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); Keymanager::setFileKey($this->view, $this, $file, $multiEncKey['data']); Keymanager::setShareKeys($this->view, $this, $file, $multiEncKey['keys']); }
/** * Returns a "username => path" map for all affected users * * @param string $path * @return array */ protected function getUserPathsFromPath($path) { list($file_path, $uidOwner) = $this->getSourcePathAndOwner($path); return Share::getUsersSharingFile($file_path, $uidOwner, true, true); }
/** * Returns a "username => path" map for all affected users * * @param string $path * @param string $uidOwner * @return array */ protected function getUserPathsFromPath($path, $uidOwner) { return Share::getUsersSharingFile($path, $uidOwner, true, true); }
/** * @dataProvider dataProviderGetUsersSharingFile * * @param string $groupName name of group to share with * @param bool $includeOwner whether to include the owner in the result * @param bool $includePaths whether to include paths in the result * @param array $expectedResult expected result of the API call */ public function testGetUsersSharingFile($groupName, $includeOwner, $includePaths, $expectedResult) { $fileinfo = $this->view->getFileInfo($this->folder); $result = \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, $groupName, \OCP\Constants::PERMISSION_READ); $this->assertTrue($result); // public share $result = \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ); $this->assertNotNull($result); // returns the token! // owner renames after sharing $this->view->rename($this->folder, $this->folder . '_owner_renamed'); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); $user2View->rename($this->folder, $this->folder . '_renamed'); $ownerPath = $this->folder . '_owner_renamed'; $owner = self::TEST_FILES_SHARING_API_USER1; $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner, $includeOwner, $includePaths); // sort users to make sure it matches if ($includePaths) { ksort($result); } else { sort($result['users']); } $this->assertEquals($expectedResult, $result); }
/** * Returns a "username => path" map for all affected users * * @param string $path * @return array */ public static function getUserPathsFromPath($path) { list($file_path, $uidOwner) = self::getSourcePathAndOwner($path); return \OCP\Share::getUsersSharingFile($file_path, $uidOwner, true, true); }
/** * decrypt given file with recovery key and encrypt it again to the owner and his new key * @param string $file * @param string $privateKey recovery key to decrypt the file */ private function recoverFile($file, $privateKey) { $sharingEnabled = \OCP\Share::isEnabled(); // Find out who, if anyone, is sharing the file if ($sharingEnabled) { $result = \OCP\Share::getUsersSharingFile($file, $this->userId, true); $userIds = $result['users']; $userIds[] = $this->recoveryKeyId; if ($result['public']) { $userIds[] = $this->publicShareKeyId; } } else { $userIds = array($this->userId, $this->recoveryKeyId); } $filteredUids = $this->filterShareReadyUsers($userIds); $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; //decrypt file key $encKeyfile = $this->view->file_get_contents($this->keyfilesPath . $file . ".key"); $shareKey = $this->view->file_get_contents($this->shareKeysPath . $file . "." . $this->recoveryKeyId . ".shareKey"); $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); // encrypt file key again to all users, this time with the new public key for the recovered use $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); // write new keys to filesystem TDOO! $this->view->file_put_contents($this->keyfilesPath . $file . '.key', $multiEncKey['data']); foreach ($multiEncKey['keys'] as $userId => $shareKey) { $shareKeyPath = $this->shareKeysPath . $file . '.' . $userId . '.shareKey'; $this->view->file_put_contents($shareKeyPath, $shareKey); } // Return proxy to original status \OC_FileProxy::$enabled = $proxyStatus; }
/** * @param MapperEvent $event */ public function mapperEvent(MapperEvent $event) { $tagIds = $event->getTags(); if ($event->getObjectType() !== 'files' || empty($tagIds) || !in_array($event->getEvent(), [MapperEvent::EVENT_ASSIGN, MapperEvent::EVENT_UNASSIGN]) || !$this->appManager->isInstalled('activity')) { // System tags not for files, no tags, not (un-)assigning or no activity-app enabled (save the energy) return; } try { $tags = $this->tagManager->getTagsByIds($tagIds); } catch (TagNotFoundException $e) { // User assigned/unassigned a non-existing tag, ignore... return; } if (empty($tags)) { return; } // Get all mount point owners $cache = $this->mountCollection->getMountCache(); $mounts = $cache->getMountsForFileId($event->getObjectId()); if (empty($mounts)) { return; } $users = []; foreach ($mounts as $mount) { $owner = $mount->getUser()->getUID(); $ownerFolder = $this->rootFolder->getUserFolder($owner); $nodes = $ownerFolder->getById($event->getObjectId()); if (!empty($nodes)) { /** @var Node $node */ $node = array_shift($nodes); $path = $node->getPath(); if (strpos($path, '/' . $owner . '/files/') === 0) { $path = substr($path, strlen('/' . $owner . '/files')); } // Get all users that have access to the mount point $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); } } $actor = $this->session->getUser(); if ($actor instanceof IUser) { $actor = $actor->getUID(); } else { $actor = ''; } $activity = $this->activityManager->generateEvent(); $activity->setApp(Extension::APP_NAME)->setType(Extension::APP_NAME)->setAuthor($actor)->setObject($event->getObjectType(), $event->getObjectId()); foreach ($users as $user => $path) { $activity->setAffectedUser($user); foreach ($tags as $tag) { if ($event->getEvent() === MapperEvent::EVENT_ASSIGN) { $activity->setSubject(Extension::ASSIGN_TAG, [$actor, $path, $this->prepareTagAsParameter($tag)]); } else { if ($event->getEvent() === MapperEvent::EVENT_UNASSIGN) { $activity->setSubject(Extension::UNASSIGN_TAG, [$actor, $path, $this->prepareTagAsParameter($tag)]); } } $this->activityManager->publish($activity); } } }
/** * @param CommentsEvent $event */ public function commentEvent(CommentsEvent $event) { if ($event->getComment()->getObjectType() !== 'files' || !in_array($event->getEvent(), [CommentsEvent::EVENT_ADD]) || !$this->appManager->isInstalled('activity')) { // Comment not for file, not adding a comment or no activity-app enabled (save the energy) return; } // Get all mount point owners $cache = $this->mountCollection->getMountCache(); $mounts = $cache->getMountsForFileId($event->getComment()->getObjectId()); if (empty($mounts)) { return; } $users = []; foreach ($mounts as $mount) { $owner = $mount->getUser()->getUID(); $ownerFolder = $this->rootFolder->getUserFolder($owner); $nodes = $ownerFolder->getById($event->getComment()->getObjectId()); if (!empty($nodes)) { /** @var Node $node */ $node = array_shift($nodes); $path = $node->getPath(); if (strpos($path, '/' . $owner . '/files/') === 0) { $path = substr($path, strlen('/' . $owner . '/files')); } // Get all users that have access to the mount point $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); } } $actor = $this->session->getUser(); if ($actor instanceof IUser) { $actor = $actor->getUID(); } else { $actor = ''; } $activity = $this->activityManager->generateEvent(); $activity->setApp(Extension::APP_NAME)->setType(Extension::APP_NAME)->setAuthor($actor)->setObject($event->getComment()->getObjectType(), $event->getComment()->getObjectId())->setMessage(Extension::ADD_COMMENT_MESSAGE, [$event->getComment()->getId()]); foreach ($users as $user => $path) { $activity->setAffectedUser($user); $activity->setSubject(Extension::ADD_COMMENT_SUBJECT, [$actor, $path]); $this->activityManager->publish($activity); } }
/** * unmount file from yourself */ public static function postUmount($params) { if (!isset(self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]])) { return true; } $umountedFile = self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]]; $path = $umountedFile['path']; $user = $umountedFile['uid']; $itemType = $umountedFile['itemType']; $view = new \OC\Files\View(); $util = new Util($view, $user); // we don't need to remember the file any longer unset(self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]]); // if we unshare a folder we need a list of all (sub-)files if ($itemType === 'folder') { $allFiles = $util->getAllFiles($path); } else { $allFiles = array($path); } foreach ($allFiles as $path) { // check if the user still has access to the file, otherwise delete share key $sharingUsers = \OCP\Share::getUsersSharingFile($path, $user); if (!in_array(\OCP\User::getUser(), $sharingUsers['users'])) { Keymanager::delShareKey($view, array(\OCP\User::getUser()), $path, $user); } } }
/** * unmount file from yourself */ public static function postUnmount($params) { $path = $params[\OC\Files\Filesystem::signal_param_path]; $user = \OCP\User::getUser(); if (!isset(self::$unmountedFiles[$path])) { return true; } $umountedFile = self::$unmountedFiles[$path]; $keyPath = $umountedFile['keyPath']; $owner = $umountedFile['owner']; $ownerPath = $umountedFile['ownerPath']; $view = new \OC\Files\View(); // we don't need to remember the file any longer unset(self::$unmountedFiles[$path]); // check if the user still has access to the file, otherwise delete share key $sharingUsers = \OCP\Share::getUsersSharingFile($path, $user); if (!in_array($user, $sharingUsers['users'])) { Keymanager::delShareKey($view, array($user), $keyPath, $owner, $ownerPath); } }