0

I created a custom module to create a /store/ID/tasks page

https://www.drupal.org/project/commerce

How to limit access to this page to the store owner ?

If the current user is owner of store ID 76, he can access this page :

/store/76/tasks

But if he goes to another store, he must have denied access :

/store/89/tasks

https://git.drupalcode.org/sandbox/zenimagine-3076032

task_notify/task_notify.routing.yml

task_notify.store_page.tasks:
  path: '/store/{store}/tasks'
  defaults:
    _controller: '\Drupal\task_notify\Controller\TaskNotifyStoreController::Tasks'
    _title: 'Liste des tâches'
  requirements:
    _custom_access: '\Drupal\task_notify\Controller\TaskNotifyStoreController::taskAccess'

task_notify/src/Controller/TaskNotifyStoreController.php

<?php

namespace Drupal\task_notify\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\commerce_store\Entity\StoreInterface;

class TaskNotifyStoreController extends ControllerBase {

  public function Tasks() {
    return [
      '#theme' => 'task_notify_store_template',
    ];
  }

  public function taskAccess(StoreInterface $store, AccountInterface $account = NULL, $return_as_object = FALSE) {
    $result = $store->access('edit', $account, TRUE);
    return $return_as_object ? $result : $result->isAllowed();
  }

}

This page should be accessible only if the current user can edit the store (the site administrator and the store owner).

Access in the module code must have the same conditions as in this view :

https://i.stack.imgur.com/ZfUMo.png

I was inspired by the two files below :

https://git.drupalcode.org/project/commerce_marketplace/-/blob/8.x-1.x/src/Plugin/Action/MarketplaceIncreaseStoreLimitByOne.php

https://git.drupalcode.org/project/commerce_marketplace/-/blob/8.x-1.x/src/Plugin/Action/MarketplaceMarkAsDefault.php

1 Answers1

0

In this case, we can tell Drupal that {store} is an entity and it will load the object. So we don't have to do that in the Controller function.

So your routing file can include "parameters" settings to do that.

task_notify.store_page.tasks:
  path: '/store/{store}/tasks'
  defaults:
    _controller: '\Drupal\task_notify\Controller\TaskNotifyStoreController::Tasks'
    _title: 'Liste des tâches'
  requirements:
    _custom_access: '\Drupal\task_notify\Controller\TaskNotifyStoreController::taskAccess'
  options:
    parameters:
      store:
        type: entity:commerce_store

Now your controller function has access to that object.

  public function Tasks(StoreInterface $store) { ...

In my experience, that is NOT true of the access() method (at least when using a type-hinted parameter as we are doing here). You get a string, so you'll have to load the store manually.

  public function taskAccess(string $store, AccountInterface $account) {
    $store = \Drupal\commerce_store\Entity\Store::load($store);
    // Check store owner against current user.
    if ($store->access('edit', $account)) {
      return AccessResult::allowed();
    }
    else {
      return AccessResult::forbidden();
    }

Also we need to define $account in the routing file now, as we are using type-hinted parameters (I think). So add that to the options:.

task_notify.store_page.tasks:
  path: '/store/{store}/tasks'
  defaults:
    _controller: '\Drupal\task_notify\Controller\TaskNotifyStoreController::Tasks'
    _title: 'Liste des tâches'
  requirements:
    _custom_access: '\Drupal\task_notify\Controller\TaskNotifyStoreController::taskAccess'
  options:
    parameters:
      store:
        type: entity:commerce_store
      account: \Drupal\Core\Session\AccountProxy

$account is one of a few special parameters that we can type-hint this way. More info: https://www.drupal.org/docs/8/api/routing-system/access-checking-on-routes/advanced-route-access-checking

Brian Wagner
  • 817
  • 1
  • 6
  • 11
  • Thank you for your reply. But I want to do the same condition as the screenshot. I want if the current user can edit the store, they go to the task page. Like this, the owner of the store, administrators and moderators with permission to administer, can view this page. –  Jul 29 '20 at 13:27
  • Mathieu, I modifed the taskAccess() method to check the user's access to the store, not limited to store owner. – Brian Wagner Jul 29 '20 at 14:03