Skip to content

Commit

Permalink
Change access validation from User Information view page
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsvinicius committed Dec 10, 2024
1 parent 2667c3c commit 6c5b246
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ display:
position: 0
display_options:
access:
type: perm
options:
perm: 'view any profile profile'
type: profile_pages_access
options: { }
cache:
type: tag
options: { }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
views.view.user_information:
expected_config: { }
update_actions:
change:
display:
default:
display_options:
access:
type: profile_pages_access
options: { }
10 changes: 10 additions & 0 deletions modules/social_features/social_profile/social_profile.install
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,13 @@ function _social_profile_hide_path_field_from_entity_form_display(string $taxono
->save();
}
}

/**
* Change access from user information view.
*/
function social_profile_update_130004(): string {
/** @var \Drupal\update_helper\Updater $updater */
$updater = \Drupal::service('update_helper.updater');
$updater->executeUpdate('social_profile', __FUNCTION__);
return $updater->logger()->output();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Drupal\social_profile\Plugin\views\access;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\profile\Entity\ProfileInterface;
use Drupal\profile\ProfileStorageInterface;
use Drupal\user\UserInterface;
use Drupal\views\Plugin\views\access\AccessPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;

/**
* Access plugin that provides access control to user information page.
*
* @ingroup views_access_plugins
*
* @ViewsAccess(
* id = "profile_pages_access",
* title = @Translation("Profile pages access"),
* help = @Translation("Access to any profile page."),
* )
*/
class SocialProfilePagesAccess extends AccessPluginBase {

/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected RouteMatchInterface $routeMatch;

/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;

/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);

$this->routeMatch = $route_match;
$this->entityTypeManager = $entity_type_manager;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_route_match'),
$container->get('entity_type.manager')
);
}

/**
* {@inheritdoc}
*/
public function access(AccountInterface $account): bool {
// Get user from uri.
$user_id = $this->routeMatch->getRawParameter('user');
$user = $this->entityTypeManager
->getStorage('user')
->load($user_id);
if (!$user instanceof UserInterface) {
return FALSE;
}

// Load profile from user and check the access for logged user.
/** @var ProfileStorageInterface $profile_storage */
$profile_storage = $this->entityTypeManager->getStorage('profile');
$profile = $profile_storage->loadByUser($user, 'profile');
if (!$profile instanceof ProfileInterface) {
return FALSE;
}

return $profile->access('view', $account);
}

/**
* {@inheritdoc}
*/
public function alterRouteDefinition(Route $route): void {
$route->setRequirement('_custom_access', '\Drupal\social_profile\Service\SocialProfileAccessService::access');
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace Drupal\social_profile\Service;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\profile\Entity\ProfileInterface;
use Drupal\profile\ProfileStorageInterface;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Provide a service for Profile Access service.
*
* @package Drupal\social_profile\Service
*/
class SocialProfileAccessService implements ContainerInjectionInterface {

/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected RouteMatchInterface $routeMatch;

/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;

/**
* SocialProfileAccessService constructor.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager) {
$this->routeMatch = $route_match;
$this->entityTypeManager = $entity_type_manager;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): self {
return new static(
$container->get('current_route_match'),
$container->get('entity_type.manager')
);
}

/**
* Validation permission for profile pages.
*
* @param \Drupal\Core\Session\AccountInterface $account
* Logged user.
*
* @return \Drupal\Core\Access\AccessResultInterface
* Return TRUE when user has access.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function access(AccountInterface $account): AccessResultInterface {
// Load the user entity.
$user_id = $this->routeMatch->getRawParameter('user');
$user = $this->entityTypeManager
->getStorage('user')
->load($user_id);
if (!$user instanceof UserInterface) {
return AccessResult::forbidden();
}

// If user is blocked, check special permission.
if ($user->isBlocked()) {
return AccessResult::allowedIfHasPermissions($account, ['view blocked user']);
}

// Load the profile to check access.
/** @var ProfileStorageInterface $profile_storage */
$profile_storage = $this->entityTypeManager->getStorage('profile');
$profile = $profile_storage->loadByUser($user, 'profile');
if (!$profile instanceof ProfileInterface) {
return AccessResult::forbidden();
}

return $profile->access('view', $account, TRUE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ protected function alterRoutes(RouteCollection $collection) {

// Routes for which needs to disable access if the user is blocked.
$disable_access_for = [
'view.user_information.user_information',
'view.events.events_overview',
'view.topics.page_profile',
];
Expand Down

0 comments on commit 6c5b246

Please sign in to comment.