Commit 5ee75580 authored by Oliver Bartsch's avatar Oliver Bartsch
Browse files

[!!!][FEATURE] Add PSR-14 ModifyEditFormUserAccessEvent

This introduces a new PSR-14 event, enabling
extension authors to modify the user access
decision for creating / editing a record in
FormEngine.

This replaces the previously available hook
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck']
which is therefore now removed.

Resolves: #98304
Releases: main
Change-Id: I8d9e7c013f1d068a1f5a18966e5fb75d434887b2
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75680


Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
parent 236ce5fc
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Backend\Form\Event;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
/**
* Listeners to this Event will be able to modify the user access
* decision for using FormEngine to create or edit a record.
*/
final class ModifyEditFormUserAccessEvent
{
private bool $userHasAccess;
public function __construct(
private readonly ?AccessDeniedException $exception,
private readonly string $tableName,
private readonly string $command,
private readonly array $databaseRow,
) {
$this->userHasAccess = $this->exception === null;
}
public function allowUserAccess(): void
{
$this->userHasAccess = true;
}
public function denyUserAccess(): void
{
$this->userHasAccess = false;
}
public function doesUserHaveAccess(): bool
{
return $this->userHasAccess;
}
public function getAccessDeniedException(): ?AccessDeniedException
{
return $this->exception;
}
public function getTableName(): string
{
return $this->tableName;
}
public function getCommand(): string
{
return $this->command;
}
public function getDatabaseRow(): array
{
return $this->databaseRow;
}
}
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
......@@ -16,8 +18,8 @@
namespace TYPO3\CMS\Backend\Form\Exception;
/**
* User access to record was denied by a makeEditForm_accessCheck hook
* User access to record was denied by a ModifyRecordEditUserAccessEvent listener
*/
class AccessDeniedHookException extends AccessDeniedException
class AccessDeniedListenerException extends AccessDeniedException
{
}
......@@ -15,10 +15,12 @@
namespace TYPO3\CMS\Backend\Form\FormDataProvider;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Backend\Form\Event\ModifyEditFormUserAccessEvent;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedContentEditException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedEditInternalsException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedHookException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedListenerException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedPageEditException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedPageNewException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedRootNodeException;
......@@ -48,7 +50,7 @@ class DatabaseUserPermissionCheck implements FormDataProviderInterface
*
* @param array $result
* @return array
* @throws AccessDeniedException|\LogicException|\RuntimeException
* @throws AccessDeniedException
*/
public function addData(array $result)
{
......@@ -70,7 +72,6 @@ class DatabaseUserPermissionCheck implements FormDataProviderInterface
}
$exception = null;
$userHasAccess = false;
$userPermissionOnPage = new Permission(Permission::NOTHING);
if ($result['command'] === 'new') {
// A new record is created. Access rights of parent record are important here
......@@ -81,28 +82,21 @@ class DatabaseUserPermissionCheck implements FormDataProviderInterface
$userPermissionOnPage = new Permission($backendUser->calcPerms($result['parentPageRow']));
if ($result['tableName'] === 'pages') {
// New page is created, user needs PAGE_NEW for this
if ($userPermissionOnPage->createPagePermissionIsGranted()) {
$userHasAccess = true;
} else {
if (!$userPermissionOnPage->createPagePermissionIsGranted()) {
$exception = new AccessDeniedPageNewException(
'No page new permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['databaseRow']['uid'],
1437745640
);
}
} else {
} elseif (!$userPermissionOnPage->editContentPermissionIsGranted()) {
// A regular record is added, not a page. User needs CONTENT_EDIT permission
if ($userPermissionOnPage->editContentPermissionIsGranted()) {
$userHasAccess = true;
} else {
$exception = new AccessDeniedContentEditException(
'No content new permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['parentPageRow']['uid'],
1437745759
);
}
$exception = new AccessDeniedContentEditException(
'No content new permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['parentPageRow']['uid'],
1437745759
);
}
} elseif (BackendUtility::isRootLevelRestrictionIgnored($result['tableName'])) {
// Non admin is creating a record on root node for a table that is actively allowed
$userHasAccess = true;
$userPermissionOnPage->set(Permission::ALL);
} else {
// Non admin has no create permission on root node records
......@@ -116,93 +110,63 @@ class DatabaseUserPermissionCheck implements FormDataProviderInterface
if ($result['tableName'] === 'pages') {
// A page record is edited, check edit rights of this record directly
$userPermissionOnPage = new Permission($backendUser->calcPerms($result['defaultLanguagePageRow'] ?? $result['databaseRow']));
if ($userPermissionOnPage->editPagePermissionIsGranted() && $backendUser->check('pagetypes_select', $result['databaseRow'][$result['processedTca']['ctrl']['type']])) {
$userHasAccess = true;
} else {
if (!$userPermissionOnPage->editPagePermissionIsGranted()
|| !$backendUser->check('pagetypes_select', $result['databaseRow'][$result['processedTca']['ctrl']['type']])
) {
$exception = new AccessDeniedPageEditException(
'No page edit permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['databaseRow']['uid'],
1437679336
);
}
} else {
} elseif (isset($result['parentPageRow']) && is_array($result['parentPageRow'])) {
// A non page record is edited.
if (isset($result['parentPageRow']) && is_array($result['parentPageRow'])) {
// If there is a parent page row, check content edit right of user
$userPermissionOnPage = new Permission($backendUser->calcPerms($result['parentPageRow']));
if ($userPermissionOnPage->editContentPermissionIsGranted()) {
$userHasAccess = true;
} else {
$exception = new AccessDeniedContentEditException(
'No content edit permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['parentPageRow']['uid'],
1437679657
);
}
} elseif (BackendUtility::isRootLevelRestrictionIgnored($result['tableName'])) {
// Non admin is editing a record on root node for a table that is actively allowed
$userHasAccess = true;
$userPermissionOnPage->set(Permission::ALL);
} else {
// Non admin has no edit permission on root node records
// @todo: This probably needs further handling, see http://review.typo3.org/40835
$exception = new AccessDeniedRootNodeException(
'No content edit permission for user ' . $backendUser->user['uid'] . ' on page root node',
1437679856
// If there is a parent page row, check content edit right of user
$userPermissionOnPage = new Permission($backendUser->calcPerms($result['parentPageRow']));
if (!$userPermissionOnPage->editContentPermissionIsGranted()) {
$exception = new AccessDeniedContentEditException(
'No content edit permission for user ' . $backendUser->user['uid'] . ' on page ' . $result['parentPageRow']['uid'],
1437679657
);
}
} elseif (BackendUtility::isRootLevelRestrictionIgnored($result['tableName'])) {
// Non admin is editing a record on root node for a table that is actively allowed
$userPermissionOnPage->set(Permission::ALL);
} else {
// Non admin has no edit permission on root node records
// @todo: This probably needs further handling, see http://review.typo3.org/40835
$exception = new AccessDeniedRootNodeException(
'No content edit permission for user ' . $backendUser->user['uid'] . ' on page root node',
1437679856
);
}
if ($userHasAccess) {
// If general access is allowed, check "recordEditAccessInternals"
$userHasAccess = $backendUser->recordEditAccessInternals($result['tableName'], $result['databaseRow']);
if (!$userHasAccess) {
$exception = new AccessDeniedEditInternalsException(
$backendUser->errorMsg,
1437687404
);
}
// If general access is allowed, check "recordEditAccessInternals"
if ($exception === null
&& !$backendUser->recordEditAccessInternals($result['tableName'], $result['databaseRow'])
) {
$exception = new AccessDeniedEditInternalsException($backendUser->errorMsg, 1437687404);
}
}
if ($userHasAccess && $exception) {
// Having user access TRUE here and an exception defined must not happen,
// indicates an internal error and throws a logic exception
throw new \LogicException(
'Access was TRUE but an exception was raised as well for table ' . $result['tableName'] . ' and user ' . $backendUser->user['uid'],
1437688402
);
}
$userHasAccess = GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch(
new ModifyEditFormUserAccessEvent(
$exception,
$result['tableName'],
$result['command'],
$result['databaseRow'],
)
)->doesUserHaveAccess();
if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] ?? null)) {
// A hook may modify the $userHasAccess decision. Previous state is saved to see if a hook changed
// a previous decision from TRUE to FALSE to throw a specific exception in this case
$userHasAccessBeforeHook = $userHasAccess;
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] as $methodReference) {
$parameters = [
'table' => $result['tableName'],
'uid' => $result['databaseRow']['uid'] ?? 0,
'cmd' => $result['command'],
'hasAccess' => $userHasAccess,
];
$userHasAccess = (bool)GeneralUtility::callUserFunction($methodReference, $parameters, $this);
}
if ($userHasAccessBeforeHook && !$userHasAccess) {
$exception = new AccessDeniedHookException(
'Access to table ' . $result['tableName'] . ' for user ' . $backendUser->user['uid'] . ' was denied by a makeEditForm_accessCheck hook',
1437689705
);
}
if (!$userHasAccessBeforeHook && $userHasAccess) {
// Unset a previous exception if hook allowed access where previous checks didn't
$exception = null;
}
// Throw specific exception because a listener to the Event denied the previous positive user access decision
if ($exception === null && !$userHasAccess) {
$exception = new AccessDeniedListenerException(
'Access to table ' . $result['tableName'] . ' for user ' . $backendUser->user['uid'] . ' was denied by a ModifyRecordEditUserAccessEvent listener',
1662727149
);
}
if (!$userHasAccess && !$exception) {
// User has no access, but no according exception was defined. This is an
// internal error and throws a logic exception.
throw new \LogicException(
'Access to table ' . $result['tableName'] . ' denied, but no reason given',
1437690507
);
// Unset a previous exception because a listener to the Event allowed the previous negative user access decision
if ($exception !== null && $userHasAccess) {
$exception = null;
}
if ($exception) {
......
......@@ -20,16 +20,20 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Backend\Form\Event\ModifyEditFormUserAccessEvent;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedContentEditException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedEditInternalsException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedHookException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedListenerException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedPageEditException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedPageNewException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedRootNodeException;
use TYPO3\CMS\Backend\Form\Exception\AccessDeniedTableModifyException;
use TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseUserPermissionCheck;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Tests\Unit\Fixtures\EventDispatcher\MockEventDispatcher;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -88,6 +92,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'tt_content',
'command' => 'edit',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => [
'uid' => 42,
'pid' => 321,
......@@ -100,6 +105,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedContentEditException::class);
$this->expectExceptionCode(1437679657);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -122,6 +130,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms(['pid' => 321])->willReturn(Permission::CONTENT_EDIT);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::any())->willReturn(true);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::CONTENT_EDIT, $result['userPermissionOnPage']);
......@@ -148,6 +159,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedPageEditException::class);
$this->expectExceptionCode(1437679336);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -180,6 +194,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedPageEditException::class);
$this->expectExceptionCode(1437679336);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -209,6 +226,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms($input['databaseRow'])->willReturn(Permission::PAGE_EDIT);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::PAGE_EDIT, $result['userPermissionOnPage']);
......@@ -233,6 +253,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$GLOBALS['TCA'][$input['tableName']]['ctrl']['security']['ignoreRootLevelRestriction'] = true;
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::ALL, $result['userPermissionOnPage']);
......@@ -259,6 +282,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedRootNodeException::class);
$this->expectExceptionCode(1437679856);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -285,6 +311,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedEditInternalsException::class);
$this->expectExceptionCode(1437687404);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -297,6 +326,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'tt_content',
'command' => 'new',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => [
'uid' => 123,
'pid' => 321,
......@@ -309,6 +339,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedContentEditException::class);
$this->expectExceptionCode(1437745759);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -336,6 +369,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedPageNewException::class);
$this->expectExceptionCode(1437745640);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -361,14 +397,14 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms($input['parentPageRow'])->willReturn(Permission::ALL);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] = [
'unitTest' => static function () {
return false;
},
];
$this->expectException(AccessDeniedListenerException::class);
$this->expectExceptionCode(1662727149);
$this->expectException(AccessDeniedHookException::class);
$this->expectExceptionCode(1437689705);
$eventDispatcher = new MockEventDispatcher();
$eventDispatcher->addListener(static function (ModifyEditFormUserAccessEvent $event) {
$event->denyUserAccess();
});
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
......@@ -395,11 +431,11 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms($input['parentPageRow'])->willReturn(Permission::CONTENT_EDIT);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/alt_doc.php']['makeEditForm_accessCheck'] = [
'unitTest' => static function () {
return true;
},
];
$eventDispatcher = new MockEventDispatcher();
$eventDispatcher->addListener(static function (ModifyEditFormUserAccessEvent $event) {
$event->allowUserAccess();
});
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
......@@ -415,6 +451,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'pages',
'command' => 'new',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => [
'uid' => 123,
'pid' => 321,
......@@ -425,6 +462,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms($input['parentPageRow'])->willReturn(Permission::PAGE_NEW);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::PAGE_NEW, $result['userPermissionOnPage']);
......@@ -439,6 +479,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'tt_content',
'command' => 'new',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => [
'uid' => 123,
'pid' => 321,
......@@ -449,6 +490,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->calcPerms($input['parentPageRow'])->willReturn(Permission::CONTENT_EDIT);
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::CONTENT_EDIT, $result['userPermissionOnPage']);
......@@ -463,6 +507,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'pages',
'command' => 'new',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => null,
];
$this->beUserProphecy->isAdmin()->willReturn(false);
......@@ -470,6 +515,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->beUserProphecy->recordEditAccessInternals($input['tableName'], Argument::cetera())->willReturn(true);
$GLOBALS['TCA'][$input['tableName']]['ctrl']['security']['ignoreRootLevelRestriction'] = true;
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
$result = (new DatabaseUserPermissionCheck())->addData($input);
self::assertSame(Permission::ALL, $result['userPermissionOnPage']);
......@@ -484,6 +532,7 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
'tableName' => 'pages',
'command' => 'new',
'vanillaUid' => 123,
'databaseRow' => [],
'parentPageRow' => null,
];
......@@ -493,6 +542,9 @@ class DatabaseUserPermissionCheckTest extends UnitTestCase
$this->expectException(AccessDeniedRootNodeException::class);
$this->expectExceptionCode(1437745221);
$eventDispatcher = new MockEventDispatcher();
GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
(new DatabaseUserPermissionCheck())->addData($input);
}
}
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Core\Resource\Security;
use TYPO3\CMS\Backend\Form\Event\ModifyEditFormUserAccessEvent;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface;
......@@ -131,22 +132,19 @@ class FileMetadataPermissionsAspect implements DataHandlerCheckModifyAccessListH
/**
* Deny access to the edit form. This is not mandatory, but better to show this right away that access is denied.
*
* @param array $parameters
* @return bool
*/
public function isAllowedToShowEditForm(array $parameters)
public function isAllowedToShowEditForm(ModifyEditFormUserAccessEvent $event): void
{
$table = $parameters['table'];
$uid = $parameters['uid'];
$cmd = $parameters['cmd'];
$accessAllowed = $parameters['hasAccess'];
if ($accessAllowed && $table === 'sys_file_metadata' && $cmd === 'edit') {
$fileMetadataRecord = (array)BackendUtility::getRecord('sys_file_metadata', $uid);
$accessAllowed = $this->checkFileWriteAccessForFileMetaData($fileMetadataRecord);
if (!$event->doesUserHaveAccess()
|| $event->getTableName() !== 'sys_file_metadata'
|| $event->getCommand() !== 'edit'
) {
return;
}
return $accessAllowed;
$this->checkFileWriteAccessForFileMetaData(