access_policy-1.0.x-dev/src/AccessPolicyPermissions.php
src/AccessPolicyPermissions.php
<?php namespace Drupal\access_policy; use Drupal\access_policy\Entity\AccessPolicy; use Drupal\access_policy\Entity\AccessPolicyInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines dynamic permissions. * * This generates permissions based on the access policy operation plugins. * * @ingroup access_policy */ class AccessPolicyPermissions implements ContainerInjectionInterface { use StringTranslationTrait; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The operation plugin manager. * * @var \Drupal\access_policy\AccessPolicyOperationPluginManager */ protected $operationPluginManager; /** * AccessPolicyPermissions constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\access_policy\AccessPolicyOperationPluginManager $operation_plugin_manager * The operation plugin manager. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, AccessPolicyOperationPluginManager $operation_plugin_manager) { $this->entityTypeManager = $entity_type_manager; $this->operationPluginManager = $operation_plugin_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), $container->get('plugin.manager.access_policy_operation') ); } /** * Returns an array of Access Policy permissions. * * @return array * The permissions. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ public function entityPermissions() { $perms = []; // Generate permissions for all Access Policies based on their type. /** @var \Drupal\access_policy\Entity\AccessPolicyInterface $access_policy */ foreach ($this->entityTypeManager->getStorage('access_policy')->loadMultiple() as $access_policy) { $perms = array_merge($perms, $this->createAccessPolicyPermissions($access_policy)); } return $perms; } /** * Get the permission strings for a particular access policy. * * @param \Drupal\access_policy\Entity\AccessPolicyInterface $access_policy * The access policy. * * @return array * The access policy permissions. */ public function getAccessPolicyPermissions(AccessPolicyInterface $access_policy) { $permissions = $this->createAccessPolicyPermissions($access_policy); if (!empty($permissions)) { return array_keys($permissions); } return []; } /** * Get the permissions for a specific access policy. * * @param \Drupal\access_policy\Entity\AccessPolicyInterface $access_policy * The access policy. * * @return array[] * Array of permissions. */ protected function createAccessPolicyPermissions(AccessPolicyInterface $access_policy) { $perms = []; $entity_type = $this->entityTypeManager->getDefinition($access_policy->getTargetEntityTypeId()); $entity_type_label = strtolower($entity_type->getLabel()->getUntranslatedString()); $operations_handler = $access_policy->getOperationsHandler(); if ($operations_handler->supportsPermissions()) { $operations = $operations_handler->getPermissionOperations(); foreach ($operations as $op) { $plugin = $this->operationPluginManager->createInstance($op); if ($plugin) { $definition = $plugin->getPluginDefinition(); if ($definition['class']::isApplicable($entity_type)) { $entity_type_permissions = $plugin->createPermission($access_policy); if ($entity_type_permissions) { $perms = array_merge($perms, $entity_type_permissions); } } } } } // If the policy supports rules then create the bypass permission and user // field value permission. if ($operations_handler->supportsAccessRules()) { $perms = array_merge($perms, self::getBypassAccessRulesPermission($access_policy, $entity_type_label)); $perms = array_merge($perms, $this->getEditUserFieldValuesPermission($access_policy, $entity_type_label)); } // Assigning an access policy is controlled by permissions and selection // rules. Therefore, it can't be configured like other operations. $perms = array_merge($perms, self::getAssignPermission($access_policy, $entity_type_label)); // For each permission also append the dependency on the access policy. foreach ($perms as &$permission) { $permission['dependencies'] = $this->getAccessPolicyDependency($access_policy); } return $perms; } /** * Retrieves the assign permission for a given entity type. * * @param \Drupal\access_policy\Entity\AccessPolicy $access_policy * The Access Policy. * @param string $entity_type_label * The entity type label. * * @return array * The listing permission. */ private static function getAssignPermission(AccessPolicy $access_policy, $entity_type_label) { return [ 'assign ' . $access_policy->id() . ' access policy' => [ 'title' => t("@access_policy: Assign to any @entity_type", [ '@access_policy' => $access_policy->label(), '@entity_type' => $entity_type_label, ]), ], ]; } /** * Retrieves the permission dependency config. * * This is primarily so that we can filter by permission on the manage * permissions tab. * * @param \Drupal\access_policy\Entity\AccessPolicy $access_policy * The Access Policy. * * @return array * The access policy dependency config. */ private function getAccessPolicyDependency(AccessPolicy $access_policy) { return [ $access_policy->getConfigDependencyKey() => [$access_policy->getConfigDependencyName()], ]; } /** * Retrieves the assign permission for a given entity type. * * @param \Drupal\access_policy\Entity\AccessPolicy $access_policy * The Access Policy. * @param string $entity_type_label * The entity type label. * * @return array * The listing permission. */ private static function getBypassAccessRulesPermission(AccessPolicy $access_policy, $entity_type_label) { return [ 'bypass ' . $access_policy->id() . ' access rules' => [ 'title' => t("@access_policy: Bypass @entity_type access rule restrictions", [ '@access_policy' => $access_policy->label(), '@entity_type' => $entity_type_label, ]), 'description' => t('View, edit and delete @entity_type regardless of access rule restrictions. Note that the user still needs permission for view/edit/delete any @entity_type assigned this access policy.', ['@entity_type' => $entity_type_label]), ], ]; } /** * Retrieves the edit user information permission for an access policy. * * @param \Drupal\access_policy\Entity\AccessPolicy $access_policy * The Access Policy. * @param string $entity_type_label * The entity type label. * * @return array * The permission. */ private function getEditUserFieldValuesPermission(AccessPolicy $access_policy, $entity_type_label) { return [ 'edit ' . $access_policy->id() . ' user information' => [ 'title' => $this->t("@access_policy: Edit user information associated with this access policy.", [ '@access_policy' => $access_policy->label(), ]), 'description' => $this->t('Grant access to any user fields being observed by access rules in this policy.'), 'restrict access' => TRUE, ], ]; } }