From 9c04921a8c28c18ef757f2d43ba35e7e2a7f1a4b Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 16 Oct 2020 20:17:08 +0200 Subject: Feature: Share private bookmarks using a URL containing a private key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add a share link next to « Permalink » in linklist (using share icon from fork awesome) - This link generates a private key associated to the bookmark - Accessing the bookmark while logged out with the proper key will display it Fixes #475 --- application/bookmark/BookmarkFileService.php | 7 ++++-- application/bookmark/BookmarkServiceInterface.php | 5 +++-- .../controller/admin/ManageShaareController.php | 26 ++++++++++++++++++++++ .../controller/visitor/BookmarkListController.php | 4 +++- 4 files changed, 37 insertions(+), 5 deletions(-) (limited to 'application') diff --git a/application/bookmark/BookmarkFileService.php b/application/bookmark/BookmarkFileService.php index eb7899bf..14b3d620 100644 --- a/application/bookmark/BookmarkFileService.php +++ b/application/bookmark/BookmarkFileService.php @@ -97,12 +97,15 @@ class BookmarkFileService implements BookmarkServiceInterface /** * @inheritDoc */ - public function findByHash(string $hash): Bookmark + public function findByHash(string $hash, string $privateKey = null): Bookmark { $bookmark = $this->bookmarkFilter->filter(BookmarkFilter::$FILTER_HASH, $hash); // PHP 7.3 introduced array_key_first() to avoid this hack $first = reset($bookmark); - if (! $this->isLoggedIn && $first->isPrivate()) { + if (!$this->isLoggedIn + && $first->isPrivate() + && (empty($privateKey) || $privateKey !== $first->getAdditionalContentEntry('private_key')) + ) { throw new Exception('Not authorized'); } diff --git a/application/bookmark/BookmarkServiceInterface.php b/application/bookmark/BookmarkServiceInterface.php index 37a54d03..9fa61533 100644 --- a/application/bookmark/BookmarkServiceInterface.php +++ b/application/bookmark/BookmarkServiceInterface.php @@ -20,13 +20,14 @@ interface BookmarkServiceInterface /** * Find a bookmark by hash * - * @param string $hash + * @param string $hash Bookmark's hash + * @param string|null $privateKey Optional key used to access private links while logged out * * @return Bookmark * * @throws \Exception */ - public function findByHash(string $hash): Bookmark; + public function findByHash(string $hash, string $privateKey = null); /** * @param $url diff --git a/application/front/controller/admin/ManageShaareController.php b/application/front/controller/admin/ManageShaareController.php index 908ebae3..e490f85a 100644 --- a/application/front/controller/admin/ManageShaareController.php +++ b/application/front/controller/admin/ManageShaareController.php @@ -320,6 +320,32 @@ class ManageShaareController extends ShaarliAdminController return $this->redirectFromReferer($request, $response, ['/pin'], ['pin']); } + /** + * GET /admin/shaare/private/{hash} - Attach a private key to given bookmark, then redirect to the sharing URL. + */ + public function sharePrivate(Request $request, Response $response, array $args): Response + { + $this->checkToken($request); + + $hash = $args['hash'] ?? ''; + $bookmark = $this->container->bookmarkService->findByHash($hash); + + if ($bookmark->isPrivate() !== true) { + return $this->redirect($response, '/shaare/' . $hash); + } + + if (empty($bookmark->getAdditionalContentEntry('private_key'))) { + $privateKey = bin2hex(random_bytes(16)); + $bookmark->addAdditionalContentEntry('private_key', $privateKey); + $this->container->bookmarkService->set($bookmark); + } + + return $this->redirect( + $response, + '/shaare/' . $hash . '?key=' . $bookmark->getAdditionalContentEntry('private_key') + ); + } + /** * Helper function used to display the shaare form whether it's a new or existing bookmark. * diff --git a/application/front/controller/visitor/BookmarkListController.php b/application/front/controller/visitor/BookmarkListController.php index 5267c8f5..78c474c9 100644 --- a/application/front/controller/visitor/BookmarkListController.php +++ b/application/front/controller/visitor/BookmarkListController.php @@ -137,8 +137,10 @@ class BookmarkListController extends ShaarliVisitorController */ public function permalink(Request $request, Response $response, array $args): Response { + $privateKey = $request->getParam('key'); + try { - $bookmark = $this->container->bookmarkService->findByHash($args['hash']); + $bookmark = $this->container->bookmarkService->findByHash($args['hash'], $privateKey); } catch (BookmarkNotFoundException $e) { $this->assignView('error_message', $e->getMessage()); -- cgit v1.2.3