RESTful-Drupal / restful

RESTful best practices for Drupal
https://drupal.org/project/restful
419 stars 173 forks source link

BUG: Entities created by RESTful get the uid property too late. #685

Open lukewertz opened 9 years ago

lukewertz commented 9 years ago

Using content access, I have a node type (notes) that users are allowed to created/edit/delete only their own nodes.

When RESTful's createEntity() method is called, the stub entity is created without the account information, which means that although the user is given access to create the entity, because the entity isn't (yet) owned by the user, no properties/fields can be set.

Allow me to demonstrate this with the following request:

POST /api/v1.0/lesson/264/note HTTP/1.1
Access-Token: eUWRUXwyMYIDhabSFApso6NoBHCh4tn88IOmmKeVyAI
Host: restful.local
Connection: close
User-Agent: Paw/2.2.5 (Macintosh; OS X/10.11.0) GCDHTTPRequest
Content-Length: 86

{
    "title": "Test Title",
    "body": "<p>An example note\r\n</p>",
    "lesson": 264
}

If I debug the output of entity_access (here), I'll see the following response:

object(stdClass)[158]
  public 'type' => string 'notes' (length=5)
  public 'language' => string 'und' (length=3)
  public 'is_new' => boolean true
  public 'status' => int 1
  public 'promote' => int 0
  public 'sticky' => int 0
string 'create' (length=6)

object(stdClass)[158]
  public 'type' => string 'notes' (length=5)
  public 'language' => string 'und' (length=3)
  public 'is_new' => boolean true
  public 'status' => int 1
  public 'promote' => int 0
  public 'sticky' => int 0
  public 'title' => string 'Test Title' (length=15)
string 'update' (length=6)

{"type":"http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html#sec10.4.1","title":"Property title cannot be set.","status":400,"detail":"Bad Request."}

When RESTful creates the entity here, there is no uid property on the element, therefore when the entity_access check is done for permission on the user account to update the in-memory entity (158 in my example), entity_access denies the $op because it cannot validate that the $entity is owned by the user making the request.

I would propose that when a stub entity is created, the uid property should be attached before any other access checks happen.

lukewertz commented 9 years ago

Just hacking at this to see how high-level I can go with a fix, I can validate that the following code gives me what I'm wanting:

  /**
   * {@inheritdoc}
   */
  public function createEntity() {
    $entity_info = $this->getEntityInfo();
    $bundle_key = $entity_info['entity keys']['bundle'];
    $values = $bundle_key ? array($bundle_key => $this->bundle) : array();

    if (empty($values['uid']) && $this->getAccount()) {
      $values['uid'] = $this->getAccount()->uid;
    }

    $entity = entity_create($this->entityType, $values);

    if ($this->checkEntityAccess('create', $this->entityType, $entity) === FALSE) {
      // User does not have access to create entity.
      $params = array('@resource' => $this->getPluginKey('label'));
      throw new RestfulForbiddenException(format_string('You do not have access to create a new @resource resource.', $params));
    }

    $wrapper = entity_metadata_wrapper($this->entityType, $entity);

    $this->setPropertyValues($wrapper);
    return array($this->viewEntity($wrapper->getIdentifier()));
  }
lukewertz commented 8 years ago

This issue should be fixed by https://github.com/RESTful-Drupal/restful/pull/749