Commit 60840292 authored by mxh's avatar mxh
Browse files

Issue #3274797 by mxh: Test coverage

parent bda7047f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,4 +5,5 @@ core_version_requirement: ^9.3 || ^10
package: Other
dependencies:
  - drupal:user
  - drupal:options
  - entity:entity
+20 −6
Original line number Diff line number Diff line
@@ -128,18 +128,31 @@ function access_records_entity_type_build(array &$entity_types) {
 */
function access_records_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
  $etm = \Drupal::entityTypeManager();
  // Target entity types are content entities only, and we can only check
  // when we have a user entity as subject. Also matching access records can
  // only be done on persisted targets.
  if (!($entity instanceof ContentEntityInterface) || $entity->isNew() || !($subject = $etm->getStorage('user')->load($account->id()))) {
  // Target entity types are content entities only, and matching access records
  // can only be done on persisted targets.
  if (!($entity instanceof ContentEntityInterface) || $entity->isNew()) {
    return AccessResult::neutral();
  }
  /** @var \Drupal\user\UserInterface $subject */

  $target = $entity;
  $target_type = $target->getEntityType();
  $cacheability = new CacheableMetadata();

  // Either no configured access record types exist for this type of entity,
  /** @var \Drupal\user\UserInterface $subject */
  if (!($subject = $etm->getStorage('user')->load($account->id()))) {
    // When the subject has no stored entity, one is created on runtime here,
    // and then lookup whether an access record type exists for the target type.
    // If so, always revoke access, because matching records may only be valid
    // for existing user entities.
    $subject = $etm->getStorage('user')->create([
      'uid' => $account->id(),
      'status' => 0,
      'name' => '',
    ]);
    return AccessRecordType::loadForAccessCheck($subject, $target_type->id(), $operation, $cacheability, FALSE) ? AccessResult::forbidden()->addCacheableDependency($cacheability) : AccessResult::neutral()->addCacheableDependency($cacheability);
  }

  // Either no configured access record type exists for this type of entity,
  // or the user is an admin and thus has access anyway.
  if (AccessRecordType::loadForAccessCheck($subject, $target_type->id(), $operation, $cacheability)) {
    // As we are now aware of existing access record types that belong to this
@@ -157,6 +170,7 @@ function access_records_entity_access(EntityInterface $entity, $operation, Accou
    }
    try {
      $query = $etm->getStorage($target_type->id())->getQuery()
        ->addMetaData('op', $operation)
        ->accessCheck(TRUE)
        ->condition($target_type->getKey('id'), $target->id());
      if ($target instanceof TranslatableInterface) {
+21 −9
Original line number Diff line number Diff line
@@ -102,18 +102,25 @@ class AccessRecord extends EditorialContentEntityBase implements AccessRecordInt
      'ar_uid' => static::getDefaultEntityOwner(),
      'ar_changed_uid' => \Drupal::currentUser()->id(),
    ];
    if (!isset($values['enabled'])) {
    if (isset($values['ar_label']) && $values['ar_label'] !== '') {
      // Disable the label pattern when a label is already there.
      $values['label_pattern'] = '';
    }
    /** @var \Drupal\access_records\AccessRecordTypeInterface $access_record_type */
      if (isset($values['ar_type']) && ($access_record_type = \Drupal::entityTypeManager()->getStorage('access_record_type')->load($values['ar_type']))) {
        $values['ar_enabled'] = $access_record_type->getStatus();
    $access_record_type = isset($values['ar_type']) ? \Drupal::entityTypeManager()->getStorage('access_record_type')->load($values['ar_type']) : NULL;
    if ($access_record_type) {
      if (!isset($values['ar_subject_type'])) {
        $values['ar_subject_type'] = $access_record_type->getSubjectTypeId();
      }
      else {
        $values['ar_enabled'] = FALSE;
      if (!isset($values['ar_target_type'])) {
        $values['ar_target_type'] = $access_record_type->getTargetTypeId();
      }
      if (!isset($values['ar_operation'])) {
        $values['ar_operation'] = $access_record_type->getOperations();
      }
      if (!isset($values['ar_enabled'])) {
        $values['ar_enabled'] = $access_record_type->getStatus();
      }
    if (isset($values['ar_label']) && $values['ar_label'] !== '') {
      // Disable the label pattern when a label is already there.
      $values['label_pattern'] = '';
    }
  }

@@ -320,6 +327,11 @@ class AccessRecord extends EditorialContentEntityBase implements AccessRecordInt

    $fields['ar_enabled']
      ->setLabel(t('Enabled'))
      ->setDisplayOptions('form', [
        'type' => 'boolean_checkbox',
        'settings' => ['display_label' => TRUE],
        'weight' => 0,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

+9 −0
Original line number Diff line number Diff line
@@ -70,6 +70,15 @@ class AccessRecordsQueryAccessSubscriber implements EventSubscriberInterface {
      if ($query = $this->accessRecordQueryBuilder->selectByType($ar_type, $subject_id, $operation)) {
        $queries[] = $query;
      }
      else {
        // When the query could not be built, it is because the according type
        // configuration is either incomplete or invalid. Therefore we revoke
        // access overall and make the result uncacheable until it's fixed.
        $conditions->alwaysFalse(TRUE);
        $conditions->mergeCacheMaxAge(0);
        \Drupal::logger('access_records')->alert(sprintf("The configuration of access record type '%s' is incomplete or invalid. Access on '%s' entity types is blocked until that configuration is fixed.", $ar_type->id(), $target_type_id));
        return;
      }
    }
    if (empty($queries)) {
      return;
+594 −0

File added.

Preview size limit exceeded, changes collapsed.