3 namespace Drupal\Tests\entity\Unit;
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Cache\Context\CacheContextsManager;
7 use Drupal\Core\DependencyInjection\ContainerBuilder;
8 use Drupal\Core\Entity\ContentEntityInterface;
9 use Drupal\Core\Entity\ContentEntityTypeInterface;
10 use Drupal\Core\Entity\EntityInterface;
11 use Drupal\Core\Entity\EntityPublishedInterface;
12 use Drupal\Core\Entity\EntityTypeInterface;
13 use Drupal\Core\Extension\ModuleHandlerInterface;
14 use Drupal\Core\Language\Language;
15 use Drupal\Core\Language\LanguageInterface;
16 use Drupal\Core\Session\AccountInterface;
17 use Drupal\entity\EntityAccessControlHandler;
18 use Drupal\entity\EntityPermissionProvider;
19 use Drupal\Tests\UnitTestCase;
20 use Drupal\user\EntityOwnerInterface;
21 use Prophecy\Argument;
24 * @coversDefaultClass \Drupal\entity\EntityAccessControlHandler
27 class EntityAccessControlHandlerTest extends UnitTestCase {
32 protected function setUp() {
35 $module_handler = $this->prophesize(ModuleHandlerInterface::class);
36 $module_handler->invokeAll(Argument::any(), Argument::any())->willReturn([]);
37 $cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
38 $cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
40 $container = new ContainerBuilder();
41 $container->set('module_handler', $module_handler->reveal());
42 $container->set('cache_contexts_manager', $cache_contexts_manager->reveal());
43 \Drupal::setContainer($container);
47 * @covers ::checkAccess
48 * @covers ::checkEntityPermissions
49 * @covers ::checkEntityOwnerPermissions
50 * @covers ::checkCreateAccess
52 * @dataProvider accessProvider
54 public function testAccess(EntityInterface $entity, $operation, $account, $allowed) {
55 $handler = new EntityAccessControlHandler($entity->getEntityType());
56 $handler->setStringTranslation($this->getStringTranslationStub());
57 $result = $handler->access($entity, $operation, $account);
58 $this->assertEquals($allowed, $result);
62 * @covers ::checkCreateAccess
64 * @dataProvider createAccessProvider
66 public function testCreateAccess(EntityTypeInterface $entity_type, $bundle, $account, $allowed) {
67 $handler = new EntityAccessControlHandler($entity_type);
68 $handler->setStringTranslation($this->getStringTranslationStub());
69 $result = $handler->createAccess($bundle, $account);
70 $this->assertEquals($allowed, $result);
74 * Data provider for testAccess().
77 * A list of testAccess method arguments.
79 public function accessProvider() {
82 $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
83 $entity_type->id()->willReturn('green_entity');
84 $entity_type->getAdminPermission()->willReturn('administer green_entity');
85 $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE);
86 $entity_type->getHandlerClass('permission_provider')->willReturn(EntityPermissionProvider::class);
88 // User with the admin permission can do anything.
89 $entity = $this->buildMockEntity($entity_type->reveal());
90 $account = $this->prophesize(AccountInterface::class);
91 $account->id()->willReturn(6);
92 $account->hasPermission('administer green_entity')->willReturn(TRUE);
93 $data[] = [$entity->reveal(), 'view', $account->reveal(), TRUE];
94 $data[] = [$entity->reveal(), 'update', $account->reveal(), TRUE];
95 $data[] = [$entity->reveal(), 'delete', $account->reveal(), TRUE];
97 // Entity with no owner.
98 $entity = $this->buildMockEntity($entity_type->reveal());
99 // User who has access.
100 $first_account = $this->prophesize(AccountInterface::class);
101 $first_account->id()->willReturn(6);
102 $first_account->hasPermission('view green_entity')->willReturn(TRUE);
103 $first_account->hasPermission(Argument::any())->willReturn(FALSE);
104 // User who doesn't have access.
105 $second_account = $this->prophesize(AccountInterface::class);
106 $second_account->id()->willReturn(7);
107 $second_account->hasPermission('view green_entity')->willReturn(FALSE);
108 $second_account->hasPermission(Argument::any())->willReturn(FALSE);
109 $data[] = [$entity->reveal(), 'view', $first_account->reveal(), TRUE];
110 $data[] = [$entity->reveal(), 'view', $second_account->reveal(), FALSE];
112 // Entity with owner.
113 $entity = $this->buildMockEntity($entity_type->reveal(), 6);
115 $first_account = $this->prophesize(AccountInterface::class);
116 $first_account->id()->willReturn(6);
117 $first_account->hasPermission('update own green_entity')->willReturn(TRUE);
118 $first_account->hasPermission(Argument::any())->willReturn(FALSE);
120 $second_account = $this->prophesize(AccountInterface::class);
121 $second_account->id()->willReturn(7);
122 $second_account->hasPermission('update own green_entity')->willReturn(TRUE);
123 $second_account->hasPermission(Argument::any())->willReturn(FALSE);
124 // User who can update any.
125 $third_account = $this->prophesize(AccountInterface::class);
126 $third_account->id()->willReturn(8);
127 $third_account->hasPermission('update any green_entity')->willReturn(TRUE);
128 $third_account->hasPermission(Argument::any())->willReturn(FALSE);
129 $data[] = [$entity->reveal(), 'update', $first_account->reveal(), TRUE];
130 $data[] = [$entity->reveal(), 'update', $second_account->reveal(), FALSE];
131 $data[] = [$entity->reveal(), 'update', $third_account->reveal(), TRUE];
133 // Test the unpublished permissions.
134 $entity_first_other_up = $this->buildMockEntity($entity_type->reveal(), 9999, 'first', FALSE);
135 $entity_first_own_up = $this->buildMockEntity($entity_type->reveal(), 14, 'first', FALSE);
136 $entity_first_own_bundle_up = $this->buildMockEntity($entity_type->reveal(), 15, 'first', FALSE);
138 $entity_second_other_up = $this->buildMockEntity($entity_type->reveal(), 9999, 'second', FALSE);
139 $entity_second_own_up = $this->buildMockEntity($entity_type->reveal(), 14, 'second', FALSE);
140 $entity_second_own_bundle_up = $this->buildMockEntity($entity_type->reveal(), 15, 'second', FALSE);
142 $user_view_own_up = $this->buildMockUser(14, 'view own unpublished green_entity');
143 $user_view_other = $this->buildMockUser(15, 'view green_entity');
145 $data['entity_first_other_up user_view_own_up'] = [$entity_first_other_up->reveal(), 'view', $user_view_own_up->reveal(), FALSE];
146 $data['entity_first_own_up user_view_own_up'] = [$entity_first_own_up->reveal(), 'view', $user_view_own_up->reveal(), TRUE];
147 $data['entity_first_own_bundle_up user_view_own_up'] = [$entity_first_own_bundle_up->reveal(), 'view', $user_view_own_up->reveal(), FALSE];
148 $data['entity_second_other_up user_view_own_up'] = [$entity_second_other_up->reveal(), 'view', $user_view_own_up->reveal(), FALSE];
149 $data['entity_second_own_up user_view_own_up'] = [$entity_second_own_up->reveal(), 'view', $user_view_own_up->reveal(), TRUE];
150 $data['entity_second_own_bundle_up user_view_own_up'] = [$entity_second_own_bundle_up->reveal(), 'view', $user_view_own_up->reveal(), FALSE];
152 $data['entity_first_other_up user_view_other'] = [$entity_first_other_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
153 $data['entity_first_own_up user_view_other'] = [$entity_first_own_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
154 $data['entity_first_own_bundle_up user_view_other'] = [$entity_first_own_bundle_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
155 $data['entity_second_other_up user_view_other'] = [$entity_second_other_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
156 $data['entity_second_own_up user_view_other'] = [$entity_second_own_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
157 $data['entity_second_own_bundle_up user_view_other'] = [$entity_second_own_bundle_up->reveal(), 'view', $user_view_other->reveal(), FALSE];
163 * Data provider for testCreateAccess().
166 * A list of testCreateAccess method arguments.
168 public function createAccessProvider() {
171 $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
172 $entity_type->id()->willReturn('green_entity');
173 $entity_type->getAdminPermission()->willReturn('administer green_entity');
174 $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE);
175 $entity_type->getHandlerClass('permission_provider')->willReturn(EntityPermissionProvider::class);
177 // User with the admin permission.
178 $account = $this->prophesize(AccountInterface::class);
179 $account->id()->willReturn(6);
180 $account->hasPermission('administer green_entity')->willReturn(TRUE);
181 $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
184 $account = $this->prophesize(AccountInterface::class);
185 $account->id()->willReturn(6);
186 $account->hasPermission('create green_entity')->willReturn(TRUE);
187 $account->hasPermission(Argument::any())->willReturn(FALSE);
188 $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
190 // Ordinary user, entity with a bundle.
191 $account = $this->prophesize(AccountInterface::class);
192 $account->id()->willReturn(6);
193 $account->hasPermission('create first_bundle green_entity')->willReturn(TRUE);
194 $account->hasPermission(Argument::any())->willReturn(FALSE);
195 $data[] = [$entity_type->reveal(), 'first_bundle', $account->reveal(), TRUE];
197 // User with no permissions.
198 $account = $this->prophesize(AccountInterface::class);
199 $account->id()->willReturn(6);
200 $account->hasPermission(Argument::any())->willReturn(FALSE);
201 $data[] = [$entity_type->reveal(), NULL, $account->reveal(), FALSE];
207 * Builds a mock entity.
209 * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
211 * @param string $owner_id
214 * @return \Prophecy\Prophecy\ObjectProphecy
217 protected function buildMockEntity(EntityTypeInterface $entity_type, $owner_id = NULL, $bundle = NULL, $published = NULL) {
218 $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
219 $entity = $this->prophesize(ContentEntityInterface::class);
220 if (isset($published)) {
221 $entity->willImplement(EntityPublishedInterface::class);
224 $entity->willImplement(EntityOwnerInterface::class);
226 if (isset($published)) {
227 $entity->isPublished()->willReturn($published);
230 $entity->getOwnerId()->willReturn($owner_id);
233 $entity->bundle()->willReturn($bundle ?: $entity_type->id());
234 $entity->isNew()->willReturn(FALSE);
235 $entity->uuid()->willReturn('fake uuid');
236 $entity->id()->willReturn('fake id');
237 $entity->getRevisionId()->willReturn(NULL);
238 $entity->language()->willReturn(new Language(['id' => $langcode]));
239 $entity->getEntityTypeId()->willReturn($entity_type->id());
240 $entity->getEntityType()->willReturn($entity_type);
241 $entity->getCacheContexts()->willReturn([]);
242 $entity->getCacheTags()->willReturn([]);
243 $entity->getCacheMaxAge()->willReturn(Cache::PERMANENT);
249 protected function buildMockUser($uid, $permission) {
250 $account = $this->prophesize(AccountInterface::class);
251 $account->id()->willReturn($uid);
252 $account->hasPermission($permission)->willReturn(TRUE);
253 $account->hasPermission(Argument::any())->willReturn(FALSE);