diff --git a/lib/Dav/Faces/FaceRoot.php b/lib/Dav/Faces/FaceRoot.php index 97b0d8625..6df6babfd 100644 --- a/lib/Dav/Faces/FaceRoot.php +++ b/lib/Dav/Faces/FaceRoot.php @@ -114,7 +114,7 @@ public function getChild($name): FacePhoto { } catch (DoesNotExistException $e) { throw new NotFound(); } - if ($detection->getClusterId() !== $this->cluster->getId()) { + if ($detection->getUserId() !== $this->user->getUID() || $detection->getClusterId() !== $this->cluster->getId()) { throw new NotFound(); } return new FacePhoto($this->detectionMapper, $detection, $this->rootFolder->getUserFolder($this->user->getUID()), $this->tagManager, $this->previewManager); @@ -131,6 +131,9 @@ public function childExists($name): bool { public function moveInto($targetName, $sourcePath, INode $sourceNode) { if ($sourceNode instanceof FacePhoto) { + if ($sourceNode->getFaceDetection()->getUserId() !== $this->user->getUID()) { + throw new Forbidden('Not allowed to move face detections of other users'); + } $sourceNode->getFaceDetection()->setClusterId($this->cluster->getId()); $this->detectionMapper->update($sourceNode->getFaceDetection()); return true; diff --git a/lib/Dav/Faces/PropFindPlugin.php b/lib/Dav/Faces/PropFindPlugin.php index 41721e2a1..d32bbdebe 100644 --- a/lib/Dav/Faces/PropFindPlugin.php +++ b/lib/Dav/Faces/PropFindPlugin.php @@ -20,6 +20,7 @@ use OCP\DB\Exception; use OCP\Files\DavUtil; use OCP\IPreview; +use OCP\IUserSession; use OCP\Security\ICrypto; use Psr\Log\LoggerInterface; use Sabre\DAV\Exception\Forbidden; @@ -49,6 +50,7 @@ public function __construct( private LoggerInterface $logger, private ITimeFactory $timeFactory, private IAppConfig $appConfig, + private IUserSession $userSession, ) { } @@ -61,13 +63,26 @@ public function initialize(Server $server): void { } + /** + * @return list + * @throws Exception + */ + private function getDetections(int $fileId): array { + // Detections and cluster titles are private to each user + $userId = $this->userSession->getUser()?->getUID(); + if ($userId === null) { + return []; + } + return $this->faceDetectionMapper->findByFileIdWithTitle($fileId, $userId); + } + public function propFind(PropFind $propFind, INode $node): void { if ($node instanceof FacePhoto) { $propFind->handle(self::FACE_DETECTIONS_PROPERTYNAME, function () use ($node) { return json_encode( array_map( fn (FaceDetectionWithTitle $face) => $face->toArray(), - $this->faceDetectionMapper->findByFileIdWithTitle($node->getFile()->getId()) + $this->getDetections($node->getFile()->getId()) ) ); }); @@ -102,7 +117,7 @@ public function propFind(PropFind $propFind, INode $node): void { return json_encode( array_map( fn (FaceDetectionWithTitle $face) => $face->toArray(), - $this->faceDetectionMapper->findByFileIdWithTitle($node->getId()), + $this->getDetections((int)$node->getId()), ) ); }); diff --git a/lib/Dav/Faces/UnassignedFacesHome.php b/lib/Dav/Faces/UnassignedFacesHome.php index a1d491d42..d38d8cf54 100644 --- a/lib/Dav/Faces/UnassignedFacesHome.php +++ b/lib/Dav/Faces/UnassignedFacesHome.php @@ -76,7 +76,7 @@ public function getChild($name): UnassignedFacePhoto { } catch (DoesNotExistException $e) { throw new NotFound(); } - if ($detection->getClusterId() !== -1) { + if ($detection->getUserId() !== $this->user->getUID() || $detection->getClusterId() !== -1) { throw new NotFound(); } diff --git a/lib/Db/FaceDetectionMapper.php b/lib/Db/FaceDetectionMapper.php index 939205429..5f2c28e3d 100644 --- a/lib/Db/FaceDetectionMapper.php +++ b/lib/Db/FaceDetectionMapper.php @@ -179,14 +179,16 @@ public function assocWithCluster(FaceDetection $faceDetection, FaceCluster $face /** * @param int $fileId + * @param string $userId * @return list<\OCA\Recognize\Db\FaceDetectionWithTitle> * @throws \OCP\DB\Exception */ - public function findByFileIdWithTitle(int $fileId) : array { + public function findByFileIdWithTitle(int $fileId, string $userId) : array { $qb = $this->db->getQueryBuilder(); $qb->select(array_merge(array_map(fn ($col) => 'd.'.$col, FaceDetection::$columns), ['c.title'])) ->from('recognize_face_detections', 'd') ->where($qb->expr()->eq('file_id', $qb->createPositionalParameter($fileId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('d.user_id', $qb->createPositionalParameter($userId, IQueryBuilder::PARAM_STR))) ->leftJoin('d', 'recognize_face_clusters', 'c', $qb->expr()->eq('d.cluster_id', 'c.id')); /** @var list<\OCA\Recognize\Db\FaceDetectionWithTitle> $entities */ $entities = $this->findEntities($qb);