You are here

public function OgAccess::userAccess in Organic groups 8

Determines whether a user has a group permission in a given group.

The following conditions will result in a positive result:

  • The user is the global super user (UID 1).
  • The user has the global permission to administer all organic groups.
  • The user is the owner of the group, and OG has been configured to allow full access to the group owner.
  • The user has the role of administrator in the group.
  • The user has a role in the group that specifically grants the permission.
  • The user is not a member of the group, and the permission has been granted to non-members.
  • The access result can be altered (granted or denied) by implementing hook_og_user_access().

For access to be granted, at least one of the above checks should grant access, and none of the checks should deny access. A neutral result is returned only if all checks are neutral.

All access checks in OG should go through this function. This way we guarantee consistent behavior, and ensure that the superuser and group administrators can perform all actions.

Parameters

\Drupal\Core\Entity\EntityInterface $group: The group entity.

string $permission: The name of the OG permission being checked. This includes both group level permissions such as 'subscribe without approval' and group content entity operation permissions such as 'edit own article content'.

\Drupal\Core\Session\AccountInterface|null $user: (optional) The user to check. Defaults to the current user.

bool $skip_alter: (optional) If TRUE then user access will not be sent to other modules using drupal_alter(). This can be used by modules implementing hook_og_user_access_alter() that still want to use og_user_access(), but without causing a recursion. Defaults to FALSE.

Return value

\Drupal\Core\Access\AccessResultInterface An access result object.

Overrides OgAccessInterface::userAccess

2 calls to OgAccess::userAccess()
OgAccess::userAccessEntity in src/OgAccess.php
Determines whether a user has a group permission in a given entity.
OgAccess::userAccessEntityOperation in src/OgAccess.php
Checks whether a user can perform an operation on a given entity.

File

src/OgAccess.php, line 132

Class

OgAccess
The service that determines if users have access to groups and group content.

Namespace

Drupal\og

Code

public function userAccess(EntityInterface $group, string $permission, ?AccountInterface $user = NULL, bool $skip_alter = FALSE) : AccessResultInterface {
  $group_type_id = $group
    ->getEntityTypeId();
  $bundle = $group
    ->bundle();

  // As Og::isGroup depends on this config, we retrieve it here and set it as
  // the minimal caching data.
  $config = $this->configFactory
    ->get('og.settings');
  $cacheable_metadata = (new CacheableMetadata())
    ->addCacheableDependency($config);
  if (!$this->groupTypeManager
    ->isGroup($group_type_id, $bundle)) {

    // Not a group.
    return AccessResult::neutral()
      ->addCacheableDependency($cacheable_metadata);
  }
  if (!isset($user)) {
    $user = $this->accountProxy
      ->getAccount();
  }

  // From this point on, every result also depends on the user so check
  // whether it is the current. See https://www.drupal.org/node/2628870
  // @todo This doesn't really vary by user but by the user's roles inside of
  //   the group. We should create a cache context for OgRole entities.
  // @see https://github.com/amitaibu/og/issues/219
  if ($user
    ->id() == $this->accountProxy
    ->id()) {
    $cacheable_metadata
      ->addCacheContexts([
      'user',
    ]);
  }

  // User ID 1 has all privileges.
  if ($user
    ->id() == 1) {
    return AccessResult::allowed()
      ->addCacheableDependency($cacheable_metadata);
  }

  // Check if the user has a global permission to administer all groups. This
  // gives full access.
  $user_access = AccessResult::allowedIfHasPermission($user, 'administer organic groups');
  if ($user_access
    ->isAllowed()) {
    return $user_access
      ->addCacheableDependency($cacheable_metadata);
  }
  if ($config
    ->get('group_manager_full_access') && $user
    ->isAuthenticated() && $group instanceof EntityOwnerInterface) {
    $cacheable_metadata
      ->addCacheableDependency($group);
    if ($group
      ->getOwnerId() == $user
      ->id()) {
      return AccessResult::allowed()
        ->addCacheableDependency($cacheable_metadata);
    }
  }
  $permissions = [];
  $user_is_group_admin = FALSE;
  if ($membership = $this->membershipManager
    ->getMembership($group, $user
    ->id())) {
    foreach ($membership
      ->getRoles() as $role) {

      // Check for the is_admin flag.
      if ($role
        ->isAdmin()) {
        $user_is_group_admin = TRUE;
        break;
      }
      $permissions = array_merge($permissions, $role
        ->getPermissions());
    }
  }
  elseif (!$this->membershipManager
    ->isMember($group, $user
    ->id(), [
    OgMembershipInterface::STATE_BLOCKED,
  ])) {

    // User is a non-member or has a pending membership.

    /** @var \Drupal\og\Entity\OgRole $role */
    $role = OgRole::loadByGroupAndName($group, OgRoleInterface::ANONYMOUS);
    $permissions = $role
      ->getPermissions();
  }
  $permissions = array_unique($permissions);
  if (!$skip_alter && !in_array($permission, $permissions)) {

    // Let modules alter the permissions.
    $context = [
      'permission' => $permission,
      'group' => $group,
      'user' => $user,
    ];
    $this->moduleHandler
      ->alter('og_user_access', $permissions, $cacheable_metadata, $context);
  }

  // Check if the user is a group admin and who has access to all the group
  // permissions.
  // @todo It should be possible for modules to alter the permissions even if
  //   the user is a group admin, UID 1 or has 'administer group' permission.
  if ($user_is_group_admin || in_array($permission, $permissions)) {

    // User is a group admin, and we do not ignore this special permission
    // that grants access to all the group permissions.
    return AccessResult::allowed()
      ->addCacheableDependency($cacheable_metadata);
  }
  return AccessResult::neutral()
    ->addCacheableDependency($cacheable_metadata);
}