TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?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\Form\Hooks;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
|
||||
use TYPO3\CMS\Core\DataHandling\DataHandler;
|
||||
use TYPO3\CMS\Core\SysLog\Action\Database as SystemLogDatabaseAction;
|
||||
use TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
|
||||
use TYPO3\CMS\Core\Utility\MathUtility;
|
||||
use TYPO3\CMS\Form\Storage\Security\FormDefinitionPersistenceCommand;
|
||||
use TYPO3\CMS\Form\Storage\Security\FormDefinitionPersistenceGuard;
|
||||
|
||||
/**
|
||||
* Denies direct DataHandler write access to the form_definition table unless
|
||||
* FormDefinitionPersistenceGuard has granted a matching invocation. This
|
||||
* ensures form definitions can only be persisted through DatabaseStorageAdapter,
|
||||
* which applies the form persistence manager's validation and permission checks.
|
||||
*
|
||||
* Registered as processDatamapClass (create/update) and processCmdmapClass
|
||||
* (delete) so each path carries command, identifier, and field-level checks.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#[Autoconfigure(public: true)]
|
||||
final readonly class FormDefinitionDataHandlerHook
|
||||
{
|
||||
public function __construct(
|
||||
private FormDefinitionPersistenceGuard $guard,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Verifies create/update operations against the pending invocation grant.
|
||||
*
|
||||
* The command is derived from $id: a NEW-prefixed string means create,
|
||||
* an integer means update. The full incoming field array is matched against
|
||||
* the stored field names and HMAC. Setting $incomingFieldArray to null
|
||||
* cancels the record in DataHandler.
|
||||
*
|
||||
* @param array<string, mixed>|null $incomingFieldArray
|
||||
* @param-out array<string, mixed>|null $incomingFieldArray
|
||||
*/
|
||||
public function processDatamap_preProcessFieldArray(
|
||||
?array &$incomingFieldArray,
|
||||
string $table,
|
||||
string|int $id,
|
||||
DataHandler $dataHandler,
|
||||
): void {
|
||||
if ($table !== 'form_definition') {
|
||||
return;
|
||||
}
|
||||
|
||||
$isUpdate = MathUtility::canBeInterpretedAsInteger($id);
|
||||
$command = $isUpdate
|
||||
? FormDefinitionPersistenceCommand::Update
|
||||
: FormDefinitionPersistenceCommand::Create;
|
||||
$recordIdentifier = $isUpdate ? (int)$id : (string)$id;
|
||||
|
||||
if (!$this->guard->isInvocationAllowed($command, $recordIdentifier, $incomingFieldArray)) {
|
||||
$incomingFieldArray = null;
|
||||
$dataHandler->log(
|
||||
$table,
|
||||
$isUpdate ? (int)$id : 0,
|
||||
$isUpdate ? SystemLogDatabaseAction::UPDATE : SystemLogDatabaseAction::INSERT,
|
||||
null,
|
||||
SystemLogErrorClassification::USER_ERROR,
|
||||
'Persisting form definition "%s" via DataHandler is denied',
|
||||
null,
|
||||
[$id],
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->guard->consumeInvocation($command, $recordIdentifier, $incomingFieldArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks unauthorised delete commands on form_definition records.
|
||||
*
|
||||
* Sets $commandIsProcessed to true (preventing DataHandler's built-in
|
||||
* delete) when no COMMAND_FORM_DELETE grant is pending. This mirrors the
|
||||
* FilePersistenceSlot pattern for FAL-based form definitions.
|
||||
*/
|
||||
public function processCmdmap(
|
||||
string $command,
|
||||
string $table,
|
||||
int|string $id,
|
||||
mixed $value,
|
||||
bool &$commandIsProcessed,
|
||||
DataHandler $dataHandler,
|
||||
): void {
|
||||
if ($table !== 'form_definition' || $command !== 'delete') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->guard->isInvocationAllowed(FormDefinitionPersistenceCommand::Delete, (int)$id)) {
|
||||
$commandIsProcessed = true;
|
||||
$dataHandler->log(
|
||||
$table,
|
||||
(int)$id,
|
||||
SystemLogDatabaseAction::DELETE,
|
||||
null,
|
||||
SystemLogErrorClassification::USER_ERROR,
|
||||
'Deleting form definition "%s" via DataHandler is denied',
|
||||
null,
|
||||
[$id],
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->guard->consumeInvocation(FormDefinitionPersistenceCommand::Delete, (int)$id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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\Form\Hooks;
|
||||
|
||||
use TYPO3\CMS\Filelist\ContextMenu\ItemProviders\FileProvider;
|
||||
use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface;
|
||||
|
||||
/**
|
||||
* Purges previously added form files from items for context menus.
|
||||
* @internal
|
||||
*/
|
||||
class FormFileProvider extends FileProvider
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $itemsConfiguration = [];
|
||||
|
||||
/**
|
||||
* Lowest priority, thus gets executed last.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function canHandle(): bool
|
||||
{
|
||||
return parent::canHandle()
|
||||
&& str_ends_with($this->identifier, FormPersistenceManagerInterface::FORM_DEFINITION_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
public function addItems(array $items): array
|
||||
{
|
||||
$this->initialize();
|
||||
return $this->purgeItems($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges items that are not allowed for according command.
|
||||
* According canBeEdited, canBeRenamed, ... commands will always return
|
||||
* false in order to remove those form file items.
|
||||
*
|
||||
* Using the canRender() approach avoid adding hardcoded index name
|
||||
* lookup. Thus, it's streamlined with the rest of the provides, but
|
||||
* actually purges items instead of adding them.
|
||||
*
|
||||
* @param array $items
|
||||
*/
|
||||
protected function purgeItems(array $items): array
|
||||
{
|
||||
foreach ($items as $name => $item) {
|
||||
$type = $item['type'];
|
||||
|
||||
if ($type === 'submenu' && !empty($item['childItems'])) {
|
||||
$item['childItems'] = $this->purgeItems($item['childItems']);
|
||||
} elseif (!$this->canRender($name, $type)) {
|
||||
unset($items[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
protected function canBeEdited(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function canBeRenamed(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* 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\Form\Hooks;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Form\Slot\FilePersistenceSlot;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated: Remove in v16 along with the FileFormsToDatabaseUpgradeWizard
|
||||
*/
|
||||
class ImportExportHook
|
||||
{
|
||||
public function beforeAddSysFileRecordOnImport(array $params): void
|
||||
{
|
||||
$fileRecord = $params['fileRecord'];
|
||||
$temporaryFile = $params['temporaryFile'];
|
||||
|
||||
$filePersistenceSlot = GeneralUtility::makeInstance(FilePersistenceSlot::class);
|
||||
$filePersistenceSlot->allowInvocation(
|
||||
FilePersistenceSlot::COMMAND_FILE_ADD,
|
||||
implode(':', [$fileRecord['storage'], $fileRecord['identifier']]),
|
||||
$filePersistenceSlot->getContentSignature(file_get_contents($temporaryFile))
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user