You are here

RestfulEntityAndPropertyAccessTestCase.test in RESTful 7.2

Same filename and directory in other branches
  1. 7 tests/RestfulEntityAndPropertyAccessTestCase.test

Contains RestfulEntityAndPropertyAccessTestCase

File

tests/RestfulEntityAndPropertyAccessTestCase.test
View source
<?php

/**
 * @file
 * Contains RestfulEntityAndPropertyAccessTestCase
 */
use Drupal\restful\Exception\ForbiddenException;
class RestfulEntityAndPropertyAccessTestCase extends DrupalWebTestCase {

  /**
   * {@inheritdoc}
   */
  public static function getInfo() {
    return array(
      'name' => 'Entity and property access',
      'description' => 'Test access for the entity and the properties.',
      'group' => 'RESTful',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp('restful_test');
  }

  /**
   * Test access control for creating an entity.
   */
  public function testCreateAccess() {
    $handler = restful()
      ->getResourceManager()
      ->getPlugin('test_articles:1.0');
    $parsed_body = array(
      'label' => $this
        ->randomName(),
    );

    // Non-privileged user.
    $user1 = $this
      ->drupalCreateUser();
    try {
      $handler
        ->setAccount($user1);
      $this
        ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_POST, $handler, $parsed_body);
      $this
        ->fail('Non-privileged user can create entity.');
    } catch (Exception $e) {
      $this
        ->pass('Non-privileged user cannot create entity.');
    }

    // Privileged user.
    $user2 = $this
      ->drupalCreateUser(array(
      'create article content',
    ));
    $handler
      ->setAccount($user2);
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_POST, $handler, $parsed_body);
    $this
      ->assertTrue($result['data'][0], 'Privileged user can create entity.');

    // Privileged user, with limited access to property.
    restful_test_deny_access_field();
    $handler
      ->setAccount($user2);
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_POST, $handler, $parsed_body);
    $this
      ->assertTrue($result['data'][0], 'Privileged user can create entity, with limited access to property.');

    // Privileged user, with limited access to property, and that property
    // passed in the request.
    $text1 = $this
      ->randomName();
    $parsed_body['body'] = $text1;
    try {
      $handler
        ->setAccount($user1);
      $this
        ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_POST, $handler, $parsed_body);
      $this
        ->fail('Non-privileged user can create entity with inaccessible property that was passed in the request.');
    } catch (Exception $e) {
      $this
        ->pass('Non-privileged user cannot create entity with inaccessible property that was passed in the request.');
    }
    restful_test_clear_access_field();
  }

  /**
   * Test access control for updating an entity.
   */
  public function testUpdateAccess() {
    $label = $this
      ->randomName();
    $new_label = $this
      ->randomName();
    $settings = array(
      'type' => 'article',
      'title' => $label,
    );
    $node = $this
      ->drupalCreateNode($settings);
    $id = $node->nid;
    $handler = restful()
      ->getResourceManager()
      ->getPlugin('test_articles:1.0');
    $parsed_body = array(
      'label' => $new_label,
    );

    // Non-privileged user.
    $user1 = $this
      ->drupalCreateUser();
    try {
      $handler
        ->setAccount($user1);
      $this
        ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_PUT, $handler, $parsed_body, $id);
      $this
        ->fail('Non-privileged user can update entity.');
    } catch (Exception $e) {
      $this
        ->pass('Non-privileged user cannot update entity.');
    }

    // Privileged user.
    $user2 = $this
      ->drupalCreateUser(array(
      'edit any article content',
    ));
    $handler
      ->setAccount($user2);
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_PUT, $handler, $parsed_body, $id);
    $this
      ->assertTrue($result['data'][0], 'Privileged user can update entity.');
    $this
      ->assertEqual($result['data'][0]['id'], $id, 'Updated entity has the same entity ID.');
    $this
      ->assertEqual($result['data'][0]['label'], $new_label, 'Entity label was updated.');

    // Privileged user, with limited access to property.
    restful_test_deny_access_field();
    $handler
      ->setAccount($user2);
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_PUT, $handler, $parsed_body, $id);
    $this
      ->assertTrue($result['data'][0], 'Privileged user can update entity, with limited access to property.');

    // Privileged user, with limited access to property, and that property
    // passed in the request.
    $text1 = $this
      ->randomName();
    $parsed_body['body'] = $text1;
    try {
      $handler
        ->setAccount($user1);
      $this
        ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_PUT, $handler, $parsed_body, $id);
      $this
        ->fail('Non-privileged user can update entity with inaccessible property that was passed in the request.');
    } catch (Exception $e) {
      $this
        ->pass('Non-privileged user cannot update entity with inaccessible property that was passed in the request.');
    }
    restful_test_clear_access_field();
  }

  /**
   * Test access control for viewing an entity.
   */
  public function testViewAccess() {
    $user1 = $this
      ->drupalCreateUser();
    $label = $this
      ->randomName();
    $settings = array(
      'type' => 'article',
      'title' => $label,
      'uid' => $user1->uid,
    );
    $node1 = $this
      ->drupalCreateNode($settings);
    $wrapper = entity_metadata_wrapper('node', $node1);
    $wrapper->body
      ->set(array(
      'value' => $this
        ->randomName(),
    ));
    $wrapper
      ->save();
    $handler = restful()
      ->getResourceManager()
      ->getPlugin('test_articles:1.2');

    // Privileged user.
    $handler
      ->setAccount($user1);
    $response = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_GET, $handler, array(), $node1->nid);
    $result = $response['data'][0];
    $this
      ->assertTrue($result['body'], 'Privileged user can view entity.');

    // Privileged user, with limited access to property.
    restful_test_deny_access_field();
    $handler
      ->setAccount($user1);
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_GET, $handler, array(), $node1->nid);
    $this
      ->assertTrue(!isset($result['data'][0]['body']), 'Privileged user can view entity but without inaccessible properties.');
    restful_test_clear_access_field();

    // Non-privileged user (Revoke "access content" permission).
    user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array(
      'access content',
    ));
    $user2 = drupal_anonymous_user();
    try {
      $handler
        ->setAccount($user2);
      $this
        ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_GET, $handler, array(), $node1->nid);
      $this
        ->fail('Non-privileged user can view entity.');
    } catch (Exception $e) {
      $this
        ->pass('Non-privileged user cannot view entity.');
    }
  }

  /**
   * Tests custom access callbacks at the resource method level.
   */
  public function testEndPointAccessCallback() {
    $settings = array(
      'type' => 'article',
    );
    $node = $this
      ->drupalCreateNode($settings);
    $handler = restful()
      ->getResourceManager()
      ->getPlugin('test_articles:1.3');
    try {
      $handler
        ->doGet($node->nid);
      $this
        ->fail('Custom access callback per resource\'s method not executed correctly.');
    } catch (ForbiddenException $e) {
      $this
        ->pass('Custom access callback per endpoint executed correctly.');
    }
    $handler
      ->setPath($node->nid);
    $handler
      ->setRequest(\Drupal\restful\Http\Request::create($handler
      ->versionedUrl($node->nid, array(
      'absolute' => FALSE,
    )), array(), \Drupal\restful\Http\RequestInterface::METHOD_HEAD));
    $handler
      ->process();
    $this
      ->pass('Custom access callback per endpoint executed correctly.');
  }

  /**
   * Test access callback per public field.
   */
  public function testPublicFieldAccess() {
    $settings = array(
      'title' => 'no access',
      'type' => 'article',
    );
    $node = $this
      ->drupalCreateNode($settings);
    $handler = restful()
      ->getResourceManager()
      ->getPlugin('test_articles:1.0');
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_GET, $handler, array(), $node->nid);
    $this
      ->assertNotNull($result['data'][0]['label'], 'Label access is allowed without access callback.');
    variable_set('restful_test_revoke_public_field_access', 'label');
    $handler = restful()
      ->getResourceManager()
      ->getPluginCopy('test_articles:1.0');
    $result = $this
      ->doRequest(\Drupal\restful\Http\RequestInterface::METHOD_GET, $handler, array(), $node->nid);
    $this
      ->assertTrue(empty($result['data'][0]['label']), 'Label access is denied with access callback.');
  }

  /**
   * Helper method to format a request.
   *
   * @param string $method
   *   The HTTP verb.
   * @param \Drupal\restful\Plugin\resource\ResourceInterface $handler
   *   The handler.
   * @param array $input
   *   The parsed body array.
   * @param string $path
   *   The path where to make the request.
   *
   * @return array
   *   The formatted output.
   */
  protected function doRequest($method, \Drupal\restful\Plugin\resource\ResourceInterface $handler, array $input = array(), $path = '') {
    $output = NULL;
    if ($method == \Drupal\restful\Http\RequestInterface::METHOD_POST) {
      $output = $handler
        ->doPost($input);
    }
    elseif ($method == \Drupal\restful\Http\RequestInterface::METHOD_PUT) {
      $output = $handler
        ->doPut($path, $input);
    }
    elseif ($method == \Drupal\restful\Http\RequestInterface::METHOD_PATCH) {
      $output = $handler
        ->doPatch($path, $input);
    }
    elseif ($method == \Drupal\restful\Http\RequestInterface::METHOD_GET) {
      $output = $handler
        ->doGet($path, $input);
    }
    if (!isset($output)) {
      return NULL;
    }
    $formatter = restful()
      ->getFormatterManager()
      ->negotiateFormatter(NULL, 'json');
    $formatter
      ->setResource($handler);
    return $formatter
      ->prepare($output);
  }

}