Skip to content

Commit 4882ce4

Browse files
committed
Add resetFormatsAfterRequest issue test
1 parent 6b01ba3 commit 4882ce4

17 files changed

+174
-6
lines changed

.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ DATABASE_URL=sqlite:///%kernel.project_dir%/var/test.db3
1414
###> symfony/mailer ###
1515
MAILER_DSN=null://null
1616
###< symfony/mailer ###
17+
18+
###> lexik/jwt-authentication-bundle ###
19+
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
20+
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
21+
JWT_PASSPHRASE=b406fa29adfd637669a87d0d0e0032139731110641fcf3ac692c3fde392a9566
22+
###< lexik/jwt-authentication-bundle ###

.github/workflows/symfony.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,8 @@ jobs:
5555
- name: Load Doctrine fixtures
5656
run: php bin/console doctrine:fixtures:load --quiet
5757

58+
- name: Generate JWT keypair
59+
run: php bin/console lexik:jwt:generate-keypair
60+
5861
- name: Run functional tests
5962
run: vendor/bin/codecept run Functional

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ yarn-error.log
3434
/phpunit.xml
3535
.phpunit.result.cache
3636
###< phpunit/phpunit ###
37+
38+
###> lexik/jwt-authentication-bundle ###
39+
/config/jwt/*.pem
40+
###< lexik/jwt-authentication-bundle ###

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ Lastly, if you just want to see the module in action and run the tests yourself
2424
```shell
2525
composer update
2626
```
27-
3. Update database schema and load Doctrine fixtures
27+
3. Update database schema, load Doctrine fixtures and generate JWT keypair
2828
```shell
2929
php bin/console doctrine:schema:update --force
3030

3131
php bin/console doctrine:fixtures:load --quiet
32+
33+
php bin/console lexik:jwt:generate-keypair
3234
```
3335

3436
Then, go to the project directory and run:

composer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"php": ">=8.2.0",
1515
"ext-ctype": "*",
1616
"ext-iconv": "*",
17+
"api-platform/symfony": "^4.0",
1718
"doctrine/doctrine-bundle": "^2.11",
19+
"lexik/jwt-authentication-bundle": "^3.1",
1820
"symfony/apache-pack": "^1.0",
1921
"symfony/console": "6.4.*",
2022
"symfony/dotenv": "6.4.*",
@@ -34,6 +36,7 @@
3436
"codeception/module-asserts": "^3.2",
3537
"codeception/module-doctrine": "^3.1",
3638
"codeception/module-phpbrowser": "^3.0",
39+
"codeception/module-rest": "^3.4",
3740
"codeception/module-symfony": "^3.2 | *@dev",
3841
"doctrine/doctrine-fixtures-bundle": "^3.5",
3942
"friendsofphp/php-cs-fixer": "^3.46",
@@ -102,7 +105,8 @@
102105
],
103106
"post-create-project-cmd": [
104107
"@php bin/console doctrine:schema:update --force",
105-
"@php bin/console doctrine:fixtures:load --quiet"
108+
"@php bin/console doctrine:fixtures:load --quiet",
109+
"@php bin/console lexik:jwt:generate-keypair"
106110
]
107111
},
108112
"conflict": {

config/bundles.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@
99
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
1010
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
1111
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
12+
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
13+
Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true],
1214
];

config/packages/api_platform.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symfony\Config\ApiPlatformConfig;
6+
7+
return static function (ApiPlatformConfig $apiPlatformConfig): void {
8+
$apiPlatformConfig->title('Hello API Platform');
9+
$apiPlatformConfig->version('1.0.0');
10+
$apiPlatformConfig->formats('jsonld', ['mime_types' => ['application/ld+json']]);
11+
$apiPlatformConfig->formats('json', ['mime_types' => ['application/json']]);
12+
$defaults = $apiPlatformConfig->defaults();
13+
$defaults->stateless(true);
14+
$defaults->cacheHeaders(['vary' => ['Content-Type', 'Authorization', 'Origin']]);
15+
$apiPlatformConfig->doctrine(['enabled' => false]);
16+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symfony\Config\LexikJwtAuthenticationConfig;
6+
7+
return static function (LexikJwtAuthenticationConfig $lexikJwtAuthenticationConfig): void {
8+
$lexikJwtAuthenticationConfig->secretKey('%env(resolve:JWT_SECRET_KEY)%')
9+
->publicKey('%env(resolve:JWT_PUBLIC_KEY)%')
10+
->passPhrase('%env(JWT_PASSPHRASE)%');
11+
};

config/packages/security.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919
->pattern('^/(_(profiler|wdt)|css|images|js)/')
2020
->security(false);
2121

22+
$apiFirewall = $security->firewall('api');
23+
$apiFirewall
24+
->pattern('^/api')
25+
->stateless(true)
26+
->provider('app_user_provider')
27+
->jwt();
28+
$apiFirewall->jsonLogin([
29+
'check_path' => '/api/login',
30+
'success_handler' => 'lexik_jwt_authentication.handler.authentication_success',
31+
'failure_handler' => 'lexik_jwt_authentication.handler.authentication_failure',
32+
]);
33+
2234
$mainFirewall = $security->firewall('main');
2335
$mainFirewall
2436
->lazy(true)
@@ -27,7 +39,7 @@
2739
$mainFirewall->logout(['path' => 'app_logout']);
2840
$mainFirewall->rememberMe(['secret' => '%env(APP_SECRET)%']);
2941

30-
$security->accessControl([
31-
'path' => '^/dashboard', 'roles' => 'ROLE_USER'
32-
]);
42+
$security->accessControl(['path' => '^/api/login', 'roles' => 'PUBLIC_ACCESS']);
43+
$security->accessControl(['path' => '^/api', 'roles' => 'IS_AUTHENTICATED_FULLY']);
44+
$security->accessControl(['path' => '^/dashboard', 'roles' => 'ROLE_USER']);
3345
};

config/packages/uid.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symfony\Config\FrameworkConfig;
6+
7+
return static function (FrameworkConfig $framework): void {
8+
$uid = $framework->uid();
9+
$uid->defaultUuidVersion(7);
10+
$uid->timeBasedUuidVersion(7);
11+
};

config/routes.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,7 @@
8888
$routes->add('send_email', '/send-email')
8989
->controller(App\Controller\SendEmailController::class)
9090
->methods(['GET']);
91+
92+
$routes->add('api_login', '/api/login')
93+
->methods(['POST']);
9194
};

config/routes/api_platform.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
6+
7+
return static function (RoutingConfigurator $routes): void {
8+
$routes->import('.', 'api_platform')
9+
->prefix('/api');
10+
};

src/ApiResource/Book.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace App\ApiResource;
4+
5+
use ApiPlatform\Metadata\ApiResource;
6+
use Symfony\Component\Validator\Constraints\NotNull;
7+
8+
#[ApiResource]
9+
class Book
10+
{
11+
#[NotNull]
12+
public string $name;
13+
}

symfony.lock

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
{
2+
"api-platform/symfony": {
3+
"version": "4.1",
4+
"recipe": {
5+
"repo": "github.com/symfony/recipes",
6+
"branch": "main",
7+
"version": "4.0",
8+
"ref": "e9952e9f393c2d048f10a78f272cd35e807d972b"
9+
},
10+
"files": [
11+
"config/packages/api_platform.yaml",
12+
"config/routes/api_platform.yaml",
13+
"src/ApiResource/.gitignore"
14+
]
15+
},
216
"codeception/codeception": {
317
"version": "5.0",
418
"recipe": {
@@ -46,6 +60,18 @@
4660
"./.php-cs-fixer.dist.php"
4761
]
4862
},
63+
"lexik/jwt-authentication-bundle": {
64+
"version": "3.1",
65+
"recipe": {
66+
"repo": "github.com/symfony/recipes",
67+
"branch": "main",
68+
"version": "2.5",
69+
"ref": "e9481b233a11ef7e15fe055a2b21fd3ac1aa2bb7"
70+
},
71+
"files": [
72+
"config/packages/lexik_jwt_authentication.yaml"
73+
]
74+
},
4975
"phpstan/phpstan": {
5076
"version": "1.10",
5177
"recipe": {
@@ -215,6 +241,18 @@
215241
"./templates/base.html.twig"
216242
]
217243
},
244+
"symfony/uid": {
245+
"version": "6.4",
246+
"recipe": {
247+
"repo": "github.com/symfony/recipes",
248+
"branch": "main",
249+
"version": "6.2",
250+
"ref": "d294ad4add3e15d7eb1bae0221588ca89b38e558"
251+
},
252+
"files": [
253+
"config/packages/uid.yaml"
254+
]
255+
},
218256
"symfony/validator": {
219257
"version": "7.0",
220258
"recipe": {

tests/Functional.suite.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ modules:
99
- Doctrine:
1010
depends: Symfony
1111
cleanup: true
12+
- REST:
13+
depends: Symfony

tests/Functional/IssuesCest.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use App\Entity\User;
88
use App\Tests\Support\FunctionalTester;
9+
use Codeception\Util\HttpCode;
910
use Doctrine\DBAL\Connection;
1011

1112
final class IssuesCest
@@ -19,7 +20,7 @@ public function keepDoctrineDbalConnection(FunctionalTester $I)
1920
User::class,
2021
[
2122
'email' => 'fixture@fixture.test',
22-
'password' => uniqid(),
23+
'password' => uniqid(more_entropy: true),
2324
]
2425
);
2526
$ormConnection = $I->grabService('doctrine.orm.default_entity_manager')->getConnection();
@@ -53,4 +54,22 @@ public function runSymfonyConsoleCommandIgnoresSpecificOptions(FunctionalTester
5354
$numRecords = $I->grabNumRecords(User::class);
5455
$I->assertSame(1, $numRecords);
5556
}
57+
58+
/**
59+
* @see https://github.com/Codeception/module-symfony/pull/209
60+
*/
61+
public function resetFormatsAfterRequest(FunctionalTester $I)
62+
{
63+
$I->amApiAuthenticated();
64+
$I->haveHttpHeader('Content-Type', 'application/json');
65+
$I->haveHttpHeader('Accept', 'application/json');
66+
$I->sendPost('/api/books');
67+
$I->seeResponseCodeIs(HttpCode::UNPROCESSABLE_ENTITY);
68+
$I->seeHttpHeader('Content-Type', 'application/problem+json; charset=utf-8');
69+
70+
$I->amApiAuthenticated(); // This would fail because of overwrite of format mimetypes
71+
$I->sendPost('/api/books', ['name' => 'test']);
72+
$I->seeResponseCodeIs(HttpCode::CREATED);
73+
$I->seeHttpHeader('Content-Type', 'application/json; charset=utf-8');
74+
}
5675
}

tests/Support/FunctionalTester.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,16 @@
99
class FunctionalTester extends Actor
1010
{
1111
use _generated\FunctionalTesterActions;
12+
13+
public function amApiAuthenticated(): void
14+
{
15+
$this->haveHttpHeader('content-type', 'application/json');
16+
$this->sendPost('/api/login', [
17+
'username' => 'john_doe@gmail.com',
18+
'password' => '123456',
19+
]);
20+
$token = $this->grabDataFromResponseByJsonPath('$.token')[0];
21+
22+
$this->amBearerAuthenticated($token);
23+
}
1224
}

0 commit comments

Comments
 (0)