diff --git a/CHANGELOG.md b/CHANGELOG.md index cfc2f70d..963f9574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix mandatory fields of a block hidden by its display conditions blocking the save of an item +- Fix fields values updates not applying the expected checks in some cases - Fix ticket observers being able to edit and save additional fields they are not allowed to modify ## [1.25.0] - 2026-10-06 diff --git a/inc/abstractcontainerinstance.class.php b/inc/abstractcontainerinstance.class.php index 549e67b4..45577142 100644 --- a/inc/abstractcontainerinstance.class.php +++ b/inc/abstractcontainerinstance.class.php @@ -34,6 +34,27 @@ abstract class PluginFieldsAbstractContainerInstance extends CommonDBChild public static string $items_id = 'items_id'; + // Values are only written through the parent item or the container form + public static function canCreate(): bool + { + return false; + } + + public static function canUpdate(): bool + { + return false; + } + + public static function canDelete(): bool + { + return false; + } + + public static function canPurge(): bool + { + return false; + } + /** * This function relies on the static property `static::$plugins_forward_entity`, * which should be populated using the following method (from setup): diff --git a/tests/Units/ContainerItemRightTest.php b/tests/Units/ContainerItemRightTest.php index 3f60d44b..fa4a8be6 100644 --- a/tests/Units/ContainerItemRightTest.php +++ b/tests/Units/ContainerItemRightTest.php @@ -166,6 +166,53 @@ public function testShowDomContainerRendersReadOnlyFieldsWithoutUpdateRight(): v ); } + public function testContainerValuesCanOnlyBeWrittenThroughContainer(): void + { + $this->login(); + $entity_id = getItemByTypeName(Entity::class, '_test_root_entity', true); + $this->setEntity($entity_id, true); + + $container = $this->createFieldContainer([ + 'label' => 'Tab container ' . $this->getUniqueString(), + 'type' => 'tab', + 'itemtypes' => [Computer::class], + 'is_active' => 1, + 'entities_id' => $entity_id, + 'is_recursive' => 1, + ]); + $field = $this->createField([ + 'label' => 'Tab field', + 'type' => 'text', + PluginFieldsContainer::getForeignKeyField() => $container->getID(), + 'ranking' => 1, + 'is_active' => 1, + 'is_readonly' => 0, + ]); + $computer = $this->createItem(Computer::class, [ + 'name' => 'Computer ' . $this->getUniqueString(), + 'entities_id' => $entity_id, + ]); + + $this->assertTrue($container->updateFieldsValues([ + 'plugin_fields_containers_id' => $container->getID(), + 'itemtype' => Computer::class, + 'items_id' => $computer->getID(), + $field->fields['name'] => 'value', + ], Computer::class, false)); + + $classname = PluginFieldsContainer::getClassname(Computer::class, $container->fields['name']); + $values = new $classname(); + $this->assertTrue($values->getFromDBByCrit(['items_id' => $computer->getID()])); + $this->assertSame('value', $values->fields[$field->fields['name']]); + + $this->assertTrue($values->can($values->getID(), READ)); + $this->assertFalse($values->can($values->getID(), UPDATE)); + $this->assertFalse($values->can($values->getID(), DELETE)); + $this->assertFalse($values->can($values->getID(), PURGE)); + $input = ['itemtype' => Computer::class, 'items_id' => $computer->getID()]; + $this->assertFalse($values->can(-1, CREATE, $input)); + } + private function renderDomContainer(int $containers_id, Computer $computer): string { ob_start();