NEW: Unify extrafields admin pages into a single secured page (societe, socpeople pilot)

This commit is contained in:
Frédéric FRANCE 2026-08-11 16:38:26 +02:00
parent 1ff95e5f69
commit d2b6fa3d60
No known key found for this signature in database
GPG key ID: C06E4A9656127239
4 changed files with 95 additions and 133 deletions

View file

@ -1,9 +1,5 @@
<?php
/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
/* Copyright (C) 2026 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,15 +16,18 @@
*/
/**
* \file htdocs/societe/admin/societe_extrafields.php
* \ingroup societe
* \brief Page to setup extra fields of third party
* \file htdocs/admin/extrafields.php
* \ingroup core
* \brief Single, secured admin page to create/edit/delete the
* extrafields of any registered object type. The set of
* accepted object types is a closed whitelist see
* core/lib/admin_extrafields.lib.php.
*/
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin_extrafields.lib.php';
/**
* @var Conf $conf
@ -38,7 +37,19 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
* @var User $user
*/
$langs->loadLangs(array("companies", "admin", "members"));
if (!$user->admin) {
accessforbidden();
}
$elementtype = GETPOST('elementtype', 'aZ09');
$extrafieldsadminmap = getExtrafieldsAdminMap();
if ($elementtype === '' || !array_key_exists($elementtype, $extrafieldsadminmap)) {
accessforbidden('Bad or missing value for parameter elementtype');
}
$pagedef = $extrafieldsadminmap[$elementtype];
$langs->loadLangs($pagedef['langs']);
$extrafields = new ExtraFields($db);
$form = new Form($db);
@ -48,11 +59,6 @@ $type2label = ExtraFields::getListOfTypesLabels();
$action = GETPOST('action', 'aZ09');
$attrname = GETPOST('attrname', 'alpha');
$elementtype = 'societe'; //Must be the $element of the class that manage extrafield
if (!$user->admin) {
accessforbidden();
}
/*
@ -62,24 +68,24 @@ if (!$user->admin) {
require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
/*
* View
*/
$textobject = $langs->transnoentitiesnoconv("ThirdParty");
$title = is_callable($pagedef['title']) ? $pagedef['title']() : $langs->trans($pagedef['title']);
$textobject = $langs->transnoentitiesnoconv($pagedef['headlabel']);
$help_url = 'EN:Module Third Parties setup|FR:Paramétrage_du_module_Tiers';
llxHeader('', $langs->trans("CompanySetup"), $help_url);
$help_url = $pagedef['helpurl'];
llxHeader('', $title, $help_url);
$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
print load_fiche_titre($langs->trans("CompanySetup"), $linkback, 'title_setup');
print load_fiche_titre($title, $linkback, 'title_setup');
require_once DOL_DOCUMENT_ROOT.'/'.$pagedef['headfile'];
$head = call_user_func($pagedef['headfunction']);
$head = societe_admin_prepare_head();
print dol_get_fiche_head($head, 'attributes', $langs->trans("ThirdParties"), -1, 'company');
print dol_get_fiche_head($head, $pagedef['tabid'], $textobject, -1, $pagedef['headpicto']);
require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';

View file

@ -0,0 +1,63 @@
<?php
/* Copyright (C) 2026 Frédéric France <frederic.france@free.fr>
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/core/lib/admin_extrafields.lib.php
* \brief Whitelist of elementtype values accepted by the unified
* extrafields admin page (htdocs/admin/extrafields.php).
*
* This is a closed registry: only elementtype values explicitly listed
* here can ever be processed by the unified extrafields admin page.
* Do not make this dynamic or pattern-based the whole point is that
* an attacker-controlled string can never reach ExtraFields::addExtraField(),
* ExtraFields::update()/delete(), or the raw SQL built in
* core/actions_extrafields.inc.php, without having first matched one of
* these hardcoded keys.
*/
/**
* Return the whitelist of elementtype values accepted by
* htdocs/admin/extrafields.php, and the page metadata needed to render
* each one (which tab-bar function to call, which lang files to load, ...).
*
* @return array<string,array{headfunction:string,headfile:string,tabid:string,headlabel:string,headpicto:string,title:string|callable,helpurl:string,langs:string[]}>
*/
function getExtrafieldsAdminMap()
{
return array(
'societe' => array(
'headfunction' => 'societe_admin_prepare_head',
'headfile' => 'core/lib/company.lib.php',
'tabid' => 'attributes',
'headlabel' => 'ThirdParty',
'headpicto' => 'company',
'title' => 'CompanySetup',
'helpurl' => 'EN:Module Third Parties setup|FR:Paramétrage_du_module_Tiers',
'langs' => array('companies', 'admin', 'members'),
),
'socpeople' => array(
'headfunction' => 'societe_admin_prepare_head',
'headfile' => 'core/lib/company.lib.php',
'tabid' => 'attributes_contacts',
'headlabel' => 'ContactsAddresses',
'headpicto' => 'company',
'title' => 'CompanySetup',
'helpurl' => 'EN:Module Third Parties setup|FR:Paramétrage_du_module_Tiers',
'langs' => array('companies', 'admin'),
),
);
}

View file

@ -611,7 +611,7 @@ function societe_admin_prepare_head()
// $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
complete_head_from_modules($conf, $langs, null, $head, $h, 'company_admin');
$head[$h][0] = dolBuildUrl(DOL_URL_ROOT . '/societe/admin/societe_extrafields.php');
$head[$h][0] = dolBuildUrl(DOL_URL_ROOT . '/admin/extrafields.php', array('elementtype' => 'societe'));
$head[$h][1] = $langs->trans("ExtraFieldsThirdParties");
$nbExtrafields = $extrafields->attributes['societe']['count'];
if ($nbExtrafields > 0) {
@ -620,7 +620,7 @@ function societe_admin_prepare_head()
$head[$h][2] = 'attributes';
$h++;
$head[$h][0] = dolBuildUrl(DOL_URL_ROOT . '/societe/admin/contact_extrafields.php');
$head[$h][0] = dolBuildUrl(DOL_URL_ROOT . '/admin/extrafields.php', array('elementtype' => 'socpeople'));
$head[$h][1] = $langs->trans("ExtraFieldsContacts");
$nbExtrafields = $extrafields->attributes['socpeople']['count'];
if ($nbExtrafields > 0) {

View file

@ -1,107 +0,0 @@
<?php
/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/societe/admin/contact_extrafields.php
* \ingroup societe
* \brief Page to setup extra fields of contact
*/
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
$langs->loadLangs(array("companies", "admin"));
$extrafields = new ExtraFields($db);
$form = new Form($db);
// List of supported format
$type2label = ExtraFields::getListOfTypesLabels();
$action = GETPOST('action', 'aZ09');
$attrname = GETPOST('attrname', 'alpha');
$elementtype = 'socpeople'; //Must be the $element of the class that manage extrafield
if (!$user->admin) {
accessforbidden();
}
/*
* Actions
*/
require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
/*
* View
*/
$textobject = $langs->transnoentitiesnoconv("ContactsAddresses");
$help_url = 'EN:Module Third Parties setup|FR:Paramétrage_du_module_Tiers';
llxHeader('', $langs->trans("CompanySetup"), $help_url);
$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
print load_fiche_titre($langs->trans("CompanySetup"), $linkback, 'title_setup');
$head = societe_admin_prepare_head();
print dol_get_fiche_head($head, 'attributes_contacts', $langs->trans("ThirdParties"), -1, 'company');
require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
print dol_get_fiche_end();
// Creation of an optional field
if ($action == 'create') {
print '<br><div id="newattrib"></div>';
print load_fiche_titre($langs->trans('NewAttribute'));
require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
}
// Edition of an optional field
if ($action == 'edit' && !empty($attrname)) {
print "<br>";
print load_fiche_titre($langs->trans("FieldEdition", $attrname));
require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';
}
// End of page
llxFooter();
$db->close();