Overview

Founding when researching #3494915: Support entity-level + field-level access checking in auto-save — i.e. in `experience_builder.api.api.(layout.post|auto-save.post)`

How to reproduce

  1. user 1, has path edit access, user 2 does NOT have path edit access. Both have access to have other XB permissions
  2. user 1 uses XB with node 1 and sets path to /my-page
  3. user 2 uses XB with node 1

Right user 2 will get an error.

This because \Drupal\experience_builder\Controller\ApiLayoutController::get() will

return new PreviewEnvelope($this->buildPreviewRenderable($data, $entity, FALSE), $data);

The FALSE here is for $updateAutoSave

buildPreviewRenderable has

$updated_entity_form_fields = $this->converter->convert([
      'layout' => $content,
      // An empty model needs to be represented as \stdClass so that it is
      // correctly json encoded. But we need to convert it to an array before
      // we can extract it.
      'model' => (array) $model,
      'entity_form_fields' => $body['entity_form_fields'],
    ], $entity, validate: FALSE);
    // Store the auto-save entry.
    if ($updateAutoSave) {
      $this->autoSaveManager->save($entity, [
        'layout' => [$content],
        // An empty model needs to be represented as \stdClass so that it is
        // correctly json encoded. But we need to convert it to an array before
        // we can extract it.
        'model' => self::extractModelForSubtree($content, (array) $model),
        // Store the updated form build ID but leave all other fields as-is.
        // This allows us to re-submit the values from auto-save when we finally
        // publish the entity. Some field widgets make transformations to the form
        // data which cannot be repeated.
        // @see \Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase::validateElement
        'entity_form_fields' => \array_filter([
          'form_build_id' => $updated_entity_form_fields['form_build_id'] ?? NULL,
        ]) + $body['entity_form_fields'],
      ]);

convert() will check the field access on but since user 2 doesn't have edit access for path and path is in the auto-save it will throw an error.

But $updated_entity_form_fields is only used inside the if block if $updateAutoSave. But convert() also will update the entity with the new values of the XB field, so this must be done. Most of that logic does live in \Drupal\experience_builder\Controller\ClientServerConversionTrait::convertClientToServer so it could be called directly if we are not auto-saving

Proposed resolution

In \Drupal\experience_builder\Controller\ApiLayoutController::buildPreviewRenderable() when calling \Drupal\experience_builder\ClientDataToEntityConverter::convert() set $client_data['entity_form_fields'] to an empty array if $updateAutoSave is false.

There is not need to update these fields we are not going to be using the return value of the convert() to call \Drupal\experience_builder\AutoSave\AutoSaveManager::save()

User interface changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tedbow created an issue. See original summary.

tedbow’s picture

Turns out it is little more complicated because the entity is also update during convert() so we don't just care about the return value

tedbow’s picture

Title: ApiLayoutController::buildPreviewRenderable unnecessarily call \ClientDataToEntityConverter::converts causing errors » Previewing the Layout causes an error when the user does not have access to all fields in the auto-save data
Issue summary: View changes

tedbow’s picture

Issue tags: +Needs tests
tedbow’s picture

Status: Active » Needs work
Issue tags: -Needs tests

I added a test on 3519992-only-convert-layout that passes locally but fails on 0.x

wim leers’s picture

tedbow’s picture

Assigned: tedbow » Unassigned
Status: Needs work » Needs review
tedbow’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Updated the summary

tedbow’s picture

Assigned: Unassigned » larowlan

Assigning to @larowlan for review

larowlan’s picture

Assigned: larowlan » Unassigned
Status: Needs review » Reviewed & tested by the community

Looks good to me - thanks

wim leers’s picture

Component: Page builder » Internal HTTP API
Priority: Normal » Major
Issue tags: +stable blocker
  1. ✅ Test-only CI job: failed
  2. ✅ RTBC'd by @larowlan
  3. 🤯 Diagonally reading this MR resulted in me going "woahhhhh I think this probably explains a lot of bugs we've seen lately!" — so bumped to Major

🚢

  • wim leers committed df1c2138 on 0.x authored by tedbow
    Issue #3519992 by tedbow, larowlan: Previewing the Layout causes an...
wim leers’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.