From a46aa7f5bb6388ee2de3d4976b7a6dad8c016c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Viguier?= Date: Thu, 6 Apr 2023 16:11:17 +0200 Subject: [PATCH] Remove requirement of Auth in photo upload, pass ownerId as argument (#1787) --- app/Actions/Import/Exec.php | 4 +-- app/Actions/Import/FromServer.php | 11 ++++---- app/Actions/Import/FromUrl.php | 11 ++++---- app/Actions/Photo/Create.php | 4 +-- .../Photo/Strategies/AbstractAddStrategy.php | 16 ++++------- .../Strategies/AddPhotoPartnerStrategy.php | 5 +++- .../Strategies/AddStrategyParameters.php | 6 +++- app/Actions/Photo/Strategies/ImportMode.php | 28 +++---------------- app/Console/Commands/Sync.php | 4 +-- app/Http/Controllers/ImportController.php | 12 ++++++-- app/Http/Controllers/PhotoController.php | 13 ++++++--- 11 files changed, 54 insertions(+), 60 deletions(-) diff --git a/app/Actions/Import/Exec.php b/app/Actions/Import/Exec.php index d0e2a4d5a85..83a8fe2f76d 100644 --- a/app/Actions/Import/Exec.php +++ b/app/Actions/Import/Exec.php @@ -49,11 +49,11 @@ class Exec * @param bool $enableCLIFormatting determines whether the output shall be formatted for CLI or as JSON * @param int $memLimit the threshold when a memory warning shall be reported; `0` means unlimited */ - public function __construct(ImportMode $importMode, bool $enableCLIFormatting, int $memLimit = 0) + public function __construct(ImportMode $importMode, int $intendedOwnerId, bool $enableCLIFormatting, int $memLimit = 0) { Session::forget('cancel'); $this->importMode = $importMode; - $this->photoCreate = new PhotoCreate($importMode); + $this->photoCreate = new PhotoCreate($importMode, $intendedOwnerId); $this->albumCreate = new AlbumCreate(); $this->enableCLIFormatting = $enableCLIFormatting; $this->memLimit = $memLimit; diff --git a/app/Actions/Import/FromServer.php b/app/Actions/Import/FromServer.php index 817fa2babf1..d8368161b28 100644 --- a/app/Actions/Import/FromServer.php +++ b/app/Actions/Import/FromServer.php @@ -10,15 +10,16 @@ class FromServer { /** - * @param string[] $paths the server path to import from - * @param Album|null $album the album to import into - * @param ImportMode $importMode the import mode + * @param string[] $paths the server path to import from + * @param Album|null $album the album to import into + * @param ImportMode $importMode the import mode + * @param int $intendedOwnerId the intended owner of those pictures * * @return StreamedResponse */ - public function do(array $paths, ?Album $album, ImportMode $importMode): StreamedResponse + public function do(array $paths, ?Album $album, ImportMode $importMode, int $intendedOwnerId): StreamedResponse { - $exec = new Exec($importMode, false, $this->determineMemLimit()); + $exec = new Exec($importMode, $intendedOwnerId, false, $this->determineMemLimit()); $response = new StreamedResponse(); $response->headers->set('Content-Type', 'application/json'); diff --git a/app/Actions/Import/FromUrl.php b/app/Actions/Import/FromUrl.php index 749de02bab7..44876119940 100644 --- a/app/Actions/Import/FromUrl.php +++ b/app/Actions/Import/FromUrl.php @@ -26,19 +26,20 @@ class FromUrl * * @param string[] $urls * @param Album|null $album + * @param int $intendedOwnerId * * @return Collection the collection of imported photos * * @throws MassImportException */ - public function do(array $urls, ?Album $album): Collection + public function do(array $urls, ?Album $album, int $intendedOwnerId): Collection { $result = new Collection(); $exceptions = []; - $create = new Create(new ImportMode( - true, - Configs::getValueAsBool('skip_duplicates') - )); + $create = new Create( + new ImportMode(deleteImported: true, skipDuplicates: Configs::getValueAsBool('skip_duplicates')), + $intendedOwnerId + ); foreach ($urls as $url) { try { diff --git a/app/Actions/Photo/Create.php b/app/Actions/Photo/Create.php index cedc7c9f481..d75520e1836 100644 --- a/app/Actions/Photo/Create.php +++ b/app/Actions/Photo/Create.php @@ -34,9 +34,9 @@ class Create /** @var AddStrategyParameters the strategy parameters prepared and compiled by this class */ protected AddStrategyParameters $strategyParameters; - public function __construct(?ImportMode $importMode) + public function __construct(?ImportMode $importMode, int $intendedOwnerId) { - $this->strategyParameters = new AddStrategyParameters($importMode); + $this->strategyParameters = new AddStrategyParameters($importMode, $intendedOwnerId); } /** diff --git a/app/Actions/Photo/Strategies/AbstractAddStrategy.php b/app/Actions/Photo/Strategies/AbstractAddStrategy.php index 05b8026b386..ee28afb28b9 100644 --- a/app/Actions/Photo/Strategies/AbstractAddStrategy.php +++ b/app/Actions/Photo/Strategies/AbstractAddStrategy.php @@ -6,17 +6,13 @@ use App\Exceptions\ModelDBException; use App\Exceptions\UnauthenticatedException; use App\Models\Photo; -use Illuminate\Support\Facades\Auth; abstract class AbstractAddStrategy { - protected AddStrategyParameters $parameters; - protected Photo $photo; - - protected function __construct(AddStrategyParameters $parameters, Photo $photo) - { - $this->parameters = $parameters; - $this->photo = $photo; + protected function __construct( + protected AddStrategyParameters $parameters, + protected Photo $photo + ) { } /** @@ -116,9 +112,7 @@ protected function setParentAndOwnership(): void // Avoid unnecessary DB request, when we access the album of a // photo later (e.g. when a notification is sent). $this->photo->setRelation('album', null); - /** @var int */ - $userId = Auth::id() ?? throw new UnauthenticatedException(); - $this->photo->owner_id = $userId; + $this->photo->owner_id = $this->parameters->intendedOwnerId; } } } diff --git a/app/Actions/Photo/Strategies/AddPhotoPartnerStrategy.php b/app/Actions/Photo/Strategies/AddPhotoPartnerStrategy.php index 21ce2fafeeb..974b06f6728 100644 --- a/app/Actions/Photo/Strategies/AddPhotoPartnerStrategy.php +++ b/app/Actions/Photo/Strategies/AddPhotoPartnerStrategy.php @@ -46,7 +46,10 @@ public function do(): Photo // "steals away" the stored video file from the existing video entity // and moves it to the correct destination of a live partner for the // photo. - $parameters = new AddStrategyParameters(new ImportMode(true)); + $parameters = new AddStrategyParameters( + new ImportMode(deleteImported: true), + $this->parameters->intendedOwnerId + ); $videoStrategy = new AddVideoPartnerStrategy( $parameters, $this->existingVideo->size_variants->getOriginal()->getFile(), diff --git a/app/Actions/Photo/Strategies/AddStrategyParameters.php b/app/Actions/Photo/Strategies/AddStrategyParameters.php index ac282897228..d4a4f3f021c 100644 --- a/app/Actions/Photo/Strategies/AddStrategyParameters.php +++ b/app/Actions/Photo/Strategies/AddStrategyParameters.php @@ -9,6 +9,9 @@ class AddStrategyParameters { public ImportMode $importMode; + /** @var int Indicates the intended owner of the image. */ + public int $intendedOwnerId; + /** @var Album|null the intended parent album */ public ?Album $album = null; @@ -21,8 +24,9 @@ class AddStrategyParameters /** @var Extractor|null the extracted EXIF information */ public ?Extractor $exifInfo = null; - public function __construct(ImportMode $importMode) + public function __construct(ImportMode $importMode, int $intendedOwnerId) { $this->importMode = $importMode; + $this->intendedOwnerId = $intendedOwnerId; } } diff --git a/app/Actions/Photo/Strategies/ImportMode.php b/app/Actions/Photo/Strategies/ImportMode.php index 781ca19fe81..fae26a4215a 100644 --- a/app/Actions/Photo/Strategies/ImportMode.php +++ b/app/Actions/Photo/Strategies/ImportMode.php @@ -4,32 +4,12 @@ class ImportMode { - protected bool $deleteImported = false; - protected bool $skipDuplicates = false; - protected bool $importViaSymlink = false; - protected bool $resyncMetadata = false; - public function __construct( - bool $deleteImported = false, - bool $skipDuplicates = false, - bool $importViaSymlink = false, - bool $resyncMetadata = false + protected readonly bool $deleteImported = false, + protected readonly bool $skipDuplicates = false, + protected bool $importViaSymlink = false, + protected bool $resyncMetadata = false ) { - $this->setMode( - $deleteImported, $skipDuplicates, $importViaSymlink, $resyncMetadata - ); - } - - public function setMode( - bool $deleteImported = false, - bool $skipDuplicates = false, - bool $importViaSymlink = false, - bool $resyncMetadata = false - ): void { - $this->deleteImported = $deleteImported; - $this->skipDuplicates = $skipDuplicates; - $this->importViaSymlink = $importViaSymlink; - $this->resyncMetadata = $resyncMetadata; // avoid incompatible settings (delete originals takes precedence over symbolic links) if ($deleteImported) { $this->importViaSymlink = false; diff --git a/app/Console/Commands/Sync.php b/app/Console/Commands/Sync.php index d954e86bf28..b55e66a9329 100644 --- a/app/Console/Commands/Sync.php +++ b/app/Console/Commands/Sync.php @@ -11,7 +11,6 @@ use App\Models\Configs; use Exception; use Illuminate\Console\Command; -use Illuminate\Support\Facades\Auth; use Symfony\Component\Console\Exception\ExceptionInterface as SymfonyConsoleException; class Sync extends Command @@ -105,12 +104,11 @@ public function handle(): int $importViaSymlink, $resyncMetadata ), + $owner_id, true, 0 ); - Auth::loginUsingId($owner_id); - $this->info('Start syncing.'); foreach ($directories as $directory) { diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 1b6145b290f..1dcd8322451 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -5,6 +5,7 @@ use App\Actions\Import\FromServer; use App\Actions\Import\FromUrl; use App\Exceptions\MassImportException; +use App\Exceptions\UnauthenticatedException; use App\Http\Requests\Import\CancelImportServerRequest; use App\Http\Requests\Import\ImportFromUrlRequest; use App\Http\Requests\Import\ImportServerRequest; @@ -13,6 +14,7 @@ use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Routing\Controller; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; use Symfony\Component\HttpFoundation\StreamedResponse; @@ -58,7 +60,10 @@ class ImportController extends Controller */ public function url(ImportFromUrlRequest $request, FromUrl $fromUrl): AnonymousResourceCollection { - $photos = $fromUrl->do($request->urls(), $request->album()); + /** @var int $currentUserId */ + $currentUserId = Auth::id() ?? throw new UnauthenticatedException(); + + $photos = $fromUrl->do($request->urls(), $request->album(), $currentUserId); return PhotoResource::collection($photos); } @@ -71,8 +76,11 @@ public function url(ImportFromUrlRequest $request, FromUrl $fromUrl): AnonymousR */ public function server(ImportServerRequest $request, FromServer $fromServer): StreamedResponse { + /** @var int $currentUserId */ + $currentUserId = Auth::id() ?? throw new UnauthenticatedException(); + return $fromServer->do( - $request->paths(), $request->album(), $request->importMode() + $request->paths(), $request->album(), $request->importMode(), $currentUserId ); } diff --git a/app/Http/Controllers/PhotoController.php b/app/Http/Controllers/PhotoController.php index 02327e2f309..d4eae2ba579 100644 --- a/app/Http/Controllers/PhotoController.php +++ b/app/Http/Controllers/PhotoController.php @@ -12,6 +12,7 @@ use App\Contracts\Exceptions\LycheeException; use App\Exceptions\MediaFileOperationException; use App\Exceptions\ModelDBException; +use App\Exceptions\UnauthenticatedException; use App\Http\Requests\Photo\AddPhotoRequest; use App\Http\Requests\Photo\ArchivePhotosRequest; use App\Http\Requests\Photo\ClearSymLinkRequest; @@ -37,6 +38,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; class PhotoController extends Controller @@ -98,6 +100,9 @@ public function getRandom(): PhotoResource */ public function add(AddPhotoRequest $request): PhotoResource { + /** @var int $currentUserId */ + $currentUserId = Auth::id() ?? throw new UnauthenticatedException(); + // This code is a nasty work-around which should not exist. // PHP stores a temporary copy of the uploaded file without a file // extension. @@ -127,10 +132,10 @@ public function add(AddPhotoRequest $request): PhotoResource // As the file has been uploaded, the (temporary) source file shall be // deleted - $create = new Create(new ImportMode( - true, - Configs::getValueAsBool('skip_duplicates') - )); + $create = new Create( + new ImportMode(deleteImported: true, skipDuplicates: Configs::getValueAsBool('skip_duplicates')), + $currentUserId + ); $photo = $create->add($copiedFile, $request->album()); $isNew = $photo->created_at->toIso8601String() === $photo->updated_at->toIso8601String();