diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 623991a1c192d440c9d505033bee03b77f341bae..40519720aec741111c4304c010a66a8264879fb4 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -70,11 +70,6 @@ parameters:
       count: 2
       path: modules/wse_preview/src/Form/WsePreviewLinkForm.php
 
-    -
-      message: "#^\\\\Drupal calls should be avoided in classes, use dependency injection instead$#"
-      count: 1
-      path: src/Controller/WseNodeController.php
-
     -
       message: "#^\\\\Drupal calls should be avoided in classes, use dependency injection instead$#"
       count: 1
diff --git a/src/Controller/VersionHistoryTrait.php b/src/Controller/VersionHistoryTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..59808551f98b03d32d238b4ba41ca3e1618dbeca
--- /dev/null
+++ b/src/Controller/VersionHistoryTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\wse\Controller;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Render\Element;
+
+/**
+ * Provides helper methods for the revision overview controllers.
+ */
+trait VersionHistoryTrait {
+
+  /**
+   * Adds information about each revision's workspace.
+   *
+   * @param array $build
+   *   The render array from the version history controller.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity object.
+   * @param array|null $revisions
+   *   (optional) An array of revisions that are displayed in the table.
+   */
+  protected function alterRevisionsTable(array &$build, EntityInterface $entity, ?array $revisions = NULL): void {
+    // Add a column to show the workspace in which a revision has been created.
+    $keys = Element::children($build);
+    if (!$revisions) {
+      $revisions = \Drupal::entityTypeManager()
+        ->getStorage($entity->getEntityTypeId())
+        ->loadMultipleRevisions($keys);
+    }
+
+    $field_name = $entity->getEntityType()->getRevisionMetadataKey('workspace');
+    foreach ($keys as $key) {
+      $revision = current($revisions);
+
+      $label = '';
+      if ($workspace = $revision->get($field_name)->entity) {
+        $label = $workspace->access('view label') ? $workspace->label() : $this->t('- Restricted access -');
+      }
+
+      // Insert the workspace label column.
+      if (isset($build[$key]['data'])) {
+        $build[$key]['data']['workspace'] = ['data' => $label];
+      }
+      elseif (isset($build[$key][0])) {
+        $build[$key]['workspace'] = ['data' => $label];
+      }
+      else {
+        $build[$key]['workspace'] = ['#markup' => $label];
+      }
+
+      next($revisions);
+    }
+  }
+
+}
diff --git a/src/Controller/WseDiffNodeRevisionController.php b/src/Controller/WseDiffNodeRevisionController.php
index 6d178b5084542bec579dd5a12ea839742f500673..5ffa043fec93012fa943507d4f6bc6de27f82e35 100644
--- a/src/Controller/WseDiffNodeRevisionController.php
+++ b/src/Controller/WseDiffNodeRevisionController.php
@@ -4,14 +4,9 @@ declare(strict_types=1);
 
 namespace Drupal\wse\Controller;
 
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\TypedData\TypedDataManagerInterface;
 use Drupal\diff\Controller\NodeRevisionController;
 use Drupal\node\NodeInterface;
-use Drupal\workspaces\Plugin\Validation\Constraint\EntityWorkspaceConflictConstraint;
-use Drupal\workspaces\WorkspaceManagerInterface;
 use Drupal\wse\Diff\Form\WseRevisionOverviewForm;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 /**
@@ -19,26 +14,6 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  */
 class WseDiffNodeRevisionController extends NodeRevisionController {
 
-  /**
-   * The workspace manager.
-   */
-  protected WorkspaceManagerInterface $workspaceManager;
-
-  /**
-   * The typed data manager.
-   */
-  protected TypedDataManagerInterface $typedDataManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container): self {
-    $instance = parent::create($container);
-    $instance->workspaceManager = $container->get('workspaces.manager');
-    $instance->typedDataManager = $container->get('typed_data_manager');
-    return $instance;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -46,57 +21,8 @@ class WseDiffNodeRevisionController extends NodeRevisionController {
     if (!$node->access('view')) {
       throw new AccessDeniedHttpException();
     }
-    $build = $this->formBuilder()->getForm(WseRevisionOverviewForm::class, $node);
-
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $build['node_revisions_table']['#empty'] = $this->t('There are no revisions yet in this workspace.');
-      $build['#cache']['contexts'][] = 'workspace';
-    }
-
-    // Run the workspace conflict validation constraint when the entity form is
-    // being built, so we can "disable" it early and display a message to the
-    // user, instead of allowing them to enter data that can never be saved.
-    foreach ($node->getTypedData()->getConstraints() as $constraint) {
-      if ($constraint instanceof EntityWorkspaceConflictConstraint) {
-        $violations = $this->typedDataManager->getValidator()->validate(
-          $node->getTypedData(),
-          $constraint
-        );
-        if ($violations->count()) {
-          $build['node_revisions_table']['#access'] = FALSE;
-          $build['submit']['#access'] = FALSE;
-          $build['workspace_conflict']['#markup'] = $violations->get(0)->getMessage();
-        }
-      }
-    }
-
-    return $build;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRevisionIds(EntityStorageInterface $storage, $entity_id): array {
-    $query = $storage->getQuery()
-      ->allRevisions()
-      ->condition($storage->getEntityType()->getKey('id'), $entity_id)
-      ->accessCheck(FALSE);
-
-    // When a workspace is active, filter the revisions to those created in that
-    // workspace.
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $active_workspace_id = $this->workspaceManager->getActiveWorkspace()->id();
-      $query->condition($storage->getEntityType()->getRevisionMetadataKey('workspace'), $active_workspace_id);
-    }
-    else {
-      // Otherwise show only revisions that were not created in a workspace.
-      $query->notExists($storage->getEntityType()->getRevisionMetadataKey('workspace'));
-    }
 
-    $result = $query->execute();
-    $result_array = array_keys($result);
-    sort($result_array);
-    return $result_array;
+    return $this->formBuilder()->getForm(WseRevisionOverviewForm::class, $node);
   }
 
 }
diff --git a/src/Controller/WseNodeController.php b/src/Controller/WseNodeController.php
index 26378b608a7eba82c74b81787ab296cc97b11e3c..ce2945866cd3e569643508e74565daca46e068af 100644
--- a/src/Controller/WseNodeController.php
+++ b/src/Controller/WseNodeController.php
@@ -6,30 +6,13 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\node\Controller\NodeController;
 use Drupal\node\NodeInterface;
 use Drupal\node\NodeStorageInterface;
-use Drupal\workspaces\Plugin\Validation\Constraint\EntityWorkspaceConflictConstraint;
-use Drupal\workspaces\WorkspaceManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Overrides core's NodeController.
  */
 class WseNodeController extends NodeController implements ContainerInjectionInterface {
 
-  /**
-   * The workspace manager.
-   *
-   * @var \Drupal\workspaces\WorkspaceManagerInterface
-   */
-  protected WorkspaceManagerInterface $workspaceManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    $instance = parent::create($container);
-    $instance->workspaceManager = $container->get('workspaces.manager');
-    return $instance;
-  }
+  use VersionHistoryTrait;
 
   /**
    * {@inheritdoc}
@@ -37,54 +20,13 @@ class WseNodeController extends NodeController implements ContainerInjectionInte
   public function revisionOverview(NodeInterface $node) {
     $build = parent::revisionOverview($node);
 
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $build['node_revisions_table']['#empty'] = $this->t('There are no revisions yet in this workspace.');
-      $build['#cache']['contexts'][] = 'workspace';
-    }
-
-    // Run the workspace conflict validation constraint when the entity form is
-    // being built, so we can "disable" it early and display a message to the
-    // user, instead of allowing them to enter data that can never be saved.
-    foreach ($node->getTypedData()->getConstraints() as $constraint) {
-      if ($constraint instanceof EntityWorkspaceConflictConstraint) {
-        $violations = \Drupal::typedDataManager()->getValidator()->validate(
-          $node->getTypedData(),
-          $constraint
-        );
-        if ($violations->count()) {
-          $build['node_revisions_table']['#access'] = FALSE;
-          $build['workspace_conflict']['#markup'] = $violations->get(0)->getMessage();
-        }
-      }
-    }
+    $storage = $this->entityTypeManager()->getStorage('node');
+    assert($storage instanceof NodeStorageInterface);
+    $revisions = $storage->loadMultipleRevisions($this->getRevisionIds($node, $storage));
+    $this->alterRevisionsTable($build['node_revisions_table']['#rows'], $node, $revisions);
+    $build['node_revisions_table']['#header']['workspace'] = $this->t('Workspace');
 
     return $build;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function getRevisionIds(NodeInterface $node, NodeStorageInterface $node_storage) {
-    $query = $node_storage->getQuery()
-      ->accessCheck(TRUE)
-      ->allRevisions()
-      ->condition($node->getEntityType()->getKey('id'), $node->id())
-      ->sort($node->getEntityType()->getKey('revision'), 'DESC')
-      ->pager(50);
-
-    // When a workspace is active, filter the revisions to those created in that
-    // workspace.
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $active_workspace_id = $this->workspaceManager->getActiveWorkspace()->id();
-      $query->condition($node->getEntityType()->getRevisionMetadataKey('workspace'), $active_workspace_id);
-    }
-    else {
-      // Otherwise show only revisions that were not created in a workspace.
-      $query->notExists($node->getEntityType()->getRevisionMetadataKey('workspace'));
-    }
-
-    $result = $query->execute();
-    return array_keys($result);
-  }
-
 }
diff --git a/src/Controller/WseVersionHistoryController.php b/src/Controller/WseVersionHistoryController.php
index 04472d9ba68b029413989de7beb73fc93c2138a8..0c2d79aa77d20b5622627874c8f978bc78f1209f 100644
--- a/src/Controller/WseVersionHistoryController.php
+++ b/src/Controller/WseVersionHistoryController.php
@@ -4,72 +4,13 @@ namespace Drupal\wse\Controller;
 
 use Drupal\Core\Entity\Controller\VersionHistoryController;
 use Drupal\Core\Entity\RevisionableInterface;
-use Drupal\Core\Entity\RevisionableStorageInterface;
-use Drupal\Core\Language\LanguageInterface;
-use Drupal\workspaces\WorkspaceManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Overrides core's VersionHistoryController.
  */
 class WseVersionHistoryController extends VersionHistoryController {
 
-  /**
-   * The workspace manager.
-   *
-   * @var \Drupal\workspaces\WorkspaceManagerInterface
-   */
-  protected WorkspaceManagerInterface $workspaceManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    $instance = parent::create($container);
-    $instance->workspaceManager = $container->get('workspaces.manager');
-    return $instance;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function loadRevisions(RevisionableInterface $entity) {
-    $entityType = $entity->getEntityType();
-    $translatable = $entityType->isTranslatable();
-    $entityStorage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
-    assert($entityStorage instanceof RevisionableStorageInterface);
-
-    $query = $entityStorage->getQuery()
-      ->accessCheck(FALSE)
-      ->allRevisions()
-      ->condition($entityType->getKey('id'), $entity->id())
-      ->sort($entityType->getKey('revision'), 'DESC')
-      ->pager(self::REVISIONS_PER_PAGE);
-
-    // When a workspace is active, filter the revisions to those created in that
-    // workspace.
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $active_workspace_id = $this->workspaceManager->getActiveWorkspace()->id();
-      $query->condition($entity->getEntityType()->getRevisionMetadataKey('workspace'), $active_workspace_id);
-    }
-    else {
-      // Otherwise show only revisions that were not created in a workspace.
-      $query->notExists($entity->getEntityType()->getRevisionMetadataKey('workspace'));
-    }
-
-    $result = $query->execute();
-
-    $currentLangcode = $this->languageManager
-      ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
-      ->getId();
-    foreach ($entityStorage->loadMultipleRevisions(array_keys($result)) as $revision) {
-      // Only show revisions that are affected by the language that is being
-      // displayed.
-      if (!$translatable || ($revision->hasTranslation($currentLangcode) && $revision->getTranslation($currentLangcode)->isRevisionTranslationAffected())) {
-        yield ($translatable ? $revision->getTranslation($currentLangcode) : $revision);
-      }
-    }
-  }
+  use VersionHistoryTrait;
 
   /**
    * {@inheritdoc}
@@ -77,10 +18,8 @@ class WseVersionHistoryController extends VersionHistoryController {
   protected function revisionOverview(RevisionableInterface $entity): array {
     $build = parent::revisionOverview($entity);
 
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $build['entity_revisions_table']['#empty'] = $this->t('There are no revisions yet in this workspace.');
-      $build['#cache']['contexts'][] = 'workspace';
-    }
+    $this->alterRevisionsTable($build['entity_revisions_table']['#rows'], $entity);
+    $build['entity_revisions_table']['#header']['workspace'] = $this->t('Workspace');
 
     return $build;
   }
diff --git a/src/Diff/Form/WseRevisionOverviewForm.php b/src/Diff/Form/WseRevisionOverviewForm.php
old mode 100755
new mode 100644
index f8bb7e2ae5f630927d43137669ac15654f576977..69fc25644e9e37ac54942ee132e90733d5e7dd52
--- a/src/Diff/Form/WseRevisionOverviewForm.php
+++ b/src/Diff/Form/WseRevisionOverviewForm.php
@@ -4,56 +4,32 @@ declare(strict_types=1);
 
 namespace Drupal\wse\Diff\Form;
 
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\diff\Form\RevisionOverviewForm;
-use Drupal\node\NodeInterface;
-use Drupal\workspaces\WorkspaceManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\node\NodeStorageInterface;
+use Drupal\wse\Controller\VersionHistoryTrait;
 
 /**
  * Provides a form for revision overview page.
  */
 class WseRevisionOverviewForm extends RevisionOverviewForm {
 
-  /**
-   * The workspace manager.
-   */
-  protected WorkspaceManagerInterface $workspaceManager;
+  use VersionHistoryTrait;
 
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container): self {
-    $instance = parent::create($container);
-    $instance->workspaceManager = $container->get('workspaces.manager');
-    return $instance;
-  }
+  public function buildForm(array $form, FormStateInterface $form_state, $node = NULL): array {
+    $form = parent::buildForm($form, $form_state, $node);
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function getRevisionIds(NodeInterface $node): array {
-    $query = $this->entityTypeManager->getStorage('node')->getQuery()
-      ->condition($node->getEntityType()->getKey('id'), $node->id())
-      ->pager($this->config->get('general_settings.revision_pager_limit'))
-      ->allRevisions()
-      ->sort($node->getEntityType()->getKey('revision'), 'DESC')
-      // Access to the content has already been verified. Disable query-level
-      // access checking so that revisions for unpublished content still
-      // appear.
-      ->accessCheck(FALSE);
-
-    // When a workspace is active, filter the revisions to those created in that
-    // workspace.
-    if ($this->workspaceManager->hasActiveWorkspace()) {
-      $active_workspace_id = $this->workspaceManager->getActiveWorkspace()->id();
-      $query->condition($node->getEntityType()->getRevisionMetadataKey('workspace'), $active_workspace_id);
-    }
-    else {
-      // Otherwise show only revisions that were not created in a workspace.
-      $query->notExists($node->getEntityType()->getRevisionMetadataKey('workspace'));
-    }
-
-    return \array_keys($query->execute());
+    $storage = $this->entityTypeManager->getStorage('node');
+    assert($storage instanceof NodeStorageInterface);
+    // @phpstan-ignore-next-line
+    $revisions = $storage->loadMultipleRevisions($this->getRevisionIds($node));
+    $this->alterRevisionsTable($form['node_revisions_table'], $node, $revisions);
+    $form['node_revisions_table']['#header']['workspace'] = $this->t('Workspace');
+
+    return $form;
   }
 
 }
diff --git a/wse.module b/wse.module
index d2dbfddbac395b5c895cabd330b06b84e5ac20a5..f00074919814eafb4ad77e64a77ac800cdc9db2f 100644
--- a/wse.module
+++ b/wse.module
@@ -8,6 +8,7 @@
 use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\SortArray;
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultInterface;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Entity\EntityInterface;
@@ -16,6 +17,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
 use Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler;
 use Drupal\workspaces\WorkspaceInterface;
@@ -429,3 +431,27 @@ function wse_field_info_alter(&$definitions) {
     $definitions['entity_reference']['constraints']['WseEntityReferenceSupportedNewEntities'] = [];
   }
 }
+
+/**
+ * Implements hook_entity_access().
+ */
+function wse_entity_access(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface {
+  if (
+    !\Drupal::service('workspaces.information')->isEntitySupported($entity)
+    || !in_array($operation, ['revert revision', 'revert', 'delete revision'])
+  ) {
+    return AccessResult::neutral();
+  }
+
+  /** @var \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association */
+  $workspace_association = \Drupal::service('workspaces.association');
+  $tracking_workspace_ids = $workspace_association->getEntityTrackingWorkspaceIds($entity, TRUE);
+  if ($tracking_workspace_id = reset($tracking_workspace_ids)) {
+    $active_workspace = \Drupal::service('workspaces.manager')->getActiveWorkspace();
+    if (!$active_workspace || $active_workspace->id() != $tracking_workspace_id) {
+      return AccessResult::forbidden()->addCacheContexts(['workspace']);
+    }
+  }
+
+  return AccessResult::neutral()->addCacheContexts(['workspace']);
+}