diff --git a/.env b/.env index a00827d5..d1f78e83 100644 --- a/.env +++ b/.env @@ -60,3 +60,7 @@ JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem JWT_PASSPHRASE=857ce6bfb8d058ca8f51421d40864305d96be4be4a30d75e843b2d13958e6fde ###< lexik/jwt-authentication-bundle ### + +###> nelmio/cors-bundle ### +CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' +###< nelmio/cors-bundle ### diff --git a/composer.json b/composer.json index 6e660bf5..43627c11 100644 --- a/composer.json +++ b/composer.json @@ -9,17 +9,23 @@ "ext-iconv": "*", "ext-openssl": ">=7.1", "ext-sodium": "^2.0 | >=7.2", + "api-platform/core": "^3.2", "doctrine/annotations": "*", + "doctrine/dbal": "^3", "doctrine/doctrine-bundle": "^2.7", "doctrine/doctrine-fixtures-bundle": "~3.4", + "doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/orm": "^2.13", "endroid/qr-code": "^5.0", "ircmaxell/password-compat": "~1.0.3", "knplabs/knp-menu-bundle": "^3.0", "lexik/jwt-authentication-bundle": "^2.20", "mopa/bootstrap-bundle": "~3.0", + "nelmio/cors-bundle": "^2.4", "nelmio/security-bundle": "^3.0", "pear/crypt_gpg": "^1.6", + "phpdocumentor/reflection-docblock": "^5.3", + "phpstan/phpdoc-parser": "^1.27", "ramsey/uuid": "^4.1", "scheb/2fa-backup-code": "^7.2.0", "scheb/2fa-bundle": "^7.2.0", @@ -27,8 +33,10 @@ "sonata-project/admin-bundle": "^4.0", "sonata-project/doctrine-orm-admin-bundle": "^4.0", "symfony/apache-pack": "^1.0", + "symfony/asset": "6.4.*", "symfony/console": "*", "symfony/dotenv": "*", + "symfony/expression-language": "6.4.*", "symfony/flex": "^1.1", "symfony/form": "*", "symfony/framework-bundle": "*", @@ -37,9 +45,12 @@ "symfony/monolog-bundle": "^3.8.0", "symfony/polyfill-apcu": "^1.0", "symfony/process": "6.4.*", + "symfony/property-access": "6.4.*", + "symfony/property-info": "6.4.*", "symfony/runtime": "6.4.*", "symfony/security-bundle": "*", "symfony/security-csrf": "*", + "symfony/serializer": "6.4.*", "symfony/translation": "*", "symfony/twig-bundle": "6.4.*", "symfony/validator": "*", diff --git a/composer.lock b/composer.lock index 148bed07..9d66c70d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,174 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c9706f16061b30b51ae159d4e070268e", + "content-hash": "fd0ccbe24fed08f98bd89c103af3c6dc", "packages": [ + { + "name": "api-platform/core", + "version": "v3.2.20", + "source": { + "type": "git", + "url": "https://github.com/api-platform/core.git", + "reference": "875cc155e556541c0591b0c182ed64dcc41b9984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/api-platform/core/zipball/875cc155e556541c0591b0c182ed64dcc41b9984", + "reference": "875cc155e556541c0591b0c182ed64dcc41b9984", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^1.0 || ^2.0", + "php": ">=8.1", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^3.1", + "symfony/http-foundation": "^6.1 || ^7.0", + "symfony/http-kernel": "^6.1 || ^7.0", + "symfony/property-access": "^6.1 || ^7.0", + "symfony/property-info": "^6.1 || ^7.0", + "symfony/serializer": "^6.1 || ^7.0", + "symfony/translation-contracts": "^3.3", + "symfony/web-link": "^6.1 || ^7.0", + "willdurand/negotiation": "^3.0" + }, + "conflict": { + "doctrine/common": "<3.2.2", + "doctrine/dbal": "<2.10", + "doctrine/mongodb-odm": "<2.4", + "doctrine/orm": "<2.14.0", + "doctrine/persistence": "<1.3", + "elasticsearch/elasticsearch": ">=8.0,<8.4", + "phpspec/prophecy": "<1.15", + "phpunit/phpunit": "<9.5", + "symfony/var-exporter": "<6.1.1" + }, + "require-dev": { + "behat/behat": "^3.11", + "behat/mink": "^1.9", + "doctrine/cache": "^1.11 || ^2.1", + "doctrine/common": "^3.2.2", + "doctrine/dbal": "^3.4.0", + "doctrine/doctrine-bundle": "^1.12 || ^2.0", + "doctrine/mongodb-odm": "^2.2", + "doctrine/mongodb-odm-bundle": "^4.0 || ^5.0", + "doctrine/orm": "^2.14 || ^3.0", + "elasticsearch/elasticsearch": "^7.11 || ^8.4", + "friends-of-behat/mink-browserkit-driver": "^1.3.1", + "friends-of-behat/mink-extension": "^2.2", + "friends-of-behat/symfony-extension": "^2.1", + "guzzlehttp/guzzle": "^6.0 || ^7.0", + "jangregor/phpstan-prophecy": "^1.0", + "justinrainbow/json-schema": "^5.2.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpdoc-parser": "^1.13", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-doctrine": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-symfony": "^1.0", + "phpunit/phpunit": "^9.5", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "ramsey/uuid": "^3.9.7 || ^4.0", + "ramsey/uuid-doctrine": "^1.4 || ^2.0", + "sebastian/comparator": "<5.0", + "soyuka/contexts": "v3.3.9", + "soyuka/stubs-mongodb": "^1.0", + "symfony/asset": "^6.1 || ^7.0", + "symfony/browser-kit": "^6.1 || ^7.0", + "symfony/cache": "^6.1 || ^7.0", + "symfony/config": "^6.1 || ^7.0", + "symfony/console": "^6.1 || ^7.0", + "symfony/css-selector": "^6.1 || ^7.0", + "symfony/dependency-injection": "^6.1 || ^7.0.12", + "symfony/doctrine-bridge": "^6.1 || ^7.0", + "symfony/dom-crawler": "^6.1 || ^7.0", + "symfony/error-handler": "^6.1 || ^7.0", + "symfony/event-dispatcher": "^6.1 || ^7.0", + "symfony/expression-language": "^6.1 || ^7.0", + "symfony/finder": "^6.1 || ^7.0", + "symfony/form": "^6.1 || ^7.0", + "symfony/framework-bundle": "^6.1 || ^7.0", + "symfony/http-client": "^6.1 || ^7.0", + "symfony/intl": "^6.1 || ^7.0", + "symfony/maker-bundle": "^1.24", + "symfony/mercure-bundle": "*", + "symfony/messenger": "^6.1 || ^7.0", + "symfony/phpunit-bridge": "^6.1 || ^7.0", + "symfony/routing": "^6.1 || ^7.0", + "symfony/security-bundle": "^6.1 || ^7.0", + "symfony/security-core": "^6.1 || ^7.0", + "symfony/stopwatch": "^6.1 || ^7.0", + "symfony/twig-bundle": "^6.1 || ^7.0", + "symfony/uid": "^6.1 || ^7.0", + "symfony/validator": "^6.1 || ^7.0", + "symfony/web-profiler-bundle": "^6.1 || ^7.0", + "symfony/yaml": "^6.1 || ^7.0", + "twig/twig": "^1.42.3 || ^2.12 || ^3.0", + "webonyx/graphql-php": "^14.0 || ^15.0" + }, + "suggest": { + "doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.", + "elasticsearch/elasticsearch": "To support Elasticsearch.", + "ocramius/package-versions": "To display the API Platform's version in the debug bar.", + "phpstan/phpdoc-parser": "To support extracting metadata from PHPDoc.", + "psr/cache-implementation": "To use metadata caching.", + "ramsey/uuid": "To support Ramsey's UUID identifiers.", + "symfony/cache": "To have metadata caching when using Symfony integration.", + "symfony/config": "To load XML configuration files.", + "symfony/expression-language": "To use authorization features.", + "symfony/http-client": "To use the HTTP cache invalidation system.", + "symfony/messenger": "To support messenger integration.", + "symfony/security": "To use authorization features.", + "symfony/twig-bundle": "To use the Swagger UI integration.", + "symfony/uid": "To support Symfony UUID/ULID identifiers.", + "symfony/web-profiler-bundle": "To use the data collector.", + "webonyx/graphql-php": "To support GraphQL." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3.x-dev" + }, + "symfony": { + "require": "^6.1 || ^7.0" + } + }, + "autoload": { + "psr-4": { + "ApiPlatform\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + } + ], + "description": "Build a fully-featured hypermedia or GraphQL API in minutes!", + "homepage": "https://api-platform.com", + "keywords": [ + "Hydra", + "JSON-LD", + "api", + "graphql", + "hal", + "jsonapi", + "openapi", + "rest", + "swagger" + ], + "support": { + "issues": "https://github.com/api-platform/core/issues", + "source": "https://github.com/api-platform/core/tree/v3.2.20" + }, + "time": "2024-04-03T15:33:10+00:00" + }, { "name": "bacon/bacon-qr-code", "version": "2.0.8", @@ -1038,6 +1204,97 @@ ], "time": "2023-11-19T12:48:54+00:00" }, + { + "name": "doctrine/doctrine-migrations-bundle", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", + "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1dd42906a5fb9c5960723e2ebb45c68006493835", + "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "^2.4", + "doctrine/migrations": "^3.2", + "php": "^7.2|^8.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.6 || ^3", + "doctrine/persistence": "^2.0 || ^3 ", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^8.5|^9.5", + "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-symfony": "^3 || ^5", + "symfony/phpunit-bridge": "^6.3 || ^7", + "symfony/var-exporter": "^5.4 || ^6 || ^7", + "vimeo/psalm": "^4.30 || ^5.15" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\MigrationsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineMigrationsBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "dbal", + "migrations", + "schema" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2023-11-13T19:44:41+00:00" + }, { "name": "doctrine/event-manager", "version": "2.0.0", @@ -1367,6 +1624,108 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "doctrine/migrations", + "version": "3.7.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "954e0a314c2f0eb9fb418210445111747de254a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/954e0a314c2f0eb9fb418210445111747de254a6", + "reference": "954e0a314c2f0eb9fb418210445111747de254a6", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.5.1 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.2 || ^7.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^10.3", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "dbal", + "migrations" + ], + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.7.4" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2024-03-06T13:41:11+00:00" + }, { "name": "doctrine/orm", "version": "2.19.3", @@ -2661,6 +3020,68 @@ }, "time": "2016-12-05T07:27:31+00:00" }, + { + "name": "nelmio/cors-bundle", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/nelmio/NelmioCorsBundle.git", + "reference": "78fcdb91f76b080a1008133def9c7f613833933d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/78fcdb91f76b080a1008133def9c7f613833933d", + "reference": "78fcdb91f76b080a1008133def9c7f613833933d", + "shasum": "" + }, + "require": { + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.6", + "symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Nelmio\\CorsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nelmio", + "homepage": "http://nelm.io" + }, + { + "name": "Symfony Community", + "homepage": "https://github.com/nelmio/NelmioCorsBundle/contributors" + } + ], + "description": "Adds CORS (Cross-Origin Resource Sharing) headers support in your Symfony application", + "keywords": [ + "api", + "cors", + "crossdomain" + ], + "support": { + "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.4.0" + }, + "time": "2023-11-30T16:41:19+00:00" + }, { "name": "nelmio/security-bundle", "version": "v3.2.0", @@ -2991,6 +3412,174 @@ }, "time": "2021-03-21T15:43:46+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + }, + "time": "2024-02-23T11:10:43+00:00" + }, { "name": "phpstan/phpdoc-parser", "version": "1.27.0", @@ -3238,6 +3827,62 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/link", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "84b159194ecfd7eaa472280213976e96415433f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7", + "reference": "84b159194ecfd7eaa472280213976e96415433f7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "suggest": { + "fig/link-util": "Provides some useful PSR-13 utilities" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "homepage": "https://github.com/php-fig/link", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "source": "https://github.com/php-fig/link/tree/2.0.1" + }, + "time": "2021-03-11T23:00:27+00:00" + }, { "name": "psr/log", "version": "3.0.0", @@ -8724,10 +9369,92 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", - "homepage": "https://symfony.com", + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v6.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-22T20:27:10+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.4" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -8743,45 +9470,33 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:10+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.4.1", + "name": "symfony/stopwatch", + "version": "v6.4.3", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "416596166641f1f728b0a64f5b9dd07cceb410c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/416596166641f1f728b0a64f5b9dd07cceb410c1", + "reference": "416596166641f1f728b0a64f5b9dd07cceb410c1", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" + "symfony/service-contracts": "^2.5|^3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" + "Symfony\\Component\\Stopwatch\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -8790,26 +9505,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Provides a way to profile code", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.3" }, "funding": [ { @@ -8825,7 +9532,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2024-01-23T14:35:58+00:00" }, { "name": "symfony/string", @@ -9535,6 +10242,89 @@ ], "time": "2024-02-26T08:37:45+00:00" }, + { + "name": "symfony/web-link", + "version": "v6.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "1722ee157388aaf2f312954addf5b9665e4b7ee9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/1722ee157388aaf2f312954addf5b9665e4b7ee9", + "reference": "1722ee157388aaf2f312954addf5b9665e4b7ee9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/link": "^1.1|^2.0" + }, + "conflict": { + "symfony/http-kernel": "<5.4" + }, + "provide": { + "psr/link-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages links between resources", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "support": { + "source": "https://github.com/symfony/web-link/tree/v6.4.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T14:51:35+00:00" + }, { "name": "symfony/yaml", "version": "v6.4.3", @@ -10071,6 +10861,120 @@ "source": "https://github.com/ua-parser/uap-php/tree/v3.9.14" }, "time": "2020-10-02T23:36:20+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "willdurand/negotiation", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/willdurand/Negotiation.git", + "reference": "68e9ea0553ef6e2ee8db5c1d98829f111e623ec2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/Negotiation/zipball/68e9ea0553ef6e2ee8db5c1d98829f111e623ec2", + "reference": "68e9ea0553ef6e2ee8db5c1d98829f111e623ec2", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Negotiation\\": "src/Negotiation" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "will+git@drnd.me" + } + ], + "description": "Content Negotiation tools for PHP provided as a standalone library.", + "homepage": "http://williamdurand.fr/Negotiation/", + "keywords": [ + "accept", + "content", + "format", + "header", + "negotiation" + ], + "support": { + "issues": "https://github.com/willdurand/Negotiation/issues", + "source": "https://github.com/willdurand/Negotiation/tree/3.1.0" + }, + "time": "2022-01-30T20:08:53+00:00" } ], "packages-dev": [ @@ -12747,68 +13651,6 @@ ], "time": "2024-02-08T19:22:56+00:00" }, - { - "name": "symfony/stopwatch", - "version": "v6.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "416596166641f1f728b0a64f5b9dd07cceb410c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/416596166641f1f728b0a64f5b9dd07cceb410c1", - "reference": "416596166641f1f728b0a64f5b9dd07cceb410c1", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-01-23T14:35:58+00:00" - }, { "name": "symfony/web-profiler-bundle", "version": "v6.4.4", diff --git a/config/bundles.php b/config/bundles.php index 79937ed5..a5cd7a55 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -22,4 +22,7 @@ Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true], Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], + ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], ]; diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml new file mode 100644 index 00000000..04b1a889 --- /dev/null +++ b/config/packages/api_platform.yaml @@ -0,0 +1,23 @@ +api_platform: + title: Hello API Platform + version: 1.0.0 + formats: + jsonld: ['application/ld+json'] + docs_formats: + jsonld: ['application/ld+json'] + jsonopenapi: ['application/vnd.openapi+json'] + html: ['text/html'] + defaults: + stateless: false + cache_headers: + vary: ['Content-Type', 'Authorization', 'Origin'] + extra_properties: + standard_put: true + rfc_7807_compliant_errors: true + event_listeners_backward_compatibility_layer: false + keep_legacy_inflector: false + swagger: + api_keys: + JWT: + name: Authorization + type: header \ No newline at end of file diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml new file mode 100644 index 00000000..29231d94 --- /dev/null +++ b/config/packages/doctrine_migrations.yaml @@ -0,0 +1,6 @@ +doctrine_migrations: + migrations_paths: + # namespace is arbitrary but should be different from App\Migrations + # as migrations classes should NOT be autoloaded + 'DoctrineMigrations': '%kernel.project_dir%/migrations' + enable_profiler: false diff --git a/config/packages/lexik_jwt_authentication.yaml b/config/packages/lexik_jwt_authentication.yaml index edfb69dc..078b8116 100644 --- a/config/packages/lexik_jwt_authentication.yaml +++ b/config/packages/lexik_jwt_authentication.yaml @@ -2,3 +2,16 @@ lexik_jwt_authentication: secret_key: '%env(resolve:JWT_SECRET_KEY)%' public_key: '%env(resolve:JWT_PUBLIC_KEY)%' pass_phrase: '%env(JWT_PASSPHRASE)%' + api_platform: + check_path: /api/login + username_path: data.username + password_path: data.password + token_extractors: + authorization_header: + enabled: true + prefix: Bearer + name: Authorization + +when@prod: + lexik_jwt_authentication: + token_ttl: 31536000 \ No newline at end of file diff --git a/config/packages/nelmio_cors.yaml b/config/packages/nelmio_cors.yaml new file mode 100644 index 00000000..c7665081 --- /dev/null +++ b/config/packages/nelmio_cors.yaml @@ -0,0 +1,10 @@ +nelmio_cors: + defaults: + origin_regex: true + allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] + allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'] + allow_headers: ['Content-Type', 'Authorization'] + expose_headers: ['Link'] + max_age: 3600 + paths: + '^/': null diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 28add15a..5480e62f 100755 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -168,4 +168,5 @@ security: - { path: "^/account", roles: ROLE_USER, allow_if: "!is_granted('ROLE_SPAM')"} - { path: "^/admin", roles: ROLE_DOMAIN_ADMIN } - { path: "^/api/login", roles: PUBLIC_ACCESS } - - { path: "^/api", roles: ROLE_USER } \ No newline at end of file + - { path: "^/api/register", roles: PUBLIC_ACCESS } + - { path: "^/api/user", roles: ROLE_USER } \ No newline at end of file diff --git a/config/routes/api_platform.yaml b/config/routes/api_platform.yaml new file mode 100644 index 00000000..86ac4eb6 --- /dev/null +++ b/config/routes/api_platform.yaml @@ -0,0 +1,5 @@ +api_platform: + resource: . + type: api_platform + prefix: /api + diff --git a/migrations/.gitignore b/migrations/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/src/ApiResource/.gitignore b/src/ApiResource/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/src/Controller/Api/ApiRegistrationController.php b/src/Controller/Api/ApiRegistrationController.php new file mode 100644 index 00000000..d13bb59c --- /dev/null +++ b/src/Controller/Api/ApiRegistrationController.php @@ -0,0 +1,10 @@ +security->getUser(); + return $user; + } +} \ No newline at end of file diff --git a/src/Controller/ApiLoginController.php b/src/Controller/Api/LoginController.php similarity index 92% rename from src/Controller/ApiLoginController.php rename to src/Controller/Api/LoginController.php index 9ba502da..7d3701fd 100644 --- a/src/Controller/ApiLoginController.php +++ b/src/Controller/Api/LoginController.php @@ -1,6 +1,6 @@ render('Registration/register.html.twig', ['form' => $form->createView()]); } + } diff --git a/src/Doctrine/ApiQueryExtension.php b/src/Doctrine/ApiQueryExtension.php new file mode 100644 index 00000000..3cec2edd --- /dev/null +++ b/src/Doctrine/ApiQueryExtension.php @@ -0,0 +1,56 @@ +filterEntity($queryBuilder, $resourceClass, $this->security->getUser()); + } + + public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void + { + // Same filters as for collections + $this->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); + } + + private function filterEntity(QueryBuilder $queryBuilder, string $resourceClass, User $user): void + { + $rootAlias = $queryBuilder->getRootAliases()[0]; + if (User::class === $resourceClass) { + $queryBuilder->andWhere(sprintf('%s.id = :current_user', $rootAlias)); + $queryBuilder->setParameter('current_user', $user->getId()); + } else if ( + (OpenPgpKey::class === $resourceClass) || + (Alias::class === $resourceClass) || + (Voucher::class === $resourceClass) + ) { + $queryBuilder->andWhere(sprintf('%s.user = :current_user', $rootAlias)); + $queryBuilder->setParameter('current_user', $user->getId()); + } + if (Voucher::class === $resourceClass) { + $queryBuilder->andWhere(sprintf('%s.redeemedTime is NULL', $rootAlias)); + } + if (Alias::class === $resourceClass) { + $queryBuilder->andWhere(sprintf('%s.deleted = false', $rootAlias)); + } + + } +} diff --git a/src/Entity/Alias.php b/src/Entity/Alias.php index 811c8f2b..46c40ecf 100644 --- a/src/Entity/Alias.php +++ b/src/Entity/Alias.php @@ -2,6 +2,10 @@ namespace App\Entity; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use App\Repository\AliasRepository; use Stringable; use DateTime; @@ -15,6 +19,30 @@ use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\AssociationOverride; use Doctrine\ORM\Mapping\Index; +use Symfony\Component\Serializer\Annotation\Groups; + +#[ApiResource( + security: 'is_granted("ROLE_USER")', + normalizationContext: ['groups' => ['read']], + denormalizationContext: ['groups' => ['write']], + + operations: [ + new Get( + uriTemplate: '/users/{userId}/aliases/{id}', + uriVariables: [ + 'id' => new Link(fromClass: Alias::class), + 'userId' => new Link(fromClass: User::class, toProperty: 'User'), + ] + ), + new GetCollection( + uriTemplate: '/users/{userId}/aliases', + uriVariables: [ + 'userId' => new Link(fromClass: User::class, toProperty: 'User') + ], + ), + ] + ), +] #[ORM\Entity(repositoryClass: AliasRepository::class)] #[ORM\AssociationOverrides([new AssociationOverride(name: 'domain', joinColumns: new ORM\JoinColumn(nullable: true))])] @@ -51,6 +79,7 @@ public function __construct() $this->updatedTime = $currentDateTime; } + #[Groups(['read'])] public function getSource(): ?string { return $this->source; diff --git a/src/Entity/OpenPgpKey.php b/src/Entity/OpenPgpKey.php index 5364f78f..df227d06 100644 --- a/src/Entity/OpenPgpKey.php +++ b/src/Entity/OpenPgpKey.php @@ -2,6 +2,8 @@ namespace App\Entity; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; use App\Repository\OpenPgpKeyRepository; use App\Traits\EmailTrait; use App\Traits\IdTrait; @@ -9,6 +11,16 @@ use App\Traits\UserAwareTrait; use Doctrine\ORM\Mapping as ORM; + +#[ApiResource( + routePrefix: '/user', + security: 'is_granted("ROLE_USER")', + normalizationContext: ['groups' => ['read']], + denormalizationContext: ['groups' => ['write']], + operations: [ + new GetCollection(uriTemplate: '/pgpkeys'), + ] +)] #[ORM\Entity(repositoryClass: OpenPgpKeyRepository::class)] #[ORM\Table(name: 'virtual_openpgp_keys')] class OpenPgpKey diff --git a/src/Entity/User.php b/src/Entity/User.php index 08313bcb..4c6eb9c2 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -2,6 +2,12 @@ namespace App\Entity; +use ApiPlatform\Action\NotFoundAction; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use App\Controller\Api\ApiRegisterController; use App\Repository\UserRepository; use Stringable; use DateTime; @@ -29,13 +35,35 @@ use App\Traits\TwofactorTrait; use App\Traits\UpdatedTimeTrait; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\Index; use Scheb\TwoFactorBundle\Model\BackupCodeInterface; use Scheb\TwoFactorBundle\Model\Totp\TwoFactorInterface; use Symfony\Component\PasswordHasher\Hasher\PasswordHasherAwareInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; -use Doctrine\ORM\Mapping\Index; +use Symfony\Component\Serializer\Annotation\Groups; +#[ApiResource( + security: 'is_granted("ROLE_USER")', + normalizationContext: ['groups' => ['read']], + denormalizationContext: ['groups' => ['write']], + operations: [ + new Get( + controller: NotFoundAction::class, + uriTemplate: '/users/{id}', + read: false, + output: false + ), + new GetCollection( + uriTemplate: '/users', + ), + #new Post( + # name: 'register_user', + # uriTemplate: '/register', + # controller: ApiRegistrationController::class, + #) + ] +)] #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: 'virtual_users')] #[Index(name: 'email_idx', columns: ['email'])] @@ -112,6 +140,7 @@ public function hasRole($role): bool /** * {@inheritdoc} */ + #[Groups(['read'])] public function getUsername(): ?string { return $this->getUserIdentifier(); @@ -120,7 +149,9 @@ public function getUsername(): ?string /** * @return string */ - public function getUserIdentifier(): string { + #[Groups(['read'])] + public function getUserIdentifier(): string + { return $this->email; } diff --git a/src/Entity/Voucher.php b/src/Entity/Voucher.php index 34243aba..04bae279 100644 --- a/src/Entity/Voucher.php +++ b/src/Entity/Voucher.php @@ -2,6 +2,9 @@ namespace App\Entity; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Repository\VoucherRepository; use Stringable; use DateTime; @@ -10,7 +13,18 @@ use App\Traits\UserAwareTrait; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\Index; +use Symfony\Component\Serializer\Annotation\Groups; + +#[ApiResource( + routePrefix: '/user', + security: 'is_granted("ROLE_USER")', + normalizationContext: ['groups' => ['read']], + denormalizationContext: ['groups' => ['write']], + operations: [ + new GetCollection(uriTemplate: '/vouchers'), + ] +)] #[ORM\Entity(repositoryClass: VoucherRepository::class)] #[ORM\Table(name: 'virtual_vouchers')] #[Index(name: 'code_idx', columns: ['code'])] @@ -49,6 +63,7 @@ public function isRedeemed(): bool return null !== $this->getRedeemedTime(); } + #[Groups(['read'])] public function getCode(): string { return $this->code; diff --git a/src/Traits/AliasAwareTrait.php b/src/Traits/AliasAwareTrait.php index f3466a4f..e7363c04 100644 --- a/src/Traits/AliasAwareTrait.php +++ b/src/Traits/AliasAwareTrait.php @@ -2,12 +2,15 @@ namespace App\Traits; + use App\Entity\Alias; +use Symfony\Component\Serializer\Annotation\Groups; trait AliasAwareTrait { private ?Alias $alias = null; + #[Groups(['read'])] public function getAlias(): ?Alias { return $this->alias; diff --git a/src/Traits/EmailTrait.php b/src/Traits/EmailTrait.php index d4c7cb9d..06f81476 100644 --- a/src/Traits/EmailTrait.php +++ b/src/Traits/EmailTrait.php @@ -3,12 +3,14 @@ namespace App\Traits; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; trait EmailTrait { #[ORM\Column(unique: true)] private ?string $email = ''; + #[Groups('read')] public function getEmail(): ?string { return $this->email; diff --git a/src/Traits/MailCryptTrait.php b/src/Traits/MailCryptTrait.php index 0dcb0213..624733c2 100644 --- a/src/Traits/MailCryptTrait.php +++ b/src/Traits/MailCryptTrait.php @@ -3,12 +3,14 @@ namespace App\Traits; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; trait MailCryptTrait { #[ORM\Column(options: ['default' => false])] private bool $mailCrypt = false; + #[Groups('read')] public function hasMailCrypt(): bool { return $this->mailCrypt; diff --git a/src/Traits/OpenPgpKeyTrait.php b/src/Traits/OpenPgpKeyTrait.php index 22226915..f9e53d36 100644 --- a/src/Traits/OpenPgpKeyTrait.php +++ b/src/Traits/OpenPgpKeyTrait.php @@ -4,6 +4,7 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; trait OpenPgpKeyTrait { @@ -19,6 +20,7 @@ trait OpenPgpKeyTrait #[ORM\Column(type: 'text')] public ?string $keyData = null; + #[Groups('read')] public function getKeyId(): ?string { return $this->keyId; @@ -29,6 +31,7 @@ public function setKeyId(?string $keyId): void $this->keyId = $keyId; } + #[Groups('read')] public function getKeyFingerprint(): ?string { return $this->keyFingerprint; @@ -39,6 +42,7 @@ public function setKeyFingerprint(?string $keyFingerprint): void $this->keyFingerprint = $keyFingerprint; } + #[Groups('read')] public function getKeyExpireTime(): ?DateTime { return $this->keyExpireTime; diff --git a/src/Traits/QuotaTrait.php b/src/Traits/QuotaTrait.php index eab563fd..3be02dcf 100644 --- a/src/Traits/QuotaTrait.php +++ b/src/Traits/QuotaTrait.php @@ -3,12 +3,14 @@ namespace App\Traits; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; trait QuotaTrait { #[ORM\Column(nullable: true)] private ?int $quota = null; + #[Groups('read')] public function getQuota(): ?int { return $this->quota; diff --git a/src/Traits/RandomTrait.php b/src/Traits/RandomTrait.php index fba15fc8..0ece7cf9 100644 --- a/src/Traits/RandomTrait.php +++ b/src/Traits/RandomTrait.php @@ -3,12 +3,16 @@ namespace App\Traits; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; + trait RandomTrait { + #[ORM\Column(options: ['default' => false])] private bool $random = false; + #[Groups(['read'])] public function isRandom(): bool { return $this->random; diff --git a/src/Traits/TwofactorTrait.php b/src/Traits/TwofactorTrait.php index d9250c6c..5ecccdfd 100644 --- a/src/Traits/TwofactorTrait.php +++ b/src/Traits/TwofactorTrait.php @@ -5,6 +5,7 @@ use Doctrine\ORM\Mapping as ORM; use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration; use Scheb\TwoFactorBundle\Model\Totp\TotpConfigurationInterface; +use Symfony\Component\Serializer\Annotation\Groups; trait TwofactorTrait { @@ -17,6 +18,7 @@ trait TwofactorTrait /** * {@inheritdoc} */ + #[Groups('read')] public function isTotpAuthenticationEnabled(): bool { return (bool) $this->totpConfirmed; diff --git a/src/Traits/UserAwareTrait.php b/src/Traits/UserAwareTrait.php index 8785706d..a2f83ba2 100644 --- a/src/Traits/UserAwareTrait.php +++ b/src/Traits/UserAwareTrait.php @@ -4,6 +4,8 @@ use App\Entity\User; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; + trait UserAwareTrait { diff --git a/symfony.lock b/symfony.lock index 7d0696d2..0ec453dd 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,18 @@ { + "api-platform/core": { + "version": "3.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.2", + "ref": "696d44adc3c0d4f5d25a2f1c4f3700dd8a5c6db9" + }, + "files": [ + "config/packages/api_platform.yaml", + "config/routes/api_platform.yaml", + "src/ApiResource/.gitignore" + ] + }, "behat/behat": { "version": "v3.5.0" }, @@ -71,6 +85,19 @@ "src/DataFixtures/AppFixtures.php" ] }, + "doctrine/doctrine-migrations-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.1", + "ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33" + }, + "files": [ + "config/packages/doctrine_migrations.yaml", + "migrations/.gitignore" + ] + }, "doctrine/event-manager": { "version": "v1.0.0" }, @@ -146,6 +173,18 @@ "mopa/composer-bridge": { "version": "v1.5.0" }, + "nelmio/cors-bundle": { + "version": "2.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.5", + "ref": "6bea22e6c564fba3a1391615cada1437d0bde39c" + }, + "files": [ + "config/packages/nelmio_cors.yaml" + ] + }, "nelmio/security-bundle": { "version": "2.4", "recipe": {