diff --git a/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php b/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php index 424b802a16..dfe045a41e 100644 --- a/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php +++ b/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php @@ -148,11 +148,13 @@ protected function checkAccess(ContentEntityInterface $entity, LanguageInterface $handler = $this->entityTypeManager->getHandler($entity->getEntityTypeId(), 'translation'); $translations = $entity->getTranslationLanguages(); $languages = $this->languageManager->getLanguages(); - $has_translation = isset($languages[$language->getId()]) - && $language->getId() != $entity->getUntranslated()->language()->getId() - && isset($translations[$language->getId()]); - return AccessResult::allowedIf($has_translation)->cachePerPermissions()->addCacheableDependency($entity) - ->andIf($handler->getTranslationAccess($entity, $operation)); + $langcode = $language->getId(); + $has_translation = isset($languages[$langcode]) + && $langcode != $entity->getUntranslated()->language()->getId() + && isset($translations[$langcode]); + $translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity; + return AccessResult::allowedIf($has_translation)->cachePerPermissions()->addCacheableDependency($translation) + ->andIf($handler->getTranslationAccess($translation, $operation)); } } diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index 20b0206185..11d7241d01 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -289,7 +289,14 @@ public function getTranslationAccess(EntityInterface $entity, $op) { if (!$this->currentUser->hasPermission('translate any entity') && $permission_granularity = $entity_type->getPermissionGranularity()) { $translate_permission = $this->currentUser->hasPermission($permission_granularity == 'bundle' ? "translate {$entity->bundle()} {$entity->getEntityTypeId()}" : "translate {$entity->getEntityTypeId()}"); } - return AccessResult::allowedIf($translate_permission && $this->currentUser->hasPermission("$op content translations"))->cachePerPermissions(); + $access = AccessResult::allowedIf($translate_permission && $this->currentUser->hasPermission("$op content translations"))->cachePerPermissions(); + if ($access->isAllowed()) { + $entity_access = $entity->access('translation_' . $op, $this->currentUser, TRUE); + // Don't prevent access if no decision has been made on the entity level. + $access = $entity_access->isNeutral() ? $access : $access->andIf($entity_access); + $access->addCacheableDependency($entity); + } + return $access; } /** diff --git a/core/modules/content_translation/src/Controller/ContentTranslationController.php b/core/modules/content_translation/src/Controller/ContentTranslationController.php index 22c5a40982..ef48ee0cc3 100644 --- a/core/modules/content_translation/src/Controller/ContentTranslationController.php +++ b/core/modules/content_translation/src/Controller/ContentTranslationController.php @@ -199,8 +199,8 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL // If the user is allowed to edit the entity we point the edit link to // the entity form, otherwise if we are not dealing with the original // language we point the link to the translation form. - $update_access = $entity->access('update', NULL, TRUE); - $translation_access = $handler->getTranslationAccess($entity, 'update'); + $update_access = $translation->access('update', NULL, TRUE); + $translation_access = $handler->getTranslationAccess($translation, 'update'); $cacheability = $cacheability ->merge(CacheableMetadata::createFromObject($update_access)) ->merge(CacheableMetadata::createFromObject($translation_access)); @@ -237,8 +237,8 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL if ($delete_route_access->isAllowed()) { $source_name = isset($languages[$source]) ? $languages[$source]->getName() : $this->t('n/a'); - $delete_access = $entity->access('delete', NULL, TRUE); - $translation_access = $handler->getTranslationAccess($entity, 'delete'); + $delete_access = $translation->access('delete', NULL, TRUE); + $translation_access = $handler->getTranslationAccess($translation, 'delete'); $cacheability ->addCacheableDependency($delete_access) ->addCacheableDependency($translation_access); @@ -291,17 +291,20 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL $status = $this->t('Not translated'); } - if ($show_source_column) { - $rows[] = [ - $language_name, - $row_title, - $source_name, - $status, - $operations, - ]; - } - else { - $rows[] = [$language_name, $row_title, $status, $operations]; + // Show the row only if there are accessible operations. + if (!empty($operations['data']['#links'])) { + if ($show_source_column) { + $rows[] = [ + $language_name, + $row_title, + $source_name, + $status, + $operations, + ]; + } + else { + $rows[] = [$language_name, $row_title, $status, $operations]; + } } } } diff --git a/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php b/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php index b663f27071..0a7c8cc5a7 100644 --- a/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php +++ b/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php @@ -74,6 +74,9 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter case 'delete': return AccessResult::allowedIfHasPermission($account, 'administer menu') ->andIf(AccessResult::allowedIf(!$entity->isNew())->addCacheableDependency($entity)); + + default: + return parent::checkAccess($entity, $operation, $account); } }