diff --git a/config/filters.yaml b/config/filters.yaml index 3b688891c..7dc94788e 100644 --- a/config/filters.yaml +++ b/config/filters.yaml @@ -33,4 +33,4 @@ services: # DataObject Pimcore\Bundle\StudioApiBundle\Filter\DataObject\ClassIdFilter: - tags: [ 'pimcore.studio_api.collection.filter' ] \ No newline at end of file + tags: [ 'pimcore.studio_api.collection.data_object.filter' ] \ No newline at end of file diff --git a/src/Attributes/Request/TokenRequestBody.php b/src/Attributes/Request/TokenRequestBody.php index 4df5e4784..72e0363be 100644 --- a/src/Attributes/Request/TokenRequestBody.php +++ b/src/Attributes/Request/TokenRequestBody.php @@ -19,7 +19,7 @@ use Attribute; use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\RequestBody; -use Pimcore\Bundle\StudioApiBundle\Dto\Token\Refresh; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Refresh; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final class TokenRequestBody extends RequestBody diff --git a/src/Attributes/Request/TranslationRequestBody.php b/src/Attributes/Request/TranslationRequestBody.php index 5ba77112b..9b48aa56e 100644 --- a/src/Attributes/Request/TranslationRequestBody.php +++ b/src/Attributes/Request/TranslationRequestBody.php @@ -19,7 +19,7 @@ use Attribute; use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\RequestBody; -use Pimcore\Bundle\StudioApiBundle\Dto\Translation; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Translation; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final class TranslationRequestBody extends RequestBody diff --git a/src/Attributes/Response/UnauthorizedResponse.php b/src/Attributes/Response/UnauthorizedResponse.php index 47005b98a..165827f62 100644 --- a/src/Attributes/Response/UnauthorizedResponse.php +++ b/src/Attributes/Response/UnauthorizedResponse.php @@ -19,7 +19,7 @@ use Attribute; use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\Response; -use Pimcore\Bundle\StudioApiBundle\Dto\Unauthorized; +use Pimcore\Bundle\StudioApiBundle\Response\Schema\Unauthorized; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final class UnauthorizedResponse extends Response diff --git a/src/Config/OpenApi/Security.php b/src/Config/OpenApi/Security.php index 9fa563476..8b81fee65 100644 --- a/src/Config/OpenApi/Security.php +++ b/src/Config/OpenApi/Security.php @@ -18,6 +18,10 @@ use OpenApi\Attributes\SecurityScheme; +/** + * @internal + * This class exists to document the public api + */ #[SecurityScheme( securityScheme: 'auth_token', type: 'http', diff --git a/src/Config/OpenApi/Spec.php b/src/Config/OpenApi/Spec.php index 5a02e3bf3..d00d102a6 100644 --- a/src/Config/OpenApi/Spec.php +++ b/src/Config/OpenApi/Spec.php @@ -19,6 +19,10 @@ use OpenApi\Attributes\Info; use OpenApi\Attributes\License; +/** + * @internal + * This class exists to document the public api + */ #[Info( version: '0.0.1', description: 'API for Studio generated by OpenApi Generator via zircote/swagger-php', diff --git a/src/Config/Tags.php b/src/Config/Tags.php index 9e6055a9e..fd5f3915c 100644 --- a/src/Config/Tags.php +++ b/src/Config/Tags.php @@ -18,6 +18,9 @@ use OpenApi\Attributes\Tag; +/** + * @internal + */ #[Tag(name: Tags::Assets->name, description: 'Asset operations to get/update/create/delete assets')] #[Tag(name: Tags::Authorization->name, description: 'Login via username and password to get a token or refresh the token')] #[Tag(name: Tags::DataObjects->name, description: 'DataObject operations to get/update/create/delete data objects')] diff --git a/src/Controller/Api/AbstractApiController.php b/src/Controller/Api/AbstractApiController.php index 6ab92b3b7..db0369f3e 100644 --- a/src/Controller/Api/AbstractApiController.php +++ b/src/Controller/Api/AbstractApiController.php @@ -21,6 +21,9 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ #[Route('/studio/api')] abstract class AbstractApiController extends AbstractController { diff --git a/src/Controller/Api/Assets/CollectionController.php b/src/Controller/Api/Assets/CollectionController.php index a23f90a3c..db49313f7 100644 --- a/src/Controller/Api/Assets/CollectionController.php +++ b/src/Controller/Api/Assets/CollectionController.php @@ -33,8 +33,8 @@ use Pimcore\Bundle\StudioApiBundle\Controller\Api\AbstractApiController; use Pimcore\Bundle\StudioApiBundle\Controller\Trait\PaginatedResponseTrait; use Pimcore\Bundle\StudioApiBundle\Dto\Asset; -use Pimcore\Bundle\StudioApiBundle\Dto\Filter\Parameters; use Pimcore\Bundle\StudioApiBundle\Exception\InvalidQueryTypeException; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Filter\Parameters; use Pimcore\Bundle\StudioApiBundle\Service\AssetSearchServiceInterface; use Pimcore\Bundle\StudioApiBundle\Service\Filter\FilterServiceInterface; use Pimcore\Bundle\StudioApiBundle\Service\GenericData\V1\AssetQuery; @@ -43,6 +43,9 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ final class CollectionController extends AbstractApiController { use PaginatedResponseTrait; @@ -84,7 +87,10 @@ public function __construct( public function getAssets(#[MapQueryString] Parameters $parameters): JsonResponse { /** @var AssetQuery $assetQuery */ - $assetQuery = $this->filterService->applyCollectionFilter($parameters, 'asset'); + $assetQuery = $this->filterService->applyFilters( + $parameters, + FilterServiceInterface::TYPE_ASSET + ); $result = $this->assetSearchService->searchAssets($assetQuery); diff --git a/src/Controller/Api/Assets/GetController.php b/src/Controller/Api/Assets/GetController.php index e258f2048..0be81728d 100644 --- a/src/Controller/Api/Assets/GetController.php +++ b/src/Controller/Api/Assets/GetController.php @@ -29,6 +29,9 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ final class GetController extends AbstractApiController { public function __construct( diff --git a/src/Controller/Api/Authorization/AuthorizationController.php b/src/Controller/Api/Authorization/AuthorizationController.php index 8b075721c..7b99417eb 100644 --- a/src/Controller/Api/Authorization/AuthorizationController.php +++ b/src/Controller/Api/Authorization/AuthorizationController.php @@ -25,8 +25,8 @@ use Pimcore\Bundle\StudioApiBundle\Config\Tags; use Pimcore\Bundle\StudioApiBundle\Controller\Api\AbstractApiController; use Pimcore\Bundle\StudioApiBundle\Dto\Credentials; -use Pimcore\Bundle\StudioApiBundle\Dto\Token; -use Pimcore\Bundle\StudioApiBundle\Dto\Token\Refresh; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Refresh; +use Pimcore\Bundle\StudioApiBundle\Response\Schema\Token; use Pimcore\Bundle\StudioApiBundle\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioApiBundle\Service\TokenServiceInterface; use Pimcore\Security\User\User; @@ -35,6 +35,9 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ final class AuthorizationController extends AbstractApiController { public function __construct( diff --git a/src/Controller/Api/DataObjects/CollectionController.php b/src/Controller/Api/DataObjects/CollectionController.php index ebed07400..ca5845b1b 100644 --- a/src/Controller/Api/DataObjects/CollectionController.php +++ b/src/Controller/Api/DataObjects/CollectionController.php @@ -34,8 +34,8 @@ use Pimcore\Bundle\StudioApiBundle\Controller\Api\AbstractApiController; use Pimcore\Bundle\StudioApiBundle\Controller\Trait\PaginatedResponseTrait; use Pimcore\Bundle\StudioApiBundle\Dto\DataObject; -use Pimcore\Bundle\StudioApiBundle\Dto\Filter\DataObjectParameters; use Pimcore\Bundle\StudioApiBundle\Exception\InvalidQueryTypeException; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Filter\DataObjectParameters; use Pimcore\Bundle\StudioApiBundle\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioApiBundle\Service\Filter\FilterServiceInterface; use Pimcore\Bundle\StudioApiBundle\Service\GenericData\V1\DataObjectQuery; @@ -87,7 +87,7 @@ public function getDataObjects(#[MapQueryString] DataObjectParameters $parameter { /** @var DataObjectQuery $dataObjectQuery */ - $dataObjectQuery = $this->filterService->applyCollectionFilter($parameters, 'dataObject'); + $dataObjectQuery = $this->filterService->applyFilters($parameters, 'dataObject'); $result = $this->dataObjectSearchService->searchDataObjects($dataObjectQuery); diff --git a/src/Controller/Api/OpenApiController.php b/src/Controller/Api/OpenApiController.php index 95343411c..03b7b5c45 100644 --- a/src/Controller/Api/OpenApiController.php +++ b/src/Controller/Api/OpenApiController.php @@ -22,6 +22,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; +/** + * @internal + */ final class OpenApiController extends AbstractController { public function __construct(private readonly OpenApiServiceInterface $openApiService) diff --git a/src/Controller/Api/TranslationController.php b/src/Controller/Api/TranslationController.php index c4653ad78..155eae0f4 100644 --- a/src/Controller/Api/TranslationController.php +++ b/src/Controller/Api/TranslationController.php @@ -22,13 +22,16 @@ use Pimcore\Bundle\StudioApiBundle\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioApiBundle\Attributes\Response\UnauthorizedResponse; use Pimcore\Bundle\StudioApiBundle\Config\Tags; -use Pimcore\Bundle\StudioApiBundle\Dto\Translation; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Translation; use Pimcore\Bundle\StudioApiBundle\Service\TranslatorServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ final class TranslationController extends AbstractApiController { private const PATH = '/translations'; diff --git a/src/Controller/Trait/PaginatedResponseTrait.php b/src/Controller/Trait/PaginatedResponseTrait.php index 31a43c6ac..61923b7b6 100644 --- a/src/Controller/Trait/PaginatedResponseTrait.php +++ b/src/Controller/Trait/PaginatedResponseTrait.php @@ -19,6 +19,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Serializer\SerializerInterface; +/** + * @internal + */ trait PaginatedResponseTrait { private const HEADER_TOTAL_ITEMS = 'X-Pimcore-Total-Items'; diff --git a/src/DependencyInjection/CompilerPass/FilterPass.php b/src/DependencyInjection/CompilerPass/FilterPass.php index d3ad6890f..baf68b1e7 100644 --- a/src/DependencyInjection/CompilerPass/FilterPass.php +++ b/src/DependencyInjection/CompilerPass/FilterPass.php @@ -36,9 +36,13 @@ final class FilterPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $taggedServices = array_keys( - $container->findTaggedServiceIds( - TaggedIteratorAdapter::FILTER_TAG - ) + [ + ... $container->findTaggedServiceIds(TaggedIteratorAdapter::FILTER_TAG), + ... $container->findTaggedServiceIds(TaggedIteratorAdapter::FILTER_ASSET_TAG), + ... $container->findTaggedServiceIds(TaggedIteratorAdapter::FILTER_DATA_OBJECT_TAG), + ... $container->findTaggedServiceIds(TaggedIteratorAdapter::FILTER_DOCUMENT_TAG), + + ] ); foreach ($taggedServices as $environmentType) { diff --git a/tests/Unit/Dto/Token/OutputTest.php b/src/Exception/AccessDeniedException.php similarity index 50% rename from tests/Unit/Dto/Token/OutputTest.php rename to src/Exception/AccessDeniedException.php index b619ce03f..af610dac6 100644 --- a/tests/Unit/Dto/Token/OutputTest.php +++ b/src/Exception/AccessDeniedException.php @@ -14,18 +14,13 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Tests\Unit\Dto\Token; +namespace Pimcore\Bundle\StudioApiBundle\Exception; -use Codeception\Test\Unit; -use Pimcore\Bundle\StudioApiBundle\Dto\Token; +use Symfony\Component\HttpKernel\Exception\HttpException; -final class OutputTest extends Unit +/** + * @internal + */ +final class AccessDeniedException extends HttpException { - public function testTokenOutput(): void - { - $output = new Token('token', 3600, 'test'); - $this->assertSame('token', $output->getToken()); - $this->assertSame(3600, $output->getLifetime()); - $this->assertSame('test', $output->getUsername()); - } } diff --git a/src/Exception/InvalidFilterTypeException.php b/src/Exception/InvalidFilterTypeException.php new file mode 100644 index 000000000..562d64704 --- /dev/null +++ b/src/Exception/InvalidFilterTypeException.php @@ -0,0 +1,26 @@ +validate(); } public function getPage(): int @@ -73,4 +81,10 @@ public function getPathIncludeDescendants(): ?bool { return $this->pathIncludeDescendants === 'true'; // TODO: symfony 7.1 will support bool type } + + private function validate(): void + { + new PositiveInteger($this->page); + new PositiveInteger($this->pageSize); + } } diff --git a/src/Dto/Filter/ParametersInterface.php b/src/Request/Query/Filter/ParametersInterface.php similarity index 91% rename from src/Dto/Filter/ParametersInterface.php rename to src/Request/Query/Filter/ParametersInterface.php index 787f59c7a..0dbc044b9 100644 --- a/src/Dto/Filter/ParametersInterface.php +++ b/src/Request/Query/Filter/ParametersInterface.php @@ -14,8 +14,11 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Dto\Filter; +namespace Pimcore\Bundle\StudioApiBundle\Request\Query\Filter; +/** + * @internal + */ interface ParametersInterface { public function getPage(): int; diff --git a/src/Dto/Token/Refresh.php b/src/Request/Query/Refresh.php similarity index 94% rename from src/Dto/Token/Refresh.php rename to src/Request/Query/Refresh.php index 20e3fa234..0ea3c6972 100644 --- a/src/Dto/Token/Refresh.php +++ b/src/Request/Query/Refresh.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Dto\Token; +namespace Pimcore\Bundle\StudioApiBundle\Request\Query; use OpenApi\Attributes\Property; use OpenApi\Attributes\Schema; diff --git a/src/Dto/Translation.php b/src/Request/Query/Translation.php similarity index 96% rename from src/Dto/Translation.php rename to src/Request/Query/Translation.php index 031f5d60c..94328355f 100644 --- a/src/Dto/Translation.php +++ b/src/Request/Query/Translation.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Dto; +namespace Pimcore\Bundle\StudioApiBundle\Request\Query; use OpenApi\Attributes\Items; use OpenApi\Attributes\Property; diff --git a/src/Dto/Token.php b/src/Response/Schema/Token.php similarity index 71% rename from src/Dto/Token.php rename to src/Response/Schema/Token.php index b5cc3aff3..fde03514c 100644 --- a/src/Dto/Token.php +++ b/src/Response/Schema/Token.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Dto; +namespace Pimcore\Bundle\StudioApiBundle\Response\Schema; use OpenApi\Attributes\Property; use OpenApi\Attributes\Schema; @@ -31,26 +31,11 @@ { public function __construct( #[Property(description: 'Token', type: 'string', example: 'This could be your token')] - private string $token, + protected string $token, #[Property(description: 'Lifetime in seconds', type: 'integer', format: 'int', example: 3600)] - private int $lifetime, + protected int $lifetime, #[Property(description: 'Username', type: 'string', example: 'shaquille.oatmeal')] - private string $username + protected string $username ) { } - - public function getToken(): string - { - return $this->token; - } - - public function getUsername(): string - { - return $this->username; - } - - public function getLifetime(): int - { - return $this->lifetime; - } } diff --git a/src/Dto/Unauthorized.php b/src/Response/Schema/Unauthorized.php similarity index 83% rename from src/Dto/Unauthorized.php rename to src/Response/Schema/Unauthorized.php index b58002090..5c2ae6f40 100644 --- a/src/Dto/Unauthorized.php +++ b/src/Response/Schema/Unauthorized.php @@ -14,11 +14,14 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioApiBundle\Dto; +namespace Pimcore\Bundle\StudioApiBundle\Response\Schema; use OpenApi\Attributes\Property; use OpenApi\Attributes\Schema; +/** + * @internal + */ #[Schema( schema: 'Unauthorized', title: 'Unauthorized', @@ -29,13 +32,8 @@ { public function __construct( #[Property(description: 'Message', type: 'string')] - private string $message + protected string $message ) { } - - public function getMessage(): string - { - return $this->message; - } } diff --git a/src/Security/Trait/PublicTranslationTrait.php b/src/Security/Trait/PublicTranslationTrait.php index 00afa3ee0..566dac245 100644 --- a/src/Security/Trait/PublicTranslationTrait.php +++ b/src/Security/Trait/PublicTranslationTrait.php @@ -20,6 +20,9 @@ use Pimcore\Bundle\StudioApiBundle\Util\Constants\PublicTranslations; use Symfony\Component\HttpFoundation\InputBag; +/** + * @internal + */ trait PublicTranslationTrait { private const ARRAY_KEYS_INDEX = 'keys'; diff --git a/src/Security/Trait/RequestTrait.php b/src/Security/Trait/RequestTrait.php index 96ad91958..100d83b69 100644 --- a/src/Security/Trait/RequestTrait.php +++ b/src/Security/Trait/RequestTrait.php @@ -21,6 +21,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +/** + * @internal + */ trait RequestTrait { private const BEARER_PREFIX = 'Bearer '; diff --git a/src/Security/Voter/AuthorizationVoter.php b/src/Security/Voter/AuthorizationVoter.php index ab22d2ee7..bbbad1472 100644 --- a/src/Security/Voter/AuthorizationVoter.php +++ b/src/Security/Voter/AuthorizationVoter.php @@ -24,6 +24,9 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; +/** + * @internal + */ final class AuthorizationVoter extends Voter { use RequestTrait; diff --git a/src/Security/Voter/PublicAuthorizationVoter.php b/src/Security/Voter/PublicAuthorizationVoter.php index 441eaf73d..d90c39d20 100644 --- a/src/Security/Voter/PublicAuthorizationVoter.php +++ b/src/Security/Voter/PublicAuthorizationVoter.php @@ -28,6 +28,9 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; +/** + * @internal + */ final class PublicAuthorizationVoter extends Voter { use RequestTrait; diff --git a/src/Service/Filter/FilterLoaderInterface.php b/src/Service/Filter/FilterLoaderInterface.php index 5f0dde3bb..49650502a 100644 --- a/src/Service/Filter/FilterLoaderInterface.php +++ b/src/Service/Filter/FilterLoaderInterface.php @@ -21,5 +21,5 @@ */ interface FilterLoaderInterface { - public function loadFilters(): array; + public function loadFilters(): Filters; } diff --git a/src/Service/Filter/FilterService.php b/src/Service/Filter/FilterService.php index ec6c176b6..5c903132c 100644 --- a/src/Service/Filter/FilterService.php +++ b/src/Service/Filter/FilterService.php @@ -16,11 +16,15 @@ namespace Pimcore\Bundle\StudioApiBundle\Service\Filter; -use Pimcore\Bundle\StudioApiBundle\Dto\Filter\Parameters; +use Pimcore\Bundle\StudioApiBundle\Exception\InvalidFilterTypeException; use Pimcore\Bundle\StudioApiBundle\Exception\InvalidQueryTypeException; use Pimcore\Bundle\StudioApiBundle\Factory\QueryFactoryInterface; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Filter\Parameters; use Pimcore\Bundle\StudioApiBundle\Service\GenericData\V1\QueryInterface; +/** + * @internal + */ final readonly class FilterService implements FilterServiceInterface { public function __construct( @@ -31,14 +35,37 @@ public function __construct( /** * @throws InvalidQueryTypeException + * @throws InvalidFilterTypeException */ - public function applyCollectionFilter(Parameters $collection, string $type): QueryInterface + public function applyFilters(Parameters $parameters, string $type): QueryInterface { $query = $this->queryFactory->create($type); - foreach ($this->filterLoader->loadFilters() as $filter) { - $query = $filter->apply($collection, $query); + // apply default filters + $filters = $this->filterLoader->loadFilters(); + + foreach($filters->getFilters() as $filter) { + $query = $filter->apply($parameters, $query); + } + + // apply type specific filters + + foreach ($this->getTypeFilters($filters, $type) as $filter) { + $query = $filter->apply($parameters, $query); } return $query; } + + /** + * @throws InvalidFilterTypeException + */ + private function getTypeFilters(Filters $filters, string $type): array + { + return match($type) { + FilterServiceInterface::TYPE_ASSET => $filters->getAssetFilters(), + FilterServiceInterface::TYPE_DATA_OBJECT => $filters->getDataObjectFilters(), + FilterServiceInterface::TYPE_DOCUMENT => $filters->getDocumentFilters(), + default => throw new InvalidFilterTypeException("Unknown filter type: $type") + }; + } } diff --git a/src/Service/Filter/FilterServiceInterface.php b/src/Service/Filter/FilterServiceInterface.php index b42b32a5c..2bc6597de 100644 --- a/src/Service/Filter/FilterServiceInterface.php +++ b/src/Service/Filter/FilterServiceInterface.php @@ -16,14 +16,23 @@ namespace Pimcore\Bundle\StudioApiBundle\Service\Filter; -use Pimcore\Bundle\StudioApiBundle\Dto\Filter\Parameters; use Pimcore\Bundle\StudioApiBundle\Exception\InvalidQueryTypeException; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Filter\Parameters; use Pimcore\Bundle\StudioApiBundle\Service\GenericData\V1\QueryInterface; +/** + * @internal + */ interface FilterServiceInterface { + public const TYPE_DATA_OBJECT = 'dataObject'; + + public const TYPE_ASSET = 'asset'; + + public const TYPE_DOCUMENT = 'document'; + /** * @throws InvalidQueryTypeException */ - public function applyCollectionFilter(Parameters $collection, string $type): QueryInterface; + public function applyFilters(Parameters $parameters, string $type): QueryInterface; } diff --git a/src/Service/Filter/Filters.php b/src/Service/Filter/Filters.php new file mode 100644 index 000000000..eadc627ac --- /dev/null +++ b/src/Service/Filter/Filters.php @@ -0,0 +1,51 @@ +filters; + } + + public function getAssetFilters(): array + { + return $this->assetFilters; + } + + public function getDataObjectFilters(): array + { + return $this->dataObjectFilters; + } + + public function getDocumentFilters(): array + { + return $this->documentFilters; + } +} diff --git a/src/Service/Filter/Loader/TaggedIteratorAdapter.php b/src/Service/Filter/Loader/TaggedIteratorAdapter.php index 7d840c046..c863060e2 100644 --- a/src/Service/Filter/Loader/TaggedIteratorAdapter.php +++ b/src/Service/Filter/Loader/TaggedIteratorAdapter.php @@ -17,6 +17,7 @@ namespace Pimcore\Bundle\StudioApiBundle\Service\Filter\Loader; use Pimcore\Bundle\StudioApiBundle\Service\Filter\FilterLoaderInterface; +use Pimcore\Bundle\StudioApiBundle\Service\Filter\Filters; use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; /** @@ -26,14 +27,31 @@ final class TaggedIteratorAdapter implements FilterLoaderInterface { public const FILTER_TAG = 'pimcore.studio_api.collection.filter'; + public const FILTER_ASSET_TAG = 'pimcore.studio_api.collection.asset.filter'; + + public const FILTER_DATA_OBJECT_TAG = 'pimcore.studio_api.collection.data_object.filter'; + + public const FILTER_DOCUMENT_TAG = 'pimcore.studio_api.collection.document.filter'; + public function __construct( #[TaggedIterator(self::FILTER_TAG)] - private readonly iterable $taggedServices + private readonly iterable $taggedFilters, + #[TaggedIterator(self::FILTER_ASSET_TAG)] + private readonly iterable $taggedAssetFilters, + #[TaggedIterator(self::FILTER_DATA_OBJECT_TAG)] + private readonly iterable $taggedDataObjectFilters, + #[TaggedIterator(self::FILTER_DOCUMENT_TAG)] + private readonly iterable $taggedDocumentFilters ) { } - public function loadFilters(): array + public function loadFilters(): Filters { - return [... $this->taggedServices]; + return new Filters( + [... $this->taggedFilters], + [... $this->taggedAssetFilters], + [... $this->taggedDataObjectFilters], + [... $this->taggedDocumentFilters] + ); } } diff --git a/src/Service/SecurityService.php b/src/Service/SecurityService.php index 8e2b9ea6f..f3d3f04a7 100644 --- a/src/Service/SecurityService.php +++ b/src/Service/SecurityService.php @@ -18,9 +18,9 @@ use Pimcore\Bundle\StaticResolverBundle\Models\Tool\TmpStoreResolverInterface; use Pimcore\Bundle\StudioApiBundle\Dto\Credentials; +use Pimcore\Bundle\StudioApiBundle\Exception\AccessDeniedException; use Pimcore\Security\User\UserProvider; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; -use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\UserNotFoundException; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; @@ -41,14 +41,14 @@ public function authenticateUser(Credentials $credentials): PasswordAuthenticate try { $user = $this->userProvider->loadUserByIdentifier($credentials->getUsername()); } catch (UserNotFoundException) { - throw new AccessDeniedException('Invalid credentials'); + throw new AccessDeniedException(401, 'Invalid credentials'); } if( !$user instanceof PasswordAuthenticatedUserInterface || !$this->passwordHasher->isPasswordValid($user, $credentials->getPassword()) ) { - throw new AccessDeniedException('Invalid credentials'); + throw new AccessDeniedException(401, 'Invalid credentials'); } return $user; diff --git a/src/Service/TokenService.php b/src/Service/TokenService.php index 3089802a9..fc03a9181 100644 --- a/src/Service/TokenService.php +++ b/src/Service/TokenService.php @@ -21,6 +21,9 @@ use Symfony\Component\Security\Core\Exception\TokenNotFoundException; use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; +/** + * @internal + */ final class TokenService implements TokenServiceInterface { private const TMP_STORE_TAG = 'studio-api-token-tag-user-{userId}'; diff --git a/src/Service/TokenServiceInterface.php b/src/Service/TokenServiceInterface.php index 35f92886c..d8ffb47c6 100644 --- a/src/Service/TokenServiceInterface.php +++ b/src/Service/TokenServiceInterface.php @@ -18,6 +18,9 @@ use Pimcore\Bundle\StudioApiBundle\Dto\Token\Info; +/** + * @internal + */ interface TokenServiceInterface { public function generateAndSaveToken(string $userIdentifier): string; diff --git a/src/Service/TranslatorService.php b/src/Service/TranslatorService.php index 7d18e41dc..60b6ecab7 100644 --- a/src/Service/TranslatorService.php +++ b/src/Service/TranslatorService.php @@ -17,7 +17,7 @@ namespace Pimcore\Bundle\StudioApiBundle\Service; use InvalidArgumentException; -use Pimcore\Bundle\StudioApiBundle\Dto\Translation; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Translation; use Symfony\Component\Translation\TranslatorBagInterface; use Symfony\Contracts\Translation\TranslatorInterface; diff --git a/src/Service/TranslatorServiceInterface.php b/src/Service/TranslatorServiceInterface.php index d8b7cab96..95768b0a4 100644 --- a/src/Service/TranslatorServiceInterface.php +++ b/src/Service/TranslatorServiceInterface.php @@ -16,7 +16,7 @@ namespace Pimcore\Bundle\StudioApiBundle\Service; -use Pimcore\Bundle\StudioApiBundle\Dto\Translation; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Translation; /** * @internal diff --git a/src/Util/Constants/PublicTranslations.php b/src/Util/Constants/PublicTranslations.php index a4d2730d1..27784c484 100644 --- a/src/Util/Constants/PublicTranslations.php +++ b/src/Util/Constants/PublicTranslations.php @@ -16,6 +16,9 @@ namespace Pimcore\Bundle\StudioApiBundle\Util\Constants; +/** + * @internal + */ final readonly class PublicTranslations { public const PUBLIC_KEYS = [ diff --git a/tests/Unit/Dto/Token/RefreshTest.php b/tests/Unit/Dto/Token/RefreshTest.php index 06878bca8..e0cd23e5b 100644 --- a/tests/Unit/Dto/Token/RefreshTest.php +++ b/tests/Unit/Dto/Token/RefreshTest.php @@ -17,7 +17,7 @@ namespace Pimcore\Bundle\StudioApiBundle\Tests\Unit\Dto\Token; use Codeception\Test\Unit; -use Pimcore\Bundle\StudioApiBundle\Dto\Token\Refresh; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Refresh; final class RefreshTest extends Unit { diff --git a/tests/Unit/Dto/TranslationTest.php b/tests/Unit/Dto/TranslationTest.php index 5258c50e2..964e962eb 100644 --- a/tests/Unit/Dto/TranslationTest.php +++ b/tests/Unit/Dto/TranslationTest.php @@ -17,7 +17,7 @@ namespace Pimcore\Bundle\StudioApiBundle\Tests\Unit\Dto; use Codeception\Test\Unit; -use Pimcore\Bundle\StudioApiBundle\Dto\Translation; +use Pimcore\Bundle\StudioApiBundle\Request\Query\Translation; final class TranslationTest extends Unit {