I would like to add an additional access condition to viewing user pages like user/1
.
I looked at the following guidelines, but have not succeeded in coming up with a solution.
and
https://www.drupal.org/docs/8/api/routing-system/access-checking-on-routes#access-custom
The module code I have come up with this far - I can restrict all access to user profiles fine. But I fail at my attempt to get the account id of the page being requested. Once I have the account I can load the field I need to check.
my_module.services.yml
services:
my_module.route_subscriber:
class: Drupal\my_module\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
my_module/src/Routing/RouteSubscriber.php
<?php
namespace Drupal\my_module\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
/**
* Listens to the dynamic route events.
*
* We deny access to profiles, if the user has not accepted the terms.
*
* See https://www.drupal.org/node/2187643
*
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
$path = \Drupal::service('path.current')->getPath();
$path_args = explode('/', $path);
// @todo: the right path does not seem to be accessible here - how do we get the user account id?
// Always deny access to '/user/{uid}'.
// Note that the second parameter of setRequirement() is a string.
if ($route = $collection->get('entity.user.canonical')) {
//$account = \Drupal\user\Entity\User::load($account_uid);
// This effectively denies all access to user profiles
$route->setRequirement('_access', 'FALSE');
}
}
}
EDIT: Based on the comments I tried the following, but I am not being restricted to paths like /user/1, so I guess something is still amiss:
My module structure now looks like this:
/my_module
/src
/Access
my_moduleAccessCheck.php
/Controller
my_moduleController.php
my_module.info.yml
my_module.routing.yml
my_module.services.yml
my_moduleAccessCheck.php:
<?php
namespace Drupal\my_module\Access;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;
/**
* Checks access for displaying configuration translation page.
*/
class my_moduleAccessCheck implements AccessInterface {
/**
* A custom access check.
*
* @param \Drupal\Core\Session\AccountInterface $account
* Run access checks for this account.
*
* @return \Drupal\Core\Access\AccessResultInterface
* The access result.
*/
public function access(AccountInterface $account) {
// Check permissions and combine that with any custom access checking needed. Pass forward
// parameters from the route and/or request as needed.
// $account->hasPermission('do example things') && $this->someOtherCustomCondition()
return AccessResult::forbidden();
}
}
my_moduleController.php:
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* An example controller.
*/
class my_moduleController extends ControllerBase {
public function sayHi() {
dpm('Hi');
}
}
my_module.routing.yml
my_module:
path: '/user/{uid}'
defaults:
_controller: '\Drupal\my_module\Controller\my_moduleController::sayHi'
_title: ''
requirements:
_my_module_access_check: 'TRUE'
my_module.services.yml
services:
my_module.access_checker:
class: Drupal\my_module\Access\my_moduleAccessCheck
arguments: ['@current_user']
tags:
- # Required: Mark that this service is for access checks.
name: access_check,
# Optional: Specify which routes this applies to.
applies_to: _my_module_access_check
_access
you need a dynamic access checking service. See drupal.org/docs/8/api/routing-system/access-checking-on-routes/…access(AccountInterface $account, UserInterface $user)