/** * Checks access to create an entity of any bundle for the given route. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The parameterized route. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) { $entity_type_id = $route->getRequirement($this->requirementsKey); $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type_id); // In case there is no "bundle" entity key, check create access with no // bundle specified. if (!$entity_type->hasKey('bundle')) { return $access_control_handler->createAccess(NULL, $account, [], TRUE); } $access = AccessResult::neutral(); $bundles = array_keys($this->entityTypeBundleInfo->getBundleInfo($entity_type_id)); // Include list cache tag as access might change if more bundles are added. if ($entity_type->getBundleEntityType()) { $access->addCacheTags($this->entityTypeManager->getDefinition($entity_type->getBundleEntityType())->getListCacheTags()); // Check if the user is allowed to create new bundles. If so, allow // access, so the add page can show a link to create one. // @see \Drupal\Core\Entity\Controller\EntityController::addPage() $bundle_access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type->getBundleEntityType()); $access = $access->orIf($bundle_access_control_handler->createAccess(NULL, $account, [], TRUE)); if ($access->isAllowed()) { return $access; } } // Check whether an entity of any bundle may be created. foreach ($bundles as $bundle) { $access = $access->orIf($access_control_handler->createAccess($bundle, $account, [], TRUE)); // In case there is a least one bundle user can create entities for, // access is allowed. if ($access->isAllowed()) { break; } } return $access; }
protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view') { $entity_type = $entity->getEntityType(); $entity_type_id = $entity->getEntityTypeId(); $entity_access = $this->entityTypeManager->getAccessControlHandler($entity_type_id); /** @var \Drupal\Core\Entity\EntityStorageInterface $entity_storage */ $entity_storage = $this->entityTypeManager->getStorage($entity_type_id); $map = ['view' => "view all {$entity_type_id} revisions", 'list' => "view all {$entity_type_id} revisions", 'update' => "revert all {$entity_type_id} revisions", 'delete' => "delete all {$entity_type_id} revisions"]; $bundle = $entity->bundle(); $type_map = ['view' => "view {$entity_type_id} {$bundle} revisions", 'list' => "view {$entity_type_id} {$bundle} revisions", 'update' => "revert {$entity_type_id} {$bundle} revisions", 'delete' => "delete {$entity_type_id} {$bundle} revisions"]; if (!$entity || !isset($map[$operation]) || !isset($type_map[$operation])) { // If there was no node to check against, or the $op was not one of the // supported ones, we return access denied. return FALSE; } // Statically cache access by revision ID, language code, user account ID, // and operation. $langcode = $entity->language()->getId(); $cid = $entity->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $operation; if (!isset($this->accessCache[$cid])) { // Perform basic permission checks first. if (!$account->hasPermission($map[$operation]) && !$account->hasPermission($type_map[$operation]) && !$account->hasPermission('administer nodes')) { $this->accessCache[$cid] = FALSE; return FALSE; } if (($admin_permission = $entity_type->getAdminPermission()) && $account->hasPermission($admin_permission)) { $this->accessCache[$cid] = TRUE; } else { // First check the access to the default revision and finally, if the // node passed in is not the default revision then access to that, too. $this->accessCache[$cid] = $entity_access->access($entity_storage->load($entity->id()), $operation, $account) && ($entity->isDefaultRevision() || $entity_access->access($entity, $operation, $account)); } } return $this->accessCache[$cid]; }
/** * Evaluate if the user has access to the field of an entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to check access on. * @param string $field * The name of the field to check access on. * @param string $operation * The operation access should be checked for. Usually one of "view" or * "edit". * @param \Drupal\Core\Session\AccountInterface $user * The user account to test access against. * * @return bool * TRUE if the user has access to the field on the entity, FALSE otherwise. */ protected function doEvaluate(ContentEntityInterface $entity, $field, $operation, AccountInterface $user) { if (!$entity->hasField($field)) { return FALSE; } $access = $this->entityTypeManager->getAccessControlHandler($entity->getEntityTypeId()); if (!$access->access($entity, $operation, $user)) { return FALSE; } $definition = $entity->getFieldDefinition($field); $items = $entity->get($field); return $access->fieldAccess($operation, $definition, $user, $items); }
/** * Checks access to the profile add page for the profile type. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * @param \Drupal\profile\Entity\ProfileTypeInterface $profile_type * The profile type entity. * * @return bool|\Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(Route $route, AccountInterface $account, ProfileTypeInterface $profile_type = NULL) { $access_control_handler = $this->entityTypeManager->getAccessControlHandler('profile'); if ($account->hasPermission('administer profile types')) { return AccessResult::allowed()->cachePerPermissions(); } $operation = $route->getRequirement('_profile_access_check'); if ($operation == 'add') { return $access_control_handler->access($profile_type, $operation, $account, TRUE); } if ($profile_type) { return $access_control_handler->createAccess($profile_type->id(), $account, [], TRUE); } // If checking whether a profile of any type may be created. foreach ($this->entityTypeManager->getStorage('profile_type')->loadMultiple() as $profile_type) { if (($access = $access_control_handler->createAccess($profile_type->id(), $account, [], TRUE)) && $access->isAllowed()) { return $access; } } // No opinion. return AccessResult::neutral(); }
/** * {@inheritdoc} */ protected function blockAccess(AccountInterface $account) { /** @var \Drupal\Core\Entity\EntityInterface $entity */ $entity = $this->getContextValue('entity'); $access = $entity->access('view', $account, TRUE); // Make sure we have access to the entity. if ($access->isAllowed()) { // Check that the entity in question has this field and a value. if ($entity instanceof FieldableEntityInterface && $entity->hasField($this->fieldName) && $entity->{$this->fieldName}->getValue()) { $access_handler = $this->entityTypeManager->getAccessControlHandler($this->entityTypeId); return $access_handler->fieldAccess('view', $this->getFieldDefinition(), $account, NULL, TRUE); } // Entity doesn't have this field, so access is denied. return AccessResult::forbidden(); } // If we don't have access to the entity, return the forbidden result. return $access; }
/** * Displays add links for the available bundles. * * Redirects to the add form if there's only one bundle available. * * @param string $entity_type_id * The entity type ID. * * @return \Symfony\Component\HttpFoundation\RedirectResponse|array * If there's only one available bundle, a redirect response. * Otherwise, a render array with the add links for each bundle. */ public function addPage($entity_type_id) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); $bundle_key = $entity_type->getKey('bundle'); $bundle_entity_type_id = $entity_type->getBundleEntityType(); $build = ['#theme' => 'entity_add_list', '#bundles' => []]; if ($bundle_entity_type_id) { $bundle_argument = $bundle_entity_type_id; $bundle_entity_type = $this->entityTypeManager->getDefinition($bundle_entity_type_id); $bundle_entity_type_label = $bundle_entity_type->getLowercaseLabel(); $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags(); // Build the message shown when there are no bundles. $link_text = $this->t('Add a new @entity_type.', ['@entity_type' => $bundle_entity_type_label]); $link_route_name = 'entity.' . $bundle_entity_type->id() . '.add_form'; $build['#add_bundle_message'] = $this->t('There is no @entity_type yet. @add_link', ['@entity_type' => $bundle_entity_type_label, '@add_link' => Link::createFromRoute($link_text, $link_route_name)->toString()]); // Filter out the bundles the user doesn't have access to. $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $access = $access_control_handler->createAccess($bundle_name, NULL, [], TRUE); if (!$access->isAllowed()) { unset($bundles[$bundle_name]); } $this->renderer->addCacheableDependency($build, $access); } // Add descriptions from the bundle entities. $bundles = $this->loadBundleDescriptions($bundles, $bundle_entity_type); } else { $bundle_argument = $bundle_key; } $form_route_name = 'entity.' . $entity_type_id . '.add_form'; // Redirect if there's only one bundle available. if (count($bundles) == 1) { $bundle_names = array_keys($bundles); $bundle_name = reset($bundle_names); return $this->redirect($form_route_name, [$bundle_argument => $bundle_name]); } // Prepare the #bundles array for the template. foreach ($bundles as $bundle_name => $bundle_info) { $build['#bundles'][$bundle_name] = ['label' => $bundle_info['label'], 'description' => isset($bundle_info['description']) ? $bundle_info['description'] : '', 'add_link' => Link::createFromRoute($bundle_info['label'], $form_route_name, [$bundle_argument => $bundle_name])]; } return $build; }
/** * Checks access to add a field collection item to its future host. * * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * * TODO: Document params * * @return string * A \Drupal\Core\Access\AccessInterface constant value. */ public function access(AccountInterface $account, $host_type, $host_id) { $access_control_handler = $this->entityTypeManager->getAccessControlHandler($host_type); $host = $this->entityTypeManager->getStorage($host_type)->load($host_id); return $access_control_handler->access($host, 'update', $account, TRUE); }
/** * Gets the access handler for the target entity type. * * @return \Drupal\Core\Entity\EntityAccessControlHandlerInterface * The access handler. */ protected function getAccessHandler() { $entity_type_id = $this->getFieldSetting('target_type'); return $this->entityTypeManager->getAccessControlHandler($entity_type_id); }