Skip to content

Commit

Permalink
fix(dataproducer): CurrentUser result is uncacheable
Browse files Browse the repository at this point in the history
  • Loading branch information
pfrenssen committed Aug 5, 2024
1 parent b37fd9e commit 01d1bc9
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/Plugin/GraphQL/DataProducer/User/CurrentUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static function create(ContainerInterface $container, array $configuratio
}

/**
* CurrentUser constructor.
* Constructs a new CurrentUser data producer.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
Expand All @@ -59,7 +59,7 @@ public function __construct(array $configuration, string $plugin_id, array $plug
}

/**
* Returns current user.
* Returns the current user.
*
* @param \Drupal\graphql\GraphQL\Execution\FieldContext $field_context
* Field context.
Expand All @@ -68,9 +68,9 @@ public function __construct(array $configuration, string $plugin_id, array $plug
* The current user.
*/
public function resolve(FieldContext $field_context): AccountInterface {
// Response must be cached based on current user as a cache context,
// otherwise a new user would became a previous user.
$field_context->addCacheableDependency($this->currentUser);
// Response must be cached per user so that information from previously
// logged in users will not leak to newly logged in users.
$field_context->addCacheContexts(['user']);
return $this->currentUser;
}

Expand Down
92 changes: 92 additions & 0 deletions tests/src/Kernel/DataProducer/CurrentUserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

namespace Drupal\Tests\graphql\Kernel\DataProducer;

use Drupal\Core\Session\AccountInterface;
use Drupal\Tests\graphql\Kernel\GraphQLTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\graphql\GraphQL\Execution\FieldContext;
use Drupal\user\Entity\User;

/**
* Tests the current_user data producer.
*
* @coversDefaultClass \Drupal\graphql\Plugin\GraphQL\DataProducer\User\CurrentUser
* @group graphql
*/
class CurrentUserTest extends GraphQLTestBase {

use UserCreationTrait;

/**
* Test users.
*
* @var \Drupal\Core\Session\AccountInterface[]
*/
protected array $users;

/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();

// Create two test users.
$this->users = [
$this->createUser(),
$this->createUser(),
];

// Log out initially.
$this->container->get('current_user')->setAccount(User::getAnonymousUser());
}

/**
* @covers \Drupal\graphql\Plugin\GraphQL\DataProducer\User\CurrentUser::resolve
*/
public function testCurrentUser(): void {
// Initially no user is logged in.
$result = $this->executeDataProducer('current_user');
$this->assertInstanceOf(AccountInterface::class, $result);
$this->assertEquals(0, $result->id());

// Log in as the first user.
$this->container->get('current_user')->setAccount($this->users[0]);
$result = $this->executeDataProducer('current_user');
$this->assertInstanceOf(AccountInterface::class, $result);
$this->assertEquals($this->users[0]->id(), $result->id());

// Log in as the second user.
$this->container->get('current_user')->setAccount($this->users[1]);
$result = $this->executeDataProducer('current_user');
$this->assertInstanceOf(AccountInterface::class, $result);
$this->assertEquals($this->users[1]->id(), $result->id());

// Log out again.
$this->container->get('current_user')->setAccount(User::getAnonymousUser());
$result = $this->executeDataProducer('current_user');
$this->assertInstanceOf(AccountInterface::class, $result);
$this->assertEquals(0, $result->id());
}

/**
* {@inheritdoc}
*/
protected function executeDataProducer($id, array $contexts = []) {
/** @var \Drupal\graphql\Plugin\DataProducerPluginManager $manager */
$manager = $this->container->get('plugin.manager.graphql.data_producer');

/** @var \Drupal\graphql\Plugin\DataProducerPluginInterface $plugin */
$plugin = $manager->createInstance($id);

// The 'user' cache context should be added so that the results will be
// cached per user.
$context = $this->prophesize(FieldContext::class);
$context->addCacheContexts(['user'])->willReturn($context->reveal())->shouldBeCalled();

return $plugin->resolveField($context->reveal());
}

}

0 comments on commit 01d1bc9

Please sign in to comment.