From 85f23596539cd21b8d851fba6d081a0d022cfc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Viguier?= Date: Sat, 16 Nov 2024 00:30:36 +0100 Subject: [PATCH] Fix error 403 on access directly password protected albums (#2688) * fix error 503 on access directly password protected albums * fix phpstan * remove deprecated comment --- app/Http/Controllers/VueController.php | 34 ++++++++++++++- app/View/Components/Meta.php | 59 +++++++++++++++++--------- phpstan.neon | 2 +- 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/VueController.php b/app/Http/Controllers/VueController.php index eb3cca0fa39..b01cb15544b 100644 --- a/app/Http/Controllers/VueController.php +++ b/app/Http/Controllers/VueController.php @@ -4,9 +4,12 @@ use App\Contracts\Models\AbstractAlbum; use App\Exceptions\Internal\InvalidSmartIdException; +use App\Exceptions\UnauthorizedException; use App\Factories\AlbumFactory; +use App\Models\Extensions\BaseAlbum; use App\Models\Photo; use App\Policies\AlbumPolicy; +use App\Policies\PhotoPolicy; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\View; @@ -20,6 +23,9 @@ */ class VueController extends Controller { + public const ACCESS = 'access'; + public const PASSWORD = 'password'; + /** * @param string|null $albumId * @param string|null $photoId @@ -37,13 +43,14 @@ public function view(?string $albumId = null, ?string $photoId = null): View try { if ($albumId !== null) { $album = $albumFactory->findAbstractAlbumOrFail($albumId, false); - Gate::authorize(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]); + + session()->now('access', $this->check($album)); session()->now('album', $album); } if ($photoId !== null) { $photo = Photo::findOrFail($photoId); - Gate::authorize(\PhotoPolicy::CAN_SEE, [Photo::class, $photo]); + Gate::authorize(PhotoPolicy::CAN_SEE, [Photo::class, $photo]); session()->now('photo', $photo); } } catch (ModelNotFoundException) { @@ -52,4 +59,27 @@ public function view(?string $albumId = null, ?string $photoId = null): View return view('vueapp'); } + + /** + * Check if user can access the album. + * + * @param AbstractAlbum $album + * + * @return bool true if access, false if password required + * + * @throws UnauthorizedException if user is not authorized at all + */ + private function check(AbstractAlbum $album): bool + { + $result = Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $album]); + if ( + !$result && + $album instanceof BaseAlbum && + $album->public_permissions()?->password !== null + ) { + return false; + } + + return $result ? true : throw new UnauthorizedException(); + } } \ No newline at end of file diff --git a/app/View/Components/Meta.php b/app/View/Components/Meta.php index c2b7b25992e..6b94fd6a120 100644 --- a/app/View/Components/Meta.php +++ b/app/View/Components/Meta.php @@ -31,6 +31,10 @@ class Meta extends Component public string $userCssUrl; public string $userJsUrl; + private bool $access = true; + private ?AbstractAlbum $album = null; + private ?Photo $photo = null; + /** * Initialize the footer once for all. * @@ -38,34 +42,49 @@ class Meta extends Component */ public function __construct() { + // default data + $this->siteOwner = Configs::getValueAsString('site_owner'); + $this->pageUrl = url()->current(); + $this->rssEnable = Configs::getValueAsBool('rss_enable'); + $this->userCssUrl = self::getUserCustomFiles('user.css'); + $this->userJsUrl = self::getUserCustomFiles('custom.js'); + $this->baseUrl = url('/'); + $this->pageTitle = Configs::getValueAsString('site_title'); $this->pageDescription = ''; - $this->imageUrl = ''; + $this->imageUrl = Configs::getValueAsString('landing_background'); + // processing photo and album data + if (session()->has('access')) { + $this->access = session()->get('access'); + session()->forget('access'); + } if (session()->has('album')) { - /** @var AbstractAlbum $album */ - $album = session()->get('album'); - $this->pageTitle = $album->title; - if ($album instanceof BaseAlbum) { - $this->pageDescription = $album->description ?? Configs::getValueAsString('site_title'); - } - $this->imageUrl = $this->getHeaderUrl($album) ?? ''; + $this->album = session()->get('album'); + session()->forget('album'); } - if (session()->has('photo')) { - /** @var Photo $photo */ - $photo = session()->get('photo'); - $this->pageTitle = $photo->title; - $this->pageDescription = $photo->description ?? Configs::getValueAsString('site_title'); - $this->imageUrl = $photo->size_variants->getSmall()->url; + $this->photo = session()->get('photo'); + session()->forget('photo'); } - $this->siteOwner = Configs::getValueAsString('site_owner'); - $this->pageUrl = url()->current(); - $this->rssEnable = Configs::getValueAsBool('rss_enable'); - $this->userCssUrl = self::getUserCustomFiles('user.css'); - $this->userJsUrl = self::getUserCustomFiles('custom.js'); - $this->baseUrl = url('/'); + if ($this->access === false) { + return; + } + + if ($this->album !== null) { + $this->pageTitle = $this->album->title; + if ($this->album instanceof BaseAlbum) { + $this->pageDescription = $this->album->description ?? Configs::getValueAsString('site_title'); + } + $this->imageUrl = $this->getHeaderUrl($this->album) ?? $this->imageUrl; + } + + if ($this->photo !== null) { + $this->pageTitle = $this->photo->title; + $this->pageDescription = $this->photo->description ?? Configs::getValueAsString('site_title'); + $this->imageUrl = $this->photo->size_variants->getSmall()->url; + } } /** diff --git a/phpstan.neon b/phpstan.neon index 3d26d404fb0..9da91257f0d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -165,4 +165,4 @@ parameters: - tests - - message: '#Dynamic call to static method Illuminate\\Session\\Store::(has|get|now)\(\).#' + message: '#Dynamic call to static method Illuminate\\Session\\Store::(has|get|now|forget)\(\).#'