diff --git a/lib/Controller/ApiBase.php b/lib/Controller/ApiBase.php index 7a882d30..faa3a210 100644 --- a/lib/Controller/ApiBase.php +++ b/lib/Controller/ApiBase.php @@ -152,13 +152,19 @@ class ApiBase extends Controller } /** - * Get a file with ID from user's folder. - * - * @param int $fileId - * - * @return null|File + * Get a file with ID for the current user. */ - protected function getUserFile(int $id) + protected function getUserFile(int $fileId): ?File + { + return $this->getUserFolderFile($fileId) ?? + $this->getAlbumFile($fileId) ?? + $this->getShareFile($fileId); + } + + /** + * Get a file with ID from user's folder. + */ + protected function getUserFolderFile(int $id): ?File { $user = $this->userSession->getUser(); if (null === $user) { @@ -166,23 +172,49 @@ class ApiBase extends Controller } $userFolder = $this->rootFolder->getUserFolder($user->getUID()); - // Check for permissions and get numeric Id - $file = $userFolder->getById($id); - if (0 === \count($file)) { + return $this->getOneFileFromFolder($userFolder, $id); + } + + /** + * Get a file with ID from an album. + */ + protected function getAlbumFile(int $id): ?File + { + $user = $this->userSession->getUser(); + if (null === $user) { + return null; + } + $uid = $user->getUID(); + + if (!$this->timelineQuery->albumHasUserFile($uid, $id)) { return null; } - // Check if node is a file - if (!$file[0] instanceof File) { + return $this->getOneFileFromFolder($this->rootFolder, $id); + } + + /** + * Get a file with ID from a public share. + * + * @param int $fileId + */ + protected function getShareFile(int $id): ?File + { + $token = $this->getShareToken(); + if (null === $token) { return null; } - // Check read permission - if (!($file[0]->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + try { + $share = $this->shareManager->getShareByToken($token)->getNode(); // throws exception if not found + if (!$share instanceof Folder) { + return null; + } + } catch (\Exception $e) { return null; } - return $file[0]; + return $this->getOneFileFromFolder($share, $id); } protected function isRecursive() @@ -233,4 +265,28 @@ class ApiBase extends Controller { return \OCA\Memories\Util::recognizeIsEnabled($this->appManager); } + + /** + * Helper to get one file or null from a fiolder. + */ + private function getOneFileFromFolder(Folder $folder, int $id): ?File + { + // Check for permissions and get numeric Id + $file = $folder->getById($id); + if (0 === \count($file)) { + return null; + } + + // Check if node is a file + if (!$file[0] instanceof File) { + return null; + } + + // Check read permission + if (!($file[0]->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + return null; + } + + return $file[0]; + } } diff --git a/lib/Controller/ImageController.php b/lib/Controller/ImageController.php index b15edbf9..919a445f 100644 --- a/lib/Controller/ImageController.php +++ b/lib/Controller/ImageController.php @@ -33,7 +33,9 @@ class ImageController extends ApiBase /** * @NoAdminRequired * - * Get image info for one file + * @PublicPage + * + * Get EXIF info for an image with file id * * @param string fileid */ @@ -49,7 +51,8 @@ class ImageController extends ApiBase $info = $this->timelineQuery->getInfoById($file->getId(), $basic); // Get latest exif data if requested - if ($this->request->getParam('current', false)) { + // Allow this ony for logged in users + if ($this->request->getParam('current', false) && null !== $this->userSession->getUser()) { $info['current'] = Exif::getExifFromFile($file); } diff --git a/lib/Db/TimelineQueryAlbums.php b/lib/Db/TimelineQueryAlbums.php index 2b8e0544..bf3e2ff2 100644 --- a/lib/Db/TimelineQueryAlbums.php +++ b/lib/Db/TimelineQueryAlbums.php @@ -116,11 +116,42 @@ trait TimelineQueryAlbums return $dayIds; } + /** + * Check if a file belongs to a user through an album. + */ + public function albumHasUserFile(string $uid, int $fileId) + { + $query = $this->connection->getQueryBuilder(); + $query->select('paf.album_id')->from('photos_albums_files', 'paf')->where( + $query->expr()->andX( + $query->expr()->eq('paf.file_id', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)), + $query->expr()->orX( + $query->expr()->eq('pa.album_id', 'paf.album_id'), + $query->expr()->eq('pc.album_id', 'paf.album_id'), + ), + ) + ); + + // Check if user-owned album or shared album + $query->leftJoin('paf', 'photos_albums', 'pa', $query->expr()->andX( + $query->expr()->eq('pa.album_id', 'paf.album_id'), + $query->expr()->eq('pa.user', $query->createNamedParameter($uid)), + )); + + // Join to shared album + $query->leftJoin('paf', $this->collaboratorsTable(), 'pc', $query->expr()->andX( + $query->expr()->eq('pc.album_id', 'paf.album_id'), + $query->expr()->eq('pc.collaborator_id', $query->createNamedParameter($uid)), + )); + + return false !== $query->executeQuery()->fetchOne(); + } + /** * Get album if allowed. Also check if album is shared with user. * - * @param string $uid UID of CURRENT user - * @param string $albumId $user/$name where $user is the OWNER of the album + * @param string $uid UID of CURRENT user + * @param string $albumId $user/$name where $user is the OWNER of the album */ private function getAlbumIfAllowed(string $uid, string $albumId) {