diff --git a/appinfo/app.php b/appinfo/app.php index 8dee578e3..69dc3c5c0 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -46,3 +46,15 @@ OC\Files\Filesystem::signal_post_rename, 'OCA\Search_Lucene\Hooks\Files', OCA\Search_Lucene\Hooks\Files::handle_post_rename); + +//register to receive notification of sharing status changes +OCP\Util::connectHook( + 'OCP\Share', + 'post_shared', + 'OCA\Search_Lucene\Hooks\Share', + 'postShareHook'); + +OCP\Util::connectHook('OCP\Share', + 'post_unshare', + 'OCA\Search_Lucene\Hooks\Share', + 'postUnshareHook'); diff --git a/appinfo/application.php b/appinfo/application.php index 1a14a3cde..0b8428be5 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -14,6 +14,7 @@ use OCA\Search_Lucene\Controller\ApiController; use OCA\Search_Lucene\Core\Logger; use OCA\Search_Lucene\Db\StatusMapper; +use OCA\Search_Lucene\Db\FilesInFolder; use OCA\Search_Lucene\Lucene\Index; use OCA\Search_Lucene\Lucene\Indexer; use OCA\Search_Lucene\Core\Files; @@ -119,6 +120,9 @@ public function __construct (array $urlParams=array()) { return $c->query('ServerContainer')->getRootFolder(); }); + $container->registerService('FilesInFolder', function($c) { + return new FilesInFolder($c->query('Db')); + }); } diff --git a/core/files.php b/core/files.php index 29368d956..dfd3a060c 100644 --- a/core/files.php +++ b/core/files.php @@ -63,9 +63,7 @@ public function setUpIndexFolder($userId = null) { // FIXME \OC::$server->getAppFolder() returns '/search' //$indexFolder = \OC::$server->getAppFolder(); - $userHome = $this->setUpUserHome($userId); - - return $this->getOrCreateSubFolder($userHome, 'lucene_index'); + return $this->getOrCreateSubFolder($this->rootFolder, '/' . 'lucene_index'); } /** diff --git a/db/filesinfolder.php b/db/filesinfolder.php new file mode 100644 index 000000000..a6a91612e --- /dev/null +++ b/db/filesinfolder.php @@ -0,0 +1,51 @@ + + * @copyright Devin M. Ceartas 2016 + */ + +namespace OCA\Search_Lucene\Db; + +use OCP\IDb; + +class FilesInFolder { + + private $db; + private $files; + + public function __construct(IDb $db) { + $this->db = $db; + $this->files = array(); + } + + public function files($folder_id) { + $sth = $this->db->prepare('SELECT fileid FROM `*PREFIX*filecache` WHERE `parent` = ?'); + $sth->bindValue(1, $folder_id, \PDO::PARAM_INT); + $sth->execute(); + $result = $sth->fetchAll(); + + foreach ($result as $row) { + if ($this->is_sub_folder($row['fileid'])) { + return $this->files($row['fileid']); + } else { + $this->files[] = $row['fileid']; + } + } + + return array_unique($this->files); + } + + private function is_sub_folder($folder_id) { + $inner = $this->db->prepare('SELECT count(fileid) AS `is_sub` FROM `*PREFIX*filecache` WHERE `parent` = ?'); + $inner->bindValue(1, $folder_id, \PDO::PARAM_INT); + $inner->execute(); + $sub_result = $inner->fetchAll(); + return ($sub_result['is_sub'] > 0); + } + +} diff --git a/hooks/share.php b/hooks/share.php new file mode 100644 index 000000000..c3e7c25b5 --- /dev/null +++ b/hooks/share.php @@ -0,0 +1,45 @@ + + * @copyright Devin M. Ceartas 2016 + */ + +namespace OCA\Search_Lucene\Hooks; + +use OCA\Search_Lucene\AppInfo\Application; + +class Share { + + private static function reIndex($fileIds) { + $app = new Application(); + $container = $app->getContainer(); + $container->query('Indexer')->indexFiles($fileIds); + } + + public static function postShareHook(array $param) { + if ('file' === $param['itemType']) { + self::reIndex([$param['itemSource']]); + } else { + $app = new Application(); + $container = $app->getContainer(); + $files = $container->query('FilesInFolder')->files($param['itemSource']); + self::reIndex($files); + } + } + + public static function postUnshareHook(array $param) { + if ('file' === $param['itemType']) { + self::reIndex([$param['itemSource']]); + } else { + $app = new Application(); + $container = $app->getContainer(); + $files = $container->query('FilesInFolder')->files($param['itemSource']); + self::reIndex($files); + } + } +} diff --git a/jobs/deletejob.php b/jobs/deletejob.php index 11f82791b..3b32faf0f 100644 --- a/jobs/deletejob.php +++ b/jobs/deletejob.php @@ -40,15 +40,8 @@ public function run($arguments){ /** @var Logger $logger */ $logger = $container->query('Logger'); - - if (empty($arguments['user'])) { - $logger->debug('indexer job did not receive user in arguments: '.json_encode($arguments) ); - return; - } - - $userId = $arguments['user']; - $logger->debug('background job optimizing index for '.$userId ); - $container->query('FileUtility')->setUpIndexFolder($userId); + $logger->debug('background job optimizing index'); + $container->query('FileUtility')->setUpIndexFolder(); /** @var Index $index */ $index = $container->query('Index'); diff --git a/jobs/optimizejob.php b/jobs/optimizejob.php index e0d78063a..5b599d0a4 100644 --- a/jobs/optimizejob.php +++ b/jobs/optimizejob.php @@ -35,13 +35,8 @@ public function run($arguments){ /** @var Logger $logger */ $logger = $container->query('Logger'); - if (!empty($arguments['user'])) { - $userId = $arguments['user']; - $logger->debug('background job optimizing index for '.$userId ); - $container->query('FileUtility')->setUpIndexFolder($userId); - $container->query('Index')->optimizeIndex(); - } else { - $logger->debug('indexer job did not receive user in arguments: '.json_encode($arguments) ); - } + $logger->debug('background job optimizing index'); + $container->query('FileUtility')->setUpIndexFolder(); + $container->query('Index')->optimizeIndex(); } } diff --git a/lucene/indexer.php b/lucene/indexer.php index c42c7e4c8..15240e23d 100644 --- a/lucene/indexer.php +++ b/lucene/indexer.php @@ -12,6 +12,7 @@ namespace OCA\Search_Lucene\Lucene; use OCP\Files\File; +use OCP\Share; use OCA\Search_Lucene\Core\Files; use OCA\Search_Lucene\Db\StatusMapper; use OCA\Search_Lucene\Document\Ods; @@ -236,6 +237,22 @@ public function indexFile(File $file, $commit = true) { // Store filecache id as unique id to lookup by when deleting $doc->addField(Document\Field::Keyword('fileId', $file->getId())); + + // Store names of individuals who have read permissions + // FIXME: this next four lines seem a bit awkward. The goal is to get the "path" as + // getUsersSharingFile() method expects it, which is relative to the user's dir + // of files, without assuming the data directory is the same as the user name. + $user = \OC::$server->getUserSession()->getUser(); + if (!$user) { + return false; + } + $full_home_dir = $user->getHome(); + $datadirectory = \OC::$server->getConfig()->getSystemValue('datadirectory'); + $prefix = preg_replace( "!^" . $datadirectory . "!", "", $full_home_dir ) . '/files/'; + $path = preg_replace( '!'.$prefix.'!', "", $file->getPath()); + $canReadIndiv = Share::getUsersSharingFile($path, $user, true, false); + $concatenated = '_' . implode('_', $canReadIndiv['users']) . '_'; + $doc->addField(Document\Field::Text('can_read', $concatenated, 'UTF-8')); // Store document path for the search results $doc->addField(Document\Field::Text('path', $file->getPath(), 'UTF-8')); diff --git a/search/luceneprovider.php b/search/luceneprovider.php index 834004cbf..bcf4ad4b3 100644 --- a/search/luceneprovider.php +++ b/search/luceneprovider.php @@ -49,7 +49,14 @@ public function search($query){ $hits = $index->find($query); //limit results. we cant show more than ~30 anyway. TODO use paging later + $user = \OC::$server->getUserSession()->getUser(); + if (!$user) { + return []; + } for ($i = 0; $i < 30 && $i < count($hits); $i++) { + if (false === strpos($hits[$i]->can_read, '_' . $user->getUID() . '_')) { + continue; + } $results[] = new LuceneResult($hits[$i]); } diff --git a/search/luceneresult.php b/search/luceneresult.php index d32fe7bbf..a41493642 100644 --- a/search/luceneresult.php +++ b/search/luceneresult.php @@ -36,14 +36,17 @@ class LuceneResult extends File { */ public function __construct(QueryHit $hit) { $this->id = (string)$hit->fileId; - $this->path = $this->getRelativePath($hit->path); + $this->path = $hit->path; $this->name = basename($this->path); $this->size = (int)$hit->size; $this->score = $hit->score; - $this->link = \OCP\Util::linkTo( - 'files', - 'index.php', - array('dir' => dirname($this->path), 'scrollto' => $this->name) + $dir = preg_replace("!/".$this->name."$!", "", $hit->path); + $this->link = \OC::$server->getURLGenerator()->linkToRoute( + 'files.view.index', + [ + 'dir' => $dir, + 'scrollto' => $this->name, + ] ); $this->permissions = $this->getPermissions($this->path); $this->modified = (int)$hit->mtime; @@ -53,7 +56,7 @@ public function __construct(QueryHit $hit) { protected function getRelativePath ($path) { $root = \OC::$server->getUserFolder(); return $root->getRelativePath($path); - } + } /** * Determine permissions for a given file path diff --git a/tests/unit/testcase.php b/tests/unit/testcase.php index e3d8ed57c..ac2d4b22b 100644 --- a/tests/unit/testcase.php +++ b/tests/unit/testcase.php @@ -71,11 +71,9 @@ public function setUp() { // create test user $this->userName = 'test'; - $user = $um->get($this->userName); - if ($user) { - $user->delete(); + if (!\OC_User::userExists($this->userName)) { + $um->createUser($this->userName, $this->userName); } - $um->createUser($this->userName, $this->userName); \OC_Util::tearDownFS(); $this->userSession->setUser(null); diff --git a/tests/unit/testsearchprovider.php b/tests/unit/testsearchprovider.php index 82d842f28..b9c07a24a 100644 --- a/tests/unit/testsearchprovider.php +++ b/tests/unit/testsearchprovider.php @@ -56,7 +56,7 @@ function testSearchLuceneResultContent($fileId, $name, $path, $size, $score, $mi $this->assertInstanceOf('OCA\Search_Lucene\Search\LuceneResult', $searchResult); $this->assertEquals($fileId, $searchResult->id); $this->assertEquals('lucene', $searchResult->type); - $this->assertEquals($path, $searchResult->path); + $this->assertEquals('/test/files'.$path, $searchResult->path); $this->assertEquals($name, $searchResult->name); $this->assertEquals($mimeType, $searchResult->mime_type); $this->assertEquals($size, $searchResult->size);