Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Fix the uploaded file name being lost after the client injection upload step
- Fix models mapped to additional fields (Fields plugin) becoming inaccessible and their values being rejected on injection

## [2.15.12] - 2026-10-05

Expand Down
29 changes: 28 additions & 1 deletion inc/commoninjectionlib.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,27 @@ private function addCheckWarning(int $code, string $itemtype): void
}


public static function isFieldsContainerItemtype(string $itemtype): bool
{
return is_a($itemtype, 'PluginFieldsAbstractContainerInstance', true);
}


public static function canWriteFieldsContainer(string $itemtype): bool
{
/** @var DBmysql $DB */
global $DB;

//The generated table stores its container id as the column default
$columns = $DB->listFields(getTableForItemType($itemtype));

return class_exists('PluginFieldsProfile') && PluginFieldsProfile::getRightOnContainer(
(int) $_SESSION['glpiactiveprofile']['id'],
(int) ($columns['plugin_fields_containers_id']['Default'] ?? 0),
) > READ;
}


/**
* Perform data injection into GLPI DB
*
Expand All @@ -1801,7 +1822,13 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr
//Skipped without a session, as the lib is also a programmatic entry point for scripts.
if (Session::getLoginUserID() !== false) {
$input = is_array($values) ? $values : [];
if ($add) {
//Fields values are only written once the parent item passed its own check
if (self::isFieldsContainerItemtype($item::class)) {
if (!self::canWriteFieldsContainer($item::class)) {
$this->addCheckWarning($add ? self::ERROR_CANNOT_IMPORT : self::ERROR_CANNOT_UPDATE, $item::class);
return 0;
}
} elseif ($add) {
//Passing the input to can() makes the check cover the target entity
if (!$item->can(-1, CREATE, $input)) {
$this->addCheckWarning(self::ERROR_CANNOT_IMPORT, $item::class);
Expand Down
9 changes: 9 additions & 0 deletions inc/model.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,15 @@ public static function checkRightOnModel(int $models_id): bool
continue;
}

//Fields denies direct writes by design: its values follow the model itemtype rights, checked in this loop
if (PluginDatainjectionCommonInjectionLib::isFieldsContainerItemtype($itemtype)) {
if (!PluginDatainjectionCommonInjectionLib::canWriteFieldsContainer($itemtype)) {
return false;
}

continue;
}

$item = new $itemtype();
if ($check_add && !$item->canCreate()) {
return false;
Expand Down
110 changes: 110 additions & 0 deletions tests/fixtures/fields_stubs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

/**
* -------------------------------------------------------------------------
* DataInjection plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of DataInjection.
*
* DataInjection is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DataInjection is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DataInjection. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2007-2023 by DataInjection plugin team.
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/datainjection
* -------------------------------------------------------------------------
*/

//Minimal stand-ins for the Fields plugin classes the rights checks rely on, loaded only when Fields is absent

abstract class PluginFieldsAbstractContainerInstance extends CommonDBChild
{
public static $itemtype = 'itemtype';

public static $items_id = 'items_id';

public static function canCreate(): bool
{
return false;
}

public static function canUpdate(): bool
{
return false;
}
}

class PluginFieldsProfile
{
public static int $right = 0;

public static function getRightOnContainer(int $profile_id, int $container_id): int
{
return $container_id === PluginFieldsComputerstub::CONTAINER_ID ? self::$right : 0;
}
}

class PluginFieldsComputerstub extends PluginFieldsAbstractContainerInstance
{
public const CONTAINER_ID = 42;

public const VALUE_FIELD = 'stubvaluefield';

public static $rightname = 'computer';
}

class PluginFieldsComputerstubInjection extends PluginFieldsComputerstub implements PluginDatainjectionInjectionInterface
{
public static $rightname = 'plugin_datainjection_model';

public static function getTable($classname = null): string
{
return getTableForItemType(PluginFieldsComputerstub::class);
}

public function isPrimaryType(): bool
{
return false;
}

public function connectedTo(): array
{
return [Computer::class];
}

public function getOptions($primary_type = ''): array
{
return [
76665 => [
'table' => self::getTable(),
'field' => self::VALUE_FIELD,
'name' => 'Stub - Value',
'linkfield' => self::VALUE_FIELD,
'datatype' => 'string',
'displaytype' => 'text',
'injectable' => PluginDatainjectionCommonInjectionLib::FIELD_INJECTABLE,
],
];
}

public function addOrUpdateObject($values = [], $options = []): array
{
$lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options);
$lib->processAddOrUpdate();

return $lib->getInjectionResults();
}
}
Loading
Loading