Skip to content

Commit baf9746

Browse files
committed
minor(live): add security tests
1 parent ab8710f commit baf9746

File tree

5 files changed

+104
-1
lines changed

5 files changed

+104
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"symfony/options-resolver": "^5.4|^6.0|^7.0",
4646
"symfony/phpunit-bridge": "^6.0|^7.0",
4747
"symfony/property-info": "^5.4|^6.0|^7.0",
48-
"symfony/security-csrf": "^5.4|^6.0|^7.0",
48+
"symfony/security-bundle": "^5.4|^6.0|^7.0",
4949
"symfony/serializer": "^5.4|^6.0|^7.0",
5050
"symfony/twig-bundle": "^5.4|^6.0|^7.0",
5151
"symfony/validator": "^5.4|^6.0|^7.0",
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\LiveComponent\Tests\Fixtures\Component;
13+
14+
use Symfony\Component\Security\Core\User\InMemoryUser;
15+
use Symfony\Component\Security\Http\Attribute\CurrentUser;
16+
use Symfony\Component\Security\Http\Attribute\IsGranted;
17+
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
18+
use Symfony\UX\LiveComponent\Attribute\LiveAction;
19+
use Symfony\UX\LiveComponent\DefaultActionTrait;
20+
21+
/**
22+
* @author Kevin Bond <[email protected]>
23+
*/
24+
#[AsLiveComponent('with_security')]
25+
#[IsGranted('ROLE_USER')]
26+
class WithSecurity
27+
{
28+
use DefaultActionTrait;
29+
30+
public ?string $username = null;
31+
32+
#[LiveAction]
33+
public function setUsername(#[CurrentUser] InMemoryUser $user)
34+
{
35+
$this->username = $user->getUserIdentifier();
36+
}
37+
}

tests/Fixtures/Kernel.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Psr\Log\NullLogger;
1717
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
1818
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
19+
use Symfony\Bundle\SecurityBundle\SecurityBundle;
1920
use Symfony\Bundle\TwigBundle\TwigBundle;
2021
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
2122
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@@ -24,6 +25,7 @@
2425
use Symfony\Component\HttpFoundation\Response;
2526
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
2627
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
28+
use Symfony\Component\Security\Core\User\InMemoryUser;
2729
use Symfony\UX\LiveComponent\LiveComponentBundle;
2830
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component1;
2931
use Symfony\UX\LiveComponent\Tests\Fixtures\Serializer\Entity2Normalizer;
@@ -66,6 +68,7 @@ public function registerBundles(): iterable
6668
yield new FrameworkBundle();
6769
yield new TwigBundle();
6870
yield new DoctrineBundle();
71+
yield new SecurityBundle();
6972
yield new TwigComponentBundle();
7073
yield new LiveComponentBundle();
7174
yield new ZenstruckFoundryBundle();
@@ -115,6 +118,14 @@ protected function configureContainer(ContainerConfigurator $c): void
115118
'default_path' => '%kernel.project_dir%/tests/Fixtures/templates',
116119
]);
117120

121+
$c->extension('security', [
122+
'password_hashers' => [InMemoryUser::class => 'plaintext'],
123+
'providers' => ['users' => ['memory' => ['users' => ['kevin' => ['password' => 'pass', 'roles' => ['ROLE_USER']]]]]],
124+
'firewalls' => ['main' => [
125+
'lazy' => true,
126+
]],
127+
]);
128+
118129
$c->extension('twig_component', [
119130
'defaults' => [
120131
'Symfony\UX\LiveComponent\Tests\Fixtures\Component\\' => 'components/',
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div{{ attributes }}>
2+
Successful.
3+
4+
Username: {{ username }}
5+
</div>

tests/Functional/EventListener/LiveComponentSubscriberTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1515
use Symfony\Component\DomCrawler\Crawler;
1616
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
17+
use Symfony\Component\Security\Core\User\InMemoryUser;
1718
use Symfony\UX\LiveComponent\Tests\Fixtures\Entity\Entity1;
1819
use Symfony\UX\LiveComponent\Tests\LiveComponentTestHelper;
1920
use Zenstruck\Browser\Test\HasBrowser;
@@ -500,4 +501,53 @@ public function testWithNullableEntity(): void
500501
->assertContains('Prop1: default')
501502
;
502503
}
504+
505+
public function testCanHaveControllerAttributes(): void
506+
{
507+
$dehydrated = $this->dehydrateComponent($this->mountComponent('with_security'));
508+
509+
$this->browser()
510+
->post('/_components/with_security?props='.urlencode(json_encode($dehydrated->getProps())))
511+
->assertStatus(401)
512+
->actingAs(new InMemoryUser('kevin', 'pass', ['ROLE_USER']))
513+
->assertAuthenticated('kevin')
514+
->post('/_components/with_security?props='.urlencode(json_encode($dehydrated->getProps())))
515+
->assertSuccessful()
516+
;
517+
}
518+
519+
public function testCanInjectSecurityUserIntoAction(): void
520+
{
521+
$dehydrated = $this->dehydrateComponent($this->mountComponent('with_security'));
522+
$token = null;
523+
524+
$this->browser()
525+
->actingAs(new InMemoryUser('kevin', 'pass', ['ROLE_USER']))
526+
->post('/_components/with_security', [
527+
'body' => [
528+
'data' => json_encode([
529+
'props' => $dehydrated->getProps(),
530+
]),
531+
],
532+
])
533+
->assertSuccessful()
534+
->assertNotSee('username: kevin')
535+
->use(function (Crawler $crawler) use (&$token) {
536+
// get a valid token to use for actions
537+
$token = $crawler->filter('div')->first()->attr('data-live-csrf-value');
538+
})
539+
->throwExceptions()
540+
->post('/_components/with_security/setUsername', [
541+
'headers' => ['X-CSRF-TOKEN' => $token],
542+
'body' => [
543+
'data' => json_encode([
544+
'props' => $dehydrated->getProps(),
545+
'args' => [],
546+
]),
547+
],
548+
])
549+
->assertSuccessful()
550+
->assertSee('username: kevin')
551+
;
552+
}
503553
}

0 commit comments

Comments
 (0)