diff --git a/Classes/Controller/EditorController.php b/Classes/Controller/EditorController.php index fa854d53..e0530c47 100644 --- a/Classes/Controller/EditorController.php +++ b/Classes/Controller/EditorController.php @@ -18,6 +18,8 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Backend\Form\Exception\AccessDeniedEditInternalsException; +use TYPO3\CMS\Backend\Form\Exception\AccessDeniedTableModifyException; use TYPO3\CMS\Backend\Form\FormDataCompiler; use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord; use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; @@ -88,51 +90,56 @@ public function getConfigurationAction(ServerRequestInterface $request, Response 'disabledWizards' => true ]; - $this->formData = $formDataCompiler->compile($formDataCompilerInput); - - $formDataFieldName = $this->formData['processedTca']['columns'][$fieldName] ?? null; - $this->rteConfiguration = (isset($formDataFieldName['config']['richtextConfiguration'])) - ? $formDataFieldName['config']['richtextConfiguration']['editor'] : []; - $hasCkeditorConfiguration = !empty($this->rteConfiguration); - - $editorConfiguration = $this->prepareConfigurationForEditor(); - - $externalPlugins = ''; - foreach ($this->getExtraPlugins() as $pluginName => $config) { - $editorConfiguration[$pluginName] = $config['config']; - $editorConfiguration['extraPlugins'] = (isset($editorConfiguration['extraPlugins'])) - ? $editorConfiguration['extraPlugins'] : ''; - if ($editorConfiguration['extraPlugins'] !== null && $editorConfiguration['extraPlugins'] !== '') { - $editorConfiguration['extraPlugins'] .= ','; + try { + $this->formData = $formDataCompiler->compile($formDataCompilerInput); + + $formDataFieldName = $this->formData['processedTca']['columns'][$fieldName] ?? null; + $this->rteConfiguration = (isset($formDataFieldName['config']['richtextConfiguration'])) + ? $formDataFieldName['config']['richtextConfiguration']['editor'] : []; + $hasCkeditorConfiguration = !empty($this->rteConfiguration); + + $editorConfiguration = $this->prepareConfigurationForEditor(); + + $externalPlugins = ''; + foreach ($this->getExtraPlugins() as $pluginName => $config) { + $editorConfiguration[$pluginName] = $config['config']; + $editorConfiguration['extraPlugins'] = (isset($editorConfiguration['extraPlugins'])) + ? $editorConfiguration['extraPlugins'] : ''; + if ($editorConfiguration['extraPlugins'] !== null && $editorConfiguration['extraPlugins'] !== '') { + $editorConfiguration['extraPlugins'] .= ','; + } + $editorConfiguration['extraPlugins'] .= $pluginName; + + $externalPlugins .= 'CKEDITOR.plugins.addExternal('; + $externalPlugins .= GeneralUtility::quoteJSvalue($pluginName) . ','; + $externalPlugins .= GeneralUtility::quoteJSvalue($config['resource']) . ','; + $externalPlugins .= '\'\');'; } - $editorConfiguration['extraPlugins'] .= $pluginName; - - $externalPlugins .= 'CKEDITOR.plugins.addExternal('; - $externalPlugins .= GeneralUtility::quoteJSvalue($pluginName) . ','; - $externalPlugins .= GeneralUtility::quoteJSvalue($config['resource']) . ','; - $externalPlugins .= '\'\');'; - } - $configuration = [ - 'configuration' => $editorConfiguration, - 'hasCkeditorConfiguration' => $hasCkeditorConfiguration, - 'externalPlugins' => $externalPlugins, - ]; + $configuration = [ + 'configuration' => $editorConfiguration, + 'hasCkeditorConfiguration' => $hasCkeditorConfiguration, + 'externalPlugins' => $externalPlugins, + ]; + + $configurationKey = ''; + foreach ($configurations as $existingConfigurationKey => $existingConfiguration) { + if (json_encode($existingConfiguration) === json_encode($configuration)) { + $configurationKey = $existingConfigurationKey; + break; + } + } - $configurationKey = ''; - foreach ($configurations as $existingConfigurationKey => $existingConfiguration) { - if (json_encode($existingConfiguration) === json_encode($configuration)) { - $configurationKey = $existingConfigurationKey; - break; + if ($configurationKey === '') { + $configurationKey = count($configurations); + $configurations[$configurationKey] = $configuration; } - } - if ($configurationKey === '') { - $configurationKey = count($configurations); - $configurations[$configurationKey] = $configuration; + $elements[$uid . '_' . $table . '_' . $fieldName] = $configurationKey; + } catch (AccessDeniedEditInternalsException|AccessDeniedTableModifyException $exception) { + // The editor does not have access to the table of this specific field or to the field itself so, + // instead of displaying a toast with an error, we simply intercept the exception and go on. } - - $elements[$uid . '_' . $table . '_' . $fieldName] = $configurationKey; } } diff --git a/Classes/Service/AccessService.php b/Classes/Service/AccessService.php index 7a747a49..1dc0b474 100644 --- a/Classes/Service/AccessService.php +++ b/Classes/Service/AccessService.php @@ -49,6 +49,33 @@ public static function isEnabled(): bool return $isEnabled; } + /** + * Has the user edit rights for the content of the page? + * + * @param array $page + * @param int $languageId + * @return bool + */ + public static function isPageEditAllowed(array $page, int $languageId = 0): bool + { + if ($GLOBALS['TCA']['pages']['ctrl']['readOnly'] ?? false) { + return false; + } + $backendUser = $GLOBALS['BE_USER']; + if ($backendUser->isAdmin()) { + return true; + } + if ($GLOBALS['TCA']['pages']['ctrl']['adminOnly'] ?? false) { + return false; + } + + return $page !== [] + && !($page[$GLOBALS['TCA']['pages']['ctrl']['editlock'] ?? null] ?? false) + && $backendUser->doesUserHaveAccess($page, Permission::PAGE_EDIT) + && $backendUser->checkLanguageAccess($languageId) + && $backendUser->check('tables_modify', 'pages'); + } + /** * Has the user edit rights for the content of the page? * diff --git a/Classes/Service/ContentEditableWrapperService.php b/Classes/Service/ContentEditableWrapperService.php index 64529cfe..5c0b269b 100644 --- a/Classes/Service/ContentEditableWrapperService.php +++ b/Classes/Service/ContentEditableWrapperService.php @@ -194,6 +194,11 @@ public function wrapContent(string $table, int $uid, array $dataArr, string $con return $content; } + // Is BE user allowed to edit CE of this table? + if (!$this->getBackendUser()->check('tables_modify', $table)) { + return $content; + } + $hiddenElementClassName = $this->getContentElementClass($table, $uid); $elementIsHidden = $hiddenElementClassName !== ''; diff --git a/Classes/ViewHelpers/ContentEditableViewHelper.php b/Classes/ViewHelpers/ContentEditableViewHelper.php index f9d89e05..481ba677 100644 --- a/Classes/ViewHelpers/ContentEditableViewHelper.php +++ b/Classes/ViewHelpers/ContentEditableViewHelper.php @@ -19,6 +19,7 @@ use Exception; use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\FrontendEditing\Service\AccessService; @@ -115,7 +116,10 @@ public function render(): string $isPageContentEditAllowed = true; } - if (!AccessService::isEnabled() || !$isPageContentEditAllowed) { + $backendUser = $this->getBackendUser(); + $isTableEditAllowed = $backendUser->check('tables_modify', $this->arguments['table']); + + if (!AccessService::isEnabled() || !$isPageContentEditAllowed || !$isTableEditAllowed) { $content = $content ?: ''; return $this->renderAsTag($content); } @@ -175,4 +179,12 @@ protected function renderAsTag(?string $content): string return $content; } + + /** + * @return BackendUserAuthentication + */ + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } }