Here's my use case: I want to disable certain endpoints by using an environment specific settings file and config overrides. Here's what I tried:

$config['rest.resource.delete_account']['status'] = FALSE;

However it doesn't look like this is going to work. Based on the alterRoutes method, the resource routes don't seem to care whether status is on or not. I used the REST module to disable the endpoint and it seems to just delete the config from the config table. I copied alterRoutes below for reference.

  protected function alterRoutes(RouteCollection $collection) {
    // Iterate over all enabled REST resource configs.
    /** @var \Drupal\rest\RestResourceConfigInterface[] $resource_configs */
    $resource_configs = $this->resourceConfigStorage->loadMultiple();
    // Iterate over all enabled resource plugins.
    foreach ($resource_configs as $resource_config) {
      $resource_routes = $this->getRoutesForResourceConfig($resource_config);
      $collection->addCollection($resource_routes);
    }
  }

My proposed solution is to add something in the alterRoutes method that looks at whether the resource has an active status. Let me know if there are problems with this approach.

Comments

dpolant created an issue. See original summary.

dpolant’s picture

Title: REST resources do not seem to respect config overrides » REST resources do not seem to respect resource config status
damienmckenna’s picture

Should this be looked at from the greater config entity perspective? Should all config entities be disable-able?

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

wim leers’s picture

Category: Support request » Bug report
Related issues: +#2308745: Remove rest.settings.yml, use rest_resource config entities

Confirmed. Great catch!

Should all config entities be disable-able?

That's already the case: \Drupal\Core\Config\Entity\ConfigEntityInterface::enable().

But of course the REST module long predates config entities. This was overlooked in #2308745: Remove rest.settings.yml, use rest_resource config entities.

wim leers’s picture

Status: Active » Needs review
Issue tags: +DX (Developer Experience), +API-First Initiative, +Needs tests
StatusFileSize
new1.24 KB

It already had a comment // Iterate over all enabled REST resource configs.… but that didn't reflect reality sadly. It also still had // Iterate over all enabled resource plugins., which should have been removed in #2308745: Remove rest.settings.yml, use rest_resource config entities.

wim leers’s picture

Title: REST resources do not seem to respect resource config status » REST Resource config entities do not seem to respect the status (enabled/disabled)
wim leers’s picture

Title: REST Resource config entities do not seem to respect the status (enabled/disabled) » [PP-1] REST Resource config entities do not seem to respect the status (enabled/disabled)

Once #2815845: Importing (deploying) REST resource config entities should automatically do the necessary route rebuilding we'll be able to easily test this: we will be able to change EntityResourceTestBase::deprovisionResource() to no longer delete the REST Resource config entity, but instead disable it. And in provisionResource() we can then create it if it does not exist, but if it already exists, just call enable(). That's exactly what we need to test here!

wim leers’s picture

Status: Needs review » Postponed
dawehner’s picture

StatusFileSize
new3.63 KB

I just tried to write some tests, no idea whether they fail or pass.

IMHO we need to both disable and delete.

wim leers’s picture

wim leers’s picture

Title: [PP-1] REST Resource config entities do not seem to respect the status (enabled/disabled) » REST Resource config entities do not seem to respect the status (enabled/disabled)
Status: Postponed » Needs review
wim leers’s picture

StatusFileSize
new3.79 KB

Rebased @dawehner's proposal of #10. (#10 no longer applies.)

The last submitted patch, 10: 2844046-10.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 13: 2844046-13.patch, failed testing.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new5.59 KB
new4.75 KB
  1. +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
    @@ -131,17 +131,25 @@ public function setUp() {
    +    $resource_config->set('config', [
    

    Should be 'configuration'.

  2. +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
    @@ -131,17 +131,25 @@ public function setUp() {
    +    $this->resourceConfigStorage->save($resource_config);
    

    Should be $resource_config->save().

Those explain the key failures.

Also, I think it doesn't make sense we allow modifying all those configuration details when we just need to be able to disable a resource. It'd be more logical to add a method to be able to retrieve the REST Resource Config entity then, so then you can call disable(), enable() and delete() on it. The complication is that you must always call refreshTestStateAfterRestConfigChange() after any of those, to keep the test environment in sync. But that's okay.

So, in this patch, I am:

  1. restoring ResourceTestBase::provisionResource() and provisionEntityResource() to their original signatures
  2. then removing the $resource_type parameter from ResourceTestBase::provisionResource(), and instead moving that to static $resourceConfigId
  3. this then allows us to do $this->resourceConfigStorage->load(static::$resourceConfigId)->disable()->save(); to disable, $this->resourceConfigStorage->load(static::$resourceConfigId)->enable()->save(); to re-enable and $this->resourceConfigStorage->load(static::$resourceConfigId)->delete(); to save
  4. hence I can now also delete this->deprovisionResource()
wim leers’s picture

StatusFileSize
new2.31 KB
new4.56 KB
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -353,6 +347,22 @@ public function testGet() {
     $this->provisionEntityResource();
+    $this->resourceConfigStorage->load(static::$resourceConfigId)->disable()->save();
+    $this->refreshTestStateAfterRestConfigChange();
+
+
+    // The resource is still provisioned, but disabled.
+    $response = $this->request('GET', $url, $request_options);
+    if ($has_canonical_url) {
+      $this->assertResourceErrorResponse(403, '', $response);
+    }
+    else {
+      $this->assertResourceErrorResponse(404, 'No route found for "GET ' . str_replace($this->baseUrl, '', $this->getUrl()->setAbsolute()->toString()) . '"', $response);
+    }
+
+
+    $this->resourceConfigStorage->load(static::$resourceConfigId)->enable()->save();
+    $this->refreshTestStateAfterRestConfigChange();
     // Simulate the developer again forgetting the ?_format query string.
     $url->setOption('query', []);

This is what @dawehner proposed in #10. It's well-intended, but it's not testing what we want to test.

We want to first verify that the provisioned resource has a 200 response. THEN we want to disable it and verify that we get a 404. Then if we re-enable again, we want a 200. And then if we delete it, we again want a 404.

It's important that we verify those 200 responses in between, because only then we're actually testing that routes are working (200 response) vs not working (404 response) at the expected times!

So, keeping this exact same test code, but moving it after our first successfully verified 200 response!

wim leers’s picture

Issue tags: -Needs tests
StatusFileSize
new917 bytes
new4.74 KB

We now have:

  1. 200
  2. disable
  3. 404
  4. enable
  5. delete
  6. 404

We still need to add an assertion of a 200 response between "enable" and "delete". This does that. Test coverage is now complete.

wim leers’s picture

StatusFileSize
new1.24 KB
new5.92 KB

Now the test coverage (and its failing tests) make it clear that the bug reported in the IS is not yet fixed.

So, time to fix that. This interdiff is identical to my patch in #6.

wim leers’s picture

StatusFileSize
new1.63 KB
new6.05 KB

Finally, there were some small flaws in the assertions that check the behavior after disabling. We should just copy/paste the assertions we already had for a deleted resource.

Also make the comments consistent.

This should be green :) And hopefully RTBC'able! :)

wim leers’s picture

Title: REST Resource config entities do not seem to respect the status (enabled/disabled) » REST Resource config entities do not respect the status (enabled/disabled)

Clearer.

The last submitted patch, 16: 2844046-16.patch, failed testing.

The last submitted patch, 17: 2844046-17.patch, failed testing.

The last submitted patch, 18: 2844046-18.patch, failed testing.

The last submitted patch, 19: 2844046-19.patch, failed testing.

tedbow’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/rest/src/Routing/ResourceRoutes.php
    @@ -59,13 +59,14 @@ public function __construct(ResourcePluginManager $manager, EntityTypeManagerInt
    -      $resource_routes = $this->getRoutesForResourceConfig($resource_config);
    -      $collection->addCollection($resource_routes);
    +      if ($resource_config->status()) {
    +        $resource_routes = $this->getRoutesForResourceConfig($resource_config);
    +        $collection->addCollection($resource_routes);
    +      }
    

    Very clear that we aren't adding routes for disabled resources!

  2. +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
    @@ -137,22 +137,13 @@
    -  protected function deprovisionEntityResource() {
    -    $this->resourceConfigStorage->load('entity.' . static::$entityTypeId)
    -      ->delete();
    -    $this->refreshTestStateAfterRestConfigChange();
    

    Removal of deprovisionEntityResource makes things simpler!

  3. +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
    @@ -481,10 +475,34 @@ public function testGet() {
    +    // DX: upon disabling a resource, immediate 404 if no route, 406 otherwise.
    +    $response = $this->request('GET', $url, $request_options);
    +    if (!$has_canonical_url) {
    +      $this->assertSame(404, $response->getStatusCode());
    +    }
    +    else {
    +      $this->assert406Response($response);
    +    }
    

    We have this code block now twice.
    Could we refactor to
    protected function assertRouteNotAvailable($url, $request_options)
    No need to pass $has_canonical_url has that can be figured out.

Other than the refactor suggestion I think this could be RTBC.

Tests just passed yay!

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new2.4 KB
new6.68 KB

Yay! :) Done.

Didn't go with assertRouteNotAvailable but with assertResourceNotAvailable, because it's about the resource, not the route (a single resource has many routes).

tedbow’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -1154,4 +1142,24 @@ protected function assert406Response(ResponseInterface $response) {
+  }
+
+
 }

Extra line that can be removed on commit.

Great! RTBC!

wim leers’s picture

StatusFileSize
new786 bytes
new6.7 KB

Forgot a bit.

wim leers’s picture

StatusFileSize
new614 bytes
new6.7 KB

And fixing the nit in #28.

The last submitted patch, 27: 2844046-27.patch, failed testing.

tedbow’s picture

@Wim Leers sorry I missed the missing arguments in #27. I guess that is why we have tests ;)

Checked the test failures and were caused by this. Tests passed in #29 after fix. and #30

Still RTBC!

alexpott’s picture

+++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
@@ -56,6 +56,15 @@
   /**
+   * The REST Resource Config entity ID under test (i.e. a resource type).
+   *
+   * The REST Resource plugin ID can be calculated from this.
+   *
+   * @var string
+   */
+  protected static $resourceConfigId = NULL;

@@ -123,24 +132,23 @@ public function setUp() {
-  protected function provisionResource($resource_type, $formats = [], $authentication = []) {
+  protected function provisionResource($formats = [], $authentication = []) {

I've stared at this for a bit and thought is this change really necessary. Cause at the moment this fix is eligible for 8.3.1 cause 8.3.x is frozen till the release of 8.3.0. This means there will be a time when the cascade of classes involved in entity resource REST testing are out of sync between 8.3.x and 8.4.x if I commit this now. Which might prove costly for writing patches during this time.

I'm not sure what to do here. If @Wim Leers or @tedbow feel that they want to get this in to 8.4.x now and are happy to live with the out-of-syncness I'm happy to go along with that. Since they are working on most of the issues that touch this area.

wim leers’s picture

That shouldn't hurt us much. We're rarely touching the "provision resource" code. This is likely the last time.

If this can still land in 8.3.1, that means that this problem is also very temporary. If this could never land in 8.3, this wouldn't even be that big of a problem.

alexpott’s picture

Version: 8.4.x-dev » 8.3.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed b739f56 and pushed to 8.4.x. Thanks!

Thanks @Wim Leers for addressing #33.

  • alexpott committed 6d2c634 on 8.4.x
    Issue #2844046 by Wim Leers, dawehner, tedbow: REST Resource config...
wim leers’s picture

Assigned: Unassigned » wim leers

Porting to 8.3.

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Patch (to be ported) » Reviewed & tested by the community
StatusFileSize
new6.7 KB

Well, actually a simple git cherry-pick 6d2c634ea1baf081c2092b757ae54ccf908c2a54 seems to work fine :)

wim leers’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

I just realized alexpott probably only set it to "Patch (to be ported)" so that he can cherry-pick it into 8.3.x once 8.3.0 is out. Oops :)

  • alexpott committed 8b622f8 on 8.3.x
    Issue #2844046 by Wim Leers, dawehner, tedbow: REST Resource config...
alexpott’s picture

Status: Patch (to be ported) » Fixed

@catch, @cilefen and @xjm and I just decided that patch rules will apply to the RC up until RC2 so backporting this to 8.3.x

Committed 8b622f8 and pushed to 8.3.x. Thanks!

wim leers’s picture

Even better, thanks!

Status: Fixed » Closed (fixed)

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