sanitize foreign fields

This commit is contained in:
Yuri Kuznetsov
2025-07-24 10:38:11 +03:00
parent 774143c5e2
commit 0dff4ac6b4
2 changed files with 76 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ use Espo\Core\ORM\Entity as CoreEntity;
use Espo\Core\ORM\Repository\Option\RemoveOption;
use Espo\Core\ORM\Repository\Option\SaveContext;
use Espo\Core\ORM\Repository\Option\SaveOption;
use Espo\Core\ORM\Type\FieldType;
use Espo\Core\Record\Access\LinkCheck;
use Espo\Core\Record\ActionHistory\Action;
use Espo\Core\Record\ActionHistory\ActionLogger;
@@ -69,6 +70,7 @@ use Espo\Core\Record\Duplicator\EntityDuplicator;
use Espo\Core\Record\Select\ApplierClassNameListProvider;
use Espo\Core\Select\SearchParams;
use Espo\Core\Di;
use Espo\ORM\Defs\Params\FieldParam;
use Espo\ORM\Defs\Params\RelationParam;
use Espo\ORM\Entity;
use Espo\ORM\Name\Attribute;
@@ -400,6 +402,55 @@ class Service implements Crud,
$manager = $this->injectableFactory->create(SanitizeManager::class);
$manager->process($this->entityType, $data);
$this->sanitizeInputForeign($data);
}
private function sanitizeInputForeign(stdClass $data): void
{
$entityDefs = $this->entityManager->getDefs()->getEntity($this->entityType);
/** @var array<string, Entity> $map */
$map = [];
foreach ($entityDefs->getFieldList() as $fieldDefs) {
if ($fieldDefs->getType() !== FieldType::FOREIGN) {
continue;
}
$link = $fieldDefs->getParam(FieldParam::LINK);
$foreignField = $fieldDefs->getParam(FieldParam::FIELD);
if (!$link || !$foreignField) {
continue;
}
$foreignEntityType = $entityDefs->tryGetRelation($link)?->tryGetForeignEntityType();
if (!$foreignEntityType) {
continue;
}
$id = $data->{$link . 'Id'} ?? null;
if (!is_string($id)) {
continue;
}
if (!array_key_exists($link, $map)) {
$map[$link] = $this->entityManager->getEntityById($foreignEntityType, $id);;
}
$foreignEntity = $map[$link] ?? null;
if (!$foreignEntity) {
continue;
}
$field = $fieldDefs->getName();
$data->$field = $foreignEntity->get($foreignField);
}
}
protected function filterInput(stdClass $data): void

View File

@@ -34,6 +34,7 @@ use Espo\Core\Record\ServiceContainer;
use Espo\Core\Utils\Config\ConfigWriter;
use Espo\Entities\User;
use Espo\Modules\Crm\Entities\Account;
use Espo\Modules\Crm\Entities\Contact;
use Espo\Modules\Crm\Entities\Meeting;
use Espo\Modules\Crm\Entities\Opportunity;
use Espo\Modules\Crm\Entities\Task;
@@ -221,4 +222,28 @@ class SanitizeTest extends BaseTestCase
$this->assertEquals('2030-12-10', $meeting->get('closeDate'));
}
public function testForeign(): void
{
$account = $this->getEntityManager()->createEntity(Account::ENTITY_TYPE, [
'type' => Account::TYPE_CUSTOMER,
]);
$serviceContainer = $this->getContainer()->getByClass(ServiceContainer::class);
$contactService = $serviceContainer->getByClass(Contact::class);
$data = (object) [
'lastName' => 'C-1',
'accountId' => $account->getId(),
];
$contactService->sanitizeInput($data);
$this->assertEquals(Account::TYPE_CUSTOMER, $data->accountType ?? null);
$data = (object) [
'lastName' => 'C-2',
];
$contactService->sanitizeInput($data);
$this->assertEquals(null, $data->accountType ?? null);
}
}