Security update for permissions_by_term
[yaffs-website] / web / modules / contrib / permissions_by_term / permissions_by_term.module
index 5886d9859907ce04adc3c9174b02781d6f174349..e7c8e0adfce3ed3999cf54122ae52e6f5e2d34df 100644 (file)
@@ -11,6 +11,7 @@ use Drupal\permissions_by_term\Controller\PermissionsByTermController;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\node\NodeInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\permissions_by_term\Event\PermissionsByTermDeniedEvent;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Cache\Cache;
@@ -27,7 +28,7 @@ function permissions_by_term_help($route_name, RouteMatchInterface $arg) {
         ability to restrict setting individual terms on nodes by user
         or role. If a user is unable to set any terms for a required
         vocabulary, they are blocked from adding or editing content with
-        that vocabulary. For more information, see the online documentation for <a href=":PbT-documentation" target="_blan" title="Online Documentation">Permissions by Term</a>.', [':PbT-documentation' => 'https://www.drupal.org/project/permissions_by_term']) . '</p>';
+        that vocabulary. For more information, see the online documentation for <a href=":PbT-documentation" target="_blan" title="Online Documentation">Permissions by Term</a>.', [':PbT-documentation' => 'https://www.drupal.org/docs/8/modules/permissions-by-term']) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('General') . '</dt>';
@@ -56,7 +57,7 @@ function permissions_by_term_validate($form, FormState $oFormState) {
       if (!empty($terms)) {
         foreach ($terms as $term) {
           $term_id = $term['target_id'];
-          /* @var \Drupal\permissions_by_term\AccessCheck $access_check_service */
+          /* @var \Drupal\permissions_by_term\Service\AccessCheck $access_check_service */
           $access_check_service = \Drupal::service('permissions_by_term.access_check');
           if (!$access_check_service->isAccessAllowedByDatabase($term_id)) {
             $term = Term::load($term_id);
@@ -73,8 +74,8 @@ function permissions_by_term_validate($form, FormState $oFormState) {
     else {
       $term_names = $not_allowed_term_names['0'];
     }
-    $oFormState->setErrorByName('field_tags', t('You are not allowed to use specific taxonomy terms like the following: "term-names". Remove the restricted taxonomy terms from the form field and try again.',
-      ['term-names' => $term_names]));
+    $oFormState->setErrorByName('field_tags', t('You are not allowed to use taxonomy terms like: "@termNames". Remove the restricted taxonomy terms from the form field and try again.',
+      ['@termNames' => $term_names]));
   }
 }
 
@@ -83,15 +84,25 @@ function permissions_by_term_validate($form, FormState $oFormState) {
  */
 function permissions_by_term_submit($form, FormState $formState) {
   $termId = $formState->getFormObject()->getEntity()->id();
-  /* @var \Drupal\permissions_by_term\AccessStorage $access_storage */
+  /* @var \Drupal\permissions_by_term\Service\AccessStorage $access_storage */
   $access_storage = \Drupal::service('permissions_by_term.access_storage');
-  $access_storage->saveTermPermissions($formState, $termId);
-  /**
-   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
-   */
-  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
-  $nodeAccess->rebuildByTid($termId, $formState);
-  Cache::invalidateTags(['search_index:node_search']);
+  $access_update = $access_storage->saveTermPermissions($formState, $termId);
+
+  // Check if we need to rebuild node_access by term id
+  $invalidate_cache_tag = false;
+
+  // Has anything has changed?
+  foreach($access_update as $values) {
+    if(!empty($values)) {
+      $invalidate_cache_tag = true;
+      break;
+    }
+  }
+
+  // Do we need to flush the cache?
+  if($invalidate_cache_tag === true) {
+    Cache::invalidateTags(['search_index:node_search']);
+  }
 }
 
 /**
@@ -101,7 +112,7 @@ function permissions_by_term_form_taxonomy_term_form_alter(&$form, FormStateInte
   if (\Drupal::currentUser()->hasPermission('show term permission form on term page')) {
     $iTermId = $oFormState->getFormObject()->getEntity()->id();
 
-    /* @var \Drupal\permissions_by_term\AccessStorage $access_storage */
+    /* @var \Drupal\permissions_by_term\Service\AccessStorage $access_storage */
     $access_storage = \Drupal::service('permissions_by_term.access_storage');
 
     $form['access'] = [
@@ -143,7 +154,7 @@ function permissions_by_term_form_taxonomy_term_form_alter(&$form, FormStateInte
       '#weight' => -10,
     ];
 
-    $aAllowedRoles = $access_storage->getExistingRoleTermPermissionsByTid($iTermId);
+    $aAllowedRoles = $access_storage->getRoleTermPermissionsByTid($iTermId);
 
     // Firstly fetch all translated allowed role names.
     $aTranslatedAllowedRoleNames = [];
@@ -190,6 +201,41 @@ function permissions_by_term_form_taxonomy_term_form_alter(&$form, FormStateInte
  */
 function permissions_by_term_form_alter(&$form, FormStateInterface $oFormState, $form_id) {
   $form['#validate'][] = 'permissions_by_term_validate';
+  if (isNodeEditForm()) {
+    $form['permissions_by_term_info'] = [
+      '#type' => 'details',
+      '#group' => 'advanced',
+      '#title' => t('Permissions by Term'),
+      '#access' => \Drupal::currentUser()->hasPermission('show term permissions on node edit page'),
+    ];
+
+    $nid = null;
+    if (!empty($node = \Drupal::routeMatch()->getParameter('node'))) {
+      $nid = $node->id();
+    }
+
+    $viewFilePath = drupal_get_path('module', 'permissions_by_term') . '/src/View/node-details.html.twig';
+    /**
+     * @var \Drupal\permissions_by_term\Service\NodeEntityBundleInfo $nodeEntityBundleInfo
+     */
+    $nodeEntityBundleInfo = \Drupal::service('permissions_by_term.node_entity_bundle_info');
+
+    $form['permissions_by_term_info']['revision'] = array(
+      '#type' => 'item',
+      '#markup' => $nodeEntityBundleInfo->renderNodeDetails($viewFilePath, $nid),
+    );
+
+    $form['#attached']['library'][] = 'permissions_by_term/nodeForm';
+  }
+}
+
+function isNodeEditForm() {
+  $currentPath = \Drupal::service('path.current')->getPath();
+  if (is_numeric(strpos($currentPath, '/node/'))
+    && (is_numeric(strpos($currentPath, '/edit')) || is_numeric(strpos($currentPath, '/add')))) {
+    return TRUE;
+  }
+  return FALSE;
 }
 
 /**
@@ -203,16 +249,19 @@ function permissions_by_term_form_alter(&$form, FormStateInterface $oFormState,
  * through the administrative interface.
  */
 function permissions_by_term_node_access(NodeInterface $node, $op, AccountInterface $account) {
-  if (method_exists($node, 'id') && $op == 'view') {
+  if (method_exists($node, 'id') && ($op == 'view' OR $op == 'update' OR $op == 'delete')) {
     if (!$node->isPublished() && !$account->hasPermission('Bypass content access control', $account)) {
+      $eventDispatcher = \Drupal::service('event_dispatcher');
+      $accessDeniedEvent = new PermissionsByTermDeniedEvent($node->id());
+      $eventDispatcher->dispatch(PermissionsByTermDeniedEvent::NAME, $accessDeniedEvent);
+
       return AccessResult::forbidden();
     }
 
-    /* @var \Drupal\permissions_by_term\AccessCheck $access_check_service */
-    $access_check_service = \Drupal::service('permissions_by_term.access_check');
-    $oPermissionsByTermController = new PermissionsByTermController($access_check_service);
+    /* @var \Drupal\permissions_by_term\Service\AccessCheck $accessCheck */
+    $accessCheck = \Drupal::service('permissions_by_term.access_check');
 
-    return $oPermissionsByTermController->handleNode($node->id());
+    return $accessCheck->handleNode($node->id());
   }
 }
 
@@ -223,10 +272,10 @@ function permissions_by_term_node_grants(\Drupal\Core\Session\AccountInterface $
 {
     if ($op == 'view') {
       /**
-       * @var \Drupal\permissions_by_term\AccessStorage $accessStorage
+       * @var \Drupal\permissions_by_term\Service\AccessStorage $accessStorage
        */
       $accessStorage = \Drupal::service('permissions_by_term.access_storage');
-      $grants = $accessStorage->getGidsByRealm('permissions_by_term__uid_' . \Drupal::currentUser()->id());
+      $grants = $accessStorage->getGids(\Drupal::currentUser());
 
       return $grants;
     }
@@ -238,27 +287,41 @@ function permissions_by_term_node_grants(\Drupal\Core\Session\AccountInterface $
  * Permissions can be rebuild at /admin/reports/status/rebuild.
  */
 function permissions_by_term_node_access_records(\Drupal\node\NodeInterface $node) {
+  // Do not return any grants for nodes that this module doesn't manage.
+  if (!$node->isPublished()) {
+    return;
+  }
+  $has_term_access_restrictions = FALSE;
+  /* @var \Drupal\permissions_by_term\Service\AccessStorage $access_storage */
+  $access_storage = \Drupal::service('permissions_by_term.access_storage');
+  foreach ($access_storage->getTidsByNid($node->id()) as $tid) {
+    /* @var \Drupal\permissions_by_term\Service\AccessCheck $access_check_service */
+    $access_check_service = \Drupal::service('permissions_by_term.access_check');
+    if ($access_check_service->isAnyPermissionSetForTerm($tid)) {
+      $has_term_access_restrictions = TRUE;
+      break;
+    }
+  }
+  if (!$has_term_access_restrictions) {
+    return;
+  }
+
   /**
-   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   * @var \Drupal\permissions_by_term\Service\NodeAccess $nodeAccess
    */
   $nodeAccess = \Drupal::service('permissions_by_term.node_access');
-  $grantsForThisNode = $nodeAccess->createGrants($node->id());
-
-  $grants = [];
-  if (!empty($grantsForThisNode)) {
-    foreach ($grantsForThisNode as $grantObject) {
-      $grants[] = [
-        'realm' => $grantObject->realm,
-        'gid' => $grantObject->gid,
-        'grant_view' => $grantObject->grant_view,
-        'grant_update' => $grantObject->grant_update,
-        'grant_delete' => $grantObject->grant_delete,
-        'langcode' => $grantObject->langcode,
-        'fallback' => 1,
-        'nid' => $node->id(),
-      ];
-    }
-  }
+  $grantObject = $nodeAccess->createGrant($node->id(), $node->id());
+
+  $grants[] = [
+    'realm' => $grantObject->realm,
+    'gid' => $grantObject->gid,
+    'grant_view' => $grantObject->grant_view,
+    'grant_update' => $grantObject->grant_update,
+    'grant_delete' => $grantObject->grant_delete,
+    'langcode' => $grantObject->langcode,
+    'fallback' => 1,
+    'nid' => $node->id(),
+  ];
 
   return $grants;
 }
@@ -267,11 +330,6 @@ function permissions_by_term_node_access_records(\Drupal\node\NodeInterface $nod
  * Implements hook_user_insert().
  */
 function permissions_by_term_user_insert($user) {
-  /**
-   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
-   */
-  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
-  $nodeAccess->rebuildByUid($user->id(), TRUE);
   Cache::invalidateTags(['search_index:node_search']);
 }
 
@@ -279,22 +337,62 @@ function permissions_by_term_user_insert($user) {
  * Implements hook_user_update().
  */
 function permissions_by_term_user_update($user) {
-  /**
-   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
-   */
-  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
-  $nodeAccess->rebuildByUid($user->id());
-  Cache::invalidateTags(['search_index:node_search']);
+  if (\Drupal::currentUser()->hasPermission('administer permissions')) {
+    Cache::invalidateTags(['search_index:node_search']);
+  }
 }
 
 /**
  * Implements hook_node_insert().
  */
 function permissions_by_term_node_insert($node) {
-  /**
-   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
-   */
-  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
-  $nodeAccess->rebuildByNid($node->id());
   Cache::invalidateTags(['search_index:node_search']);
 }
+
+/**
+ * Implements hook_options_list_alter().
+ */
+function permissions_by_term_options_list_alter(array &$options, array $context) {
+  $fieldDefinitionSettings = $context['fieldDefinition']->getFieldStorageDefinition()->getSettings();
+  if (!empty($fieldDefinitionSettings['target_type']) && $fieldDefinitionSettings['target_type'] == 'taxonomy_term') {
+    foreach ($options as $id => $names) {
+      if ($id !== '_none') {
+        /**
+         * @var \Drupal\permissions_by_term\Service\Term $term
+         */
+        $term = \Drupal::service('permissions_by_term.term');
+
+        /**
+         * @var \Drupal\permissions_by_term\Service\AccessCheck $accessCheck
+         */
+        $accessCheck = \Drupal::service('permissions_by_term.access_check');
+
+        if (is_array($names)) {
+          foreach ($names as $name) {
+            if (!$accessCheck->isAccessAllowedByDatabase($term->getTermIdByName($name))) {
+              unset($options[$id]);
+            }
+          }
+        } elseif(is_string($names)) {
+          if (!$accessCheck->isAccessAllowedByDatabase($term->getTermIdByName($names))) {
+            unset($options[$id]);
+          }
+        }
+      }
+
+    }
+  }
+}
+
+/**
+ * Implements hook_user_cancel().
+ *
+ * Deletes all term permissions for a user when their account is cancelled.
+ */
+function permissions_by_term_user_cancel($edit, $account, $method) {
+  $deleted_user_id = $account->id();
+
+  /* @var \Drupal\permissions_by_term\Service\AccessStorage $access_storage */
+  $access_storage = \Drupal::service('permissions_by_term.access_storage');
+  $access_storage->deleteAllTermPermissionsByUserId($deleted_user_id);
+}