og-8.x-1.x-dev/tests/src/Unit/Cache/Context/OgPermissionsCacheContextTest.php
tests/src/Unit/Cache/Context/OgPermissionsCacheContextTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\og\Unit\Cache\Context;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\PrivateKey;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\og\Cache\Context\OgPermissionsCacheContext;
use Drupal\og\MembershipManagerInterface;
use Drupal\og\OgMembershipInterface;
use Drupal\og\OgRoleInterface;
use Drupal\user\EntityOwnerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
/**
* Tests the OG permissions cache context.
*
* @group og
* @coversDefaultClass \Drupal\og\Cache\Context\OgPermissionsCacheContext
*/
class OgPermissionsCacheContextTest extends OgContextCacheContextTestBase {
use ProphecyTrait;
/**
* The membership manager service.
*/
protected MembershipManagerInterface|ObjectProphecy $membershipManager;
/**
* The current user.
*/
protected AccountInterface|ObjectProphecy $user;
/**
* The private key service.
*/
protected PrivateKey|ObjectProphecy $privateKey;
/**
* The entity type manager.
*/
protected EntityTypeManagerInterface|ObjectProphecy $entityTypeManager;
/**
* The OG role storage.
*/
protected EntityStorageInterface|ObjectProphecy $roleStorage;
/**
* The config factory.
*/
protected ConfigFactoryInterface|ObjectProphecy $configFactory;
/**
* The OG configuration.
*/
protected Config|ObjectProphecy $config;
/**
* The mocked private key value.
*/
protected const PRIVATE_KEY = 'private_key';
/**
* The mocked hash salt.
*/
protected const HASH_SALT = 'hash_salt';
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->group = $this->prophesize(ContentEntityInterface::class);
$this->group->willImplement(EntityOwnerInterface::class);
$this->membershipManager = $this->prophesize(MembershipManagerInterface::class);
$this->user = $this->prophesize(AccountInterface::class);
$this->privateKey = $this->prophesize(PrivateKey::class);
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
$this->roleStorage = $this->prophesize(EntityStorageInterface::class);
$this->configFactory = $this->prophesize(ConfigFactoryInterface::class);
$this->config = $this->prophesize(Config::class);
$this->entityTypeManager->getStorage('og_role')->willReturn($this->roleStorage);
$this->configFactory->get('og.settings')->willReturn($this->config->reveal());
$this->privateKey->get()->willReturn(self::PRIVATE_KEY);
new Settings(['hash_salt' => self::HASH_SALT]);
}
/**
* {@inheritdoc}
*
* @covers ::getContext
*/
public function testWithoutContext(): void {
$this->expectGroupContext();
$this->assertEquals(OgPermissionsCacheContext::NO_CONTEXT, $this->getContextResult());
}
/**
* {@inheritdoc}
*/
protected function setupExpectedContext($context): void {
$context += [
'user_id' => 1,
'is_authenticated' => TRUE,
'has_global_admin' => FALSE,
'group_owner_id' => 0,
'group_manager_full_access' => FALSE,
'membership_permissions' => NULL,
'membership_is_admin' => FALSE,
'non_member_permissions' => [],
'is_blocked' => FALSE,
];
$this->expectGroupContext($this->group->reveal());
$this->group->getEntityTypeId()->willReturn('entity_test');
$this->group->bundle()->willReturn('bundle');
$this->group->id()->willReturn('1');
$this->group->getOwnerId()->willReturn($context['group_owner_id']);
$this->config->get('group_manager_full_access')->willReturn($context['group_manager_full_access']);
$this->user->id()->willReturn($context['user_id']);
$this->user->isAuthenticated()->willReturn($context['is_authenticated']);
$this->user->hasPermission('administer organic groups')->willReturn($context['has_global_admin']);
$this->setupMembershipExpectation($context);
}
/**
* Sets up membership expectations for a test scenario.
*/
protected function setupMembershipExpectation(array $context): void {
if (!$context['is_authenticated']) {
return;
}
$this->membershipManager
->isMember($this->group->reveal(), $context['user_id'], [OgMembershipInterface::STATE_BLOCKED])
->willReturn($context['is_blocked']);
// Blocked users have no permissions so membership and roles don't matter.
if ($context['is_blocked']) {
return;
}
if ($context['membership_permissions'] !== NULL || $context['membership_is_admin']) {
$role = $this->prophesize(OgRoleInterface::class);
$role->isAdmin()->willReturn($context['membership_is_admin']);
$role->getPermissions()->willReturn($context['membership_permissions'] ?? []);
$membership = $this->prophesize(OgMembershipInterface::class);
$membership->getRoles()->willReturn([$role->reveal()]);
$this->membershipManager
->getMembership($this->group->reveal(), $context['user_id'])
->willReturn($membership->reveal());
return;
}
$this->membershipManager
->getMembership($this->group->reveal(), $context['user_id'])
->willReturn(NULL);
if (!$context['is_blocked']) {
$anonymous_role = $this->prophesize(OgRoleInterface::class);
$anonymous_role->getPermissions()->willReturn($context['non_member_permissions']);
$role_id = 'entity_test-bundle-' . OgRoleInterface::ANONYMOUS;
$this->roleStorage->load($role_id)->willReturn($anonymous_role->reveal());
}
}
/**
* {@inheritdoc}
*/
protected function getCacheContext(): CacheContextInterface {
return new OgPermissionsCacheContext(
$this->user->reveal(),
$this->ogContext->reveal(),
$this->membershipManager->reveal(),
$this->entityTypeManager->reveal(),
$this->privateKey->reveal(),
$this->configFactory->reveal(),
);
}
/**
* {@inheritdoc}
*/
public static function contextProvider(): array {
$admin_hash = self::hashPermissions([OgPermissionsCacheContext::ADMIN_PERMISSION]);
return [
'global admin' => [
[
'user_id' => 2,
'has_global_admin' => TRUE,
],
$admin_hash,
],
'group owner full access' => [
[
'user_id' => 3,
'group_owner_id' => 3,
'group_manager_full_access' => TRUE,
],
$admin_hash,
],
'admin role' => [
[
'user_id' => 4,
'membership_permissions' => ['ignored'],
'membership_is_admin' => TRUE,
],
$admin_hash,
],
'member permissions' => [
[
'user_id' => 5,
'membership_permissions' => ['approve', 'view'],
],
self::hashPermissions(['approve', 'view']),
],
'authenticated non-member permissions' => [
[
'user_id' => 6,
'non_member_permissions' => ['view group', 'access content'],
],
self::hashPermissions(['access content', 'view group']),
],
'anonymous user' => [
[
'user_id' => 0,
'is_authenticated' => FALSE,
],
OgPermissionsCacheContext::NO_CONTEXT,
],
'no permissions' => [
[
'user_id' => 7,
'membership_permissions' => [],
],
OgPermissionsCacheContext::NO_CONTEXT,
],
];
}
/**
* Returns the expected hash for the given permissions.
*/
protected static function hashPermissions(array $permissions): string {
sort($permissions);
return hash('sha256', self::PRIVATE_KEY . self::HASH_SALT . serialize($permissions));
}
}
