Skip to content

Commit

Permalink
Feature/#75698/scraper (#71)
Browse files Browse the repository at this point in the history
* Add new files related to AssetFile creation and routing

This update introduces new DTOs for handling the creation, validation, and routing of AssetFiles. These new additions, including `AssetFileSysCreateDto` and `AssetFileController.php`, facilitate asset creation and routing in the system. The included access control rules ensure authorized access to these functionalities.

* Add ExtStorage configuration key and asset handling

Integrated the 'ext_storage' configuration key into ExtSystemConfiguration to facilitate external storage in asset handling. Additional error handling mechanisms have also been implemented in the AssetFileController, AssetSysFacade, and AssetSysFactory to ensure data validity and reliability. Added validations for the newly created AssetFile.

* Replace getClient with getApiClient in test cases

fix tests
  • Loading branch information
TomasHermanek authored Dec 18, 2023
1 parent fa21690 commit d5fb1d6
Show file tree
Hide file tree
Showing 29 changed files with 339 additions and 69 deletions.
62 changes: 62 additions & 0 deletions src/Controller/Api/Sys/V1/AssetFileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Controller\Api\Sys\V1;

use AnzuSystems\CommonBundle\Exception\ValidationException;
use AnzuSystems\CommonBundle\Model\OpenApi\Response\OAResponse;
use AnzuSystems\CommonBundle\Model\OpenApi\Response\OAResponseCreated;
use AnzuSystems\CommonBundle\Model\OpenApi\Response\OAResponseValidation;
use AnzuSystems\CoreDamBundle\Controller\Api\AbstractApiController;
use AnzuSystems\CoreDamBundle\Domain\Asset\AssetSysFacade;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Exception\InvalidMimeTypeException;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetFile\AssetFileSysCreateDto;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetFile\AssetFileSysDetailDecorator;
use AnzuSystems\CoreDamBundle\Security\Permission\DamPermissions;
use AnzuSystems\SerializerBundle\Attributes\SerializeParam;
use Doctrine\ORM\NonUniqueResultException;
use League\Flysystem\FilesystemException;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

#[OA\Tag('AssetFile')]
#[Route('/asset-file', 'sys_asset_file_')]
final class AssetFileController extends AbstractApiController
{
public function __construct(
private readonly AssetSysFacade $assetSysFacade
) {
}

/**
* @throws FilesystemException
* @throws ValidationException
* @throws InvalidMimeTypeException
* @throws NonUniqueResultException
*/
#[Route('', 'create', methods: [Request::METHOD_POST])]
#[OAResponse(AssetFileSysDetailDecorator::class), OAResponseValidation, OAResponseCreated]
public function create(#[SerializeParam] AssetFileSysCreateDto $dto): JsonResponse
{
$this->denyAccessUnlessGranted(DamPermissions::DAM_ASSET_CREATE, $dto);

return $this->okResponse(
AssetFileSysDetailDecorator::getInstance($this->assetSysFacade->createFromDto($dto))
);
}

#[Route('/{assetFile}', 'get_one', methods: [Request::METHOD_GET])]
#[OAResponse(AssetFileSysDetailDecorator::class)]
public function getOne(AssetFile $assetFile): JsonResponse
{
$this->denyAccessUnlessGranted(DamPermissions::DAM_ASSET_VIEW, $assetFile->getAsset());

return $this->okResponse(
AssetFileSysDetailDecorator::getInstance($assetFile)
);
}
}
1 change: 1 addition & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ private function addExtSystemSection(): NodeDefinition
->arrayPrototype()
->children()
->scalarNode('id')->end()
->scalarNode(ExtSystemConfiguration::EXT_STORAGE_KEY)->end()
->append($this->addExtSystemAssetExternalProvidersSection())
->append($this->addFileExtSystemSection(AssetType::Image))
->append($this->addFileExtSystemSection(AssetType::Audio))
Expand Down
49 changes: 49 additions & 0 deletions src/Domain/Asset/AssetSysFacade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Domain\Asset;

use AnzuSystems\CommonBundle\Exception\ValidationException;
use AnzuSystems\CommonBundle\Validator\Validator;
use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileManagerProvider;
use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileMessageDispatcher;
use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileStatusFacadeProvider;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Exception\InvalidMimeTypeException;
use AnzuSystems\CoreDamBundle\FileSystem\FileSystemProvider;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetFile\AssetFileSysCreateDto;
use AnzuSystems\CoreDamBundle\Traits\IndexManagerAwareTrait;
use Doctrine\ORM\NonUniqueResultException;
use League\Flysystem\FilesystemException;

final class AssetSysFacade
{
use IndexManagerAwareTrait;

public function __construct(
private readonly Validator $validator,
private readonly AssetSysFactory $assetSysFactory,
private readonly AssetFileManagerProvider $assetFileManagerProvider,
private readonly AssetFileMessageDispatcher $assetFileMessageDispatcher,
private readonly AssetFileStatusFacadeProvider $facadeProvider,
private readonly FileSystemProvider $fileSystemProvider,
) {
}

/**
* @throws FilesystemException
* @throws ValidationException
* @throws InvalidMimeTypeException
* @throws NonUniqueResultException
*/
public function createFromDto(AssetFileSysCreateDto $dto): AssetFile
{
$this->validator->validate($dto);
$assetFile = $this->assetSysFactory->createFromDto($dto);
$this->facadeProvider->getStatusFacade($assetFile)->storeAndProcess($assetFile);
$this->fileSystemProvider->getTmpFileSystem()->clearPaths();

return $assetFile;
}
}
38 changes: 38 additions & 0 deletions src/Domain/Asset/AssetSysFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Domain\Asset;

use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileFactory;
use AnzuSystems\CoreDamBundle\Domain\Configuration\ExtSystemConfigurationProvider;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Exception\InvalidMimeTypeException;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetFile\AssetFileSysCreateDto;
use Doctrine\ORM\NonUniqueResultException;
use League\Flysystem\FilesystemException;

final readonly class AssetSysFactory
{
public function __construct(
private AssetFileFactory $assetFileFactory,
private ExtSystemConfigurationProvider $configurationProvider,
) {
}

/**
* @throws FilesystemException
* @throws NonUniqueResultException
* @throws InvalidMimeTypeException
*/
public function createFromDto(AssetFileSysCreateDto $dto): AssetFile
{
$configuration = $this->configurationProvider->getExtSystemConfiguration($dto->getExtSystem()->getSlug());

return $this->assetFileFactory->createAssetFileForStorage(
storageName: $configuration->getExtStorage(),
filePath: $dto->getPath(),
licence: $dto->getLicence()
);
}
}
8 changes: 8 additions & 0 deletions src/Model/Configuration/ExtSystemConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ final class ExtSystemConfiguration
{
public const ID_KEY = 'id';
public const ASSET_EXTERNAL_PROVIDERS_KEY = 'asset_external_providers';
public const EXT_STORAGE_KEY = 'ext_storage';

public function __construct(
private readonly int $id,
private readonly string $extStorage,
/** @var ArrayCollection<string, ExtSystemAssetExternalProviderConfiguration> */
private readonly ArrayCollection $assetExternalProviders,
private readonly ExtSystemAudioTypeConfiguration $audio,
Expand All @@ -35,6 +37,7 @@ public static function getFromArrayConfiguration(array $config): self

return new self(
$config[self::ID_KEY] ?? 0,
$config[self::EXT_STORAGE_KEY] ?? '',
$assetExternalProviders,
ExtSystemAudioTypeConfiguration::getFromArrayConfiguration($config[AssetType::Audio->toString()] ?? []),
ExtSystemVideoTypeConfiguration::getFromArrayConfiguration($config[AssetType::Video->toString()] ?? []),
Expand Down Expand Up @@ -76,6 +79,11 @@ public function getDocument(): ExtSystemAssetTypeConfiguration
return $this->document;
}

public function getExtStorage(): string
{
return $this->extStorage;
}

/**
* @throws AnzuException
*/
Expand Down
52 changes: 52 additions & 0 deletions src/Model/Dto/AssetFile/AssetFileSysCreateDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Model\Dto\AssetFile;

use AnzuSystems\CommonBundle\Exception\ValidationException;
use AnzuSystems\CoreDamBundle\Entity\AssetLicence;
use AnzuSystems\CoreDamBundle\Entity\ExtSystem;
use AnzuSystems\CoreDamBundle\Entity\Interfaces\ExtSystemInterface;
use AnzuSystems\SerializerBundle\Attributes\Serialize;
use AnzuSystems\SerializerBundle\Handler\Handlers\EntityIdHandler;
use Symfony\Component\Validator\Constraints as Assert;

final class AssetFileSysCreateDto implements ExtSystemInterface
{
#[Serialize]
#[Assert\NotBlank(message: ValidationException::ERROR_FIELD_EMPTY)]
#[Assert\Length(max: 192, maxMessage: ValidationException::ERROR_FIELD_LENGTH_MAX)]
private string $path;

#[Serialize(handler: EntityIdHandler::class)]
#[Assert\NotBlank(message: ValidationException::ERROR_FIELD_EMPTY)]
private AssetLicence $licence;

public function getPath(): string
{
return $this->path;
}

public function setPath(string $path): self
{
$this->path = $path;
return $this;
}

public function getLicence(): AssetLicence
{
return $this->licence;
}

public function setLicence(AssetLicence $licence): self
{
$this->licence = $licence;
return $this;
}

public function getExtSystem(): ExtSystem
{
return $this->licence->getExtSystem();
}
}
58 changes: 58 additions & 0 deletions src/Model/Dto/AssetFile/AssetFileSysDetailDecorator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Model\Dto\AssetFile;

use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Model\Dto\AbstractEntityDto;
use AnzuSystems\CoreDamBundle\Model\Enum\AssetFileProcessStatus;
use AnzuSystems\CoreDamBundle\Model\Enum\AssetType;
use AnzuSystems\SerializerBundle\Attributes\Serialize;

final class AssetFileSysDetailDecorator extends AbstractEntityDto
{
private AssetFile $assetFile;

public static function getInstance(AssetFile $assetFile): static
{
return self::getBaseInstance($assetFile)
->setAssetFile($assetFile);
}

public function getAssetFile(): AssetFile
{
return $this->assetFile;
}

public function setAssetFile(AssetFile $assetFile): self
{
$this->assetFile = $assetFile;
return $this;
}

#[Serialize]
public function getOriginAssetFileId(): string
{
return $this->assetFile->getAssetAttributes()->getOriginAssetId();
}


#[Serialize]
public function getAssetFileStatus(): AssetFileProcessStatus
{
return $this->assetFile->getAssetAttributes()->getStatus();
}

#[Serialize]
public function getAssetId(): ?string
{
return $this->assetFile->getAsset()->getId();
}

#[Serialize]
public function getAssetType(): AssetType
{
return $this->assetFile->getAssetType();
}
}
2 changes: 2 additions & 0 deletions src/Security/Voter/ExtSystemAwareVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ protected function permissionVote(string $attribute, mixed $subject, AnzuUser $u
protected function getSupportedPermissions(): array
{
return [
DamPermissions::DAM_ASSET_CREATE,
DamPermissions::DAM_ASSET_VIEW,
DamPermissions::DAM_AUTHOR_VIEW,
DamPermissions::DAM_AUTHOR_CREATE,
DamPermissions::DAM_AUTHOR_UPDATE,
Expand Down
2 changes: 1 addition & 1 deletion tests/Controller/Api/AbstractApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class AbstractApiController extends AbstractController
/** @psalm-var array<string, ApiClient> */
private array $clients = [];

public function getClient(?int $userId = null): ApiClient
public function getApiClient(?int $userId = null): ApiClient
{
$key = $userId ?? 'anonymous';
if (false === isset($this->clients[$key])) {
Expand Down
2 changes: 1 addition & 1 deletion tests/Controller/Api/AbstractAssetFileApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ protected function testSlotsSuccess(
AssetUrlInterface $url,
): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);

$primarySlotName = $firstAssetFile->getSlots()->first()->getName();
$asset = $firstAssetFile->getAsset();
Expand Down
6 changes: 3 additions & 3 deletions tests/Controller/Api/Adm/V1/AssetApiControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class AssetApiControllerTest extends AbstractAssetFileApiController
*/
public function testUpdate(int $statusCode, ?string $categoryId = null): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);
$video = $this->entityManager->find(VideoFile::class, VideoFixtures::VIDEO_ID_1);

$response = $client->put(
Expand Down Expand Up @@ -80,7 +80,7 @@ protected function setUp(): void
*/
public function testDelete(): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);
$imageUrl = new ImageUrl(AssetLicenceFixtures::DEFAULT_LICENCE_ID);

$image = $this->uploadAsset(
Expand Down Expand Up @@ -122,7 +122,7 @@ public function testDelete(): void
*/
public function testCreate(string $type): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);
$response = $client->post('/api/adm/v1/asset/licence/'.AssetLicenceFixtures::DEFAULT_LICENCE_ID, ['type' => $type]);

$this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode());
Expand Down
4 changes: 2 additions & 2 deletions tests/Controller/Api/Adm/V1/AssetCustomFormControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class AssetCustomFormControllerTest extends AbstractApiController
*/
public function testGetOneSuccess(): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);
$response = $client->get('/api/adm/v1/asset-custom-form/ext-system/1/type/image');
$this->assertSame(Response::HTTP_OK, $response->getStatusCode());

Expand All @@ -46,7 +46,7 @@ public function testGetOneSuccess(): void
*/
public function testGetElementsSuccess(): void
{
$client = $this->getClient(User::ID_ADMIN);
$client = $this->getApiClient(User::ID_ADMIN);
$response = $client->get('/api/adm/v1/asset-custom-form/ext-system/1/type/image/element');

$this->assertSame(Response::HTTP_OK, $response->getStatusCode());
Expand Down
Loading

0 comments on commit d5fb1d6

Please sign in to comment.