* Copyright (C) 2010-2015 Regis Houssin * Copyright (C) 2013 Florian Henry * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2024 Frédéric France * Copyright (C) 2024-2025 MDW * * 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 . */ /** * \file htdocs/user/param_ihm.php * \brief Page to show user setup for display */ // Load Dolibarr environment require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; /** * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Translate $langs * @var User $user */ // Load translation files required by page $langs->loadLangs(array('admin', 'users')); $error = 0; // Security check $id = GETPOSTINT('id'); if (!isset($id) || empty($id)) { accessforbidden(); } // Retrieve needed GETPOSTS for this file // Action / Massaction $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); // List filters $search_token = GETPOST('search_token', 'alpha'); $search_entity = GETPOST('search_entity', 'alpha'); $search_datec_startday = GETPOSTINT('search_datec_startday'); $search_datec_startmonth = GETPOSTINT('search_datec_startmonth'); $search_datec_startyear = GETPOSTINT('search_datec_startyear'); $search_datec_endday = GETPOSTINT('search_datec_endday'); $search_datec_endmonth = GETPOSTINT('search_datec_endmonth'); $search_datec_endyear = GETPOSTINT('search_datec_endyear'); $search_datec_start = dol_mktime(0, 0, 0, $search_datec_startmonth, $search_datec_startday, $search_datec_startyear); $search_datec_end = dol_mktime(23, 59, 59, $search_datec_endmonth, $search_datec_endday, $search_datec_endyear); $search_tms_startday = GETPOSTINT('search_tms_startday'); $search_tms_startmonth = GETPOSTINT('search_tms_startmonth'); $search_tms_startyear = GETPOSTINT('search_tms_startyear'); $search_tms_endday = GETPOSTINT('search_tms_endday'); $search_tms_endmonth = GETPOSTINT('search_tms_endmonth'); $search_tms_endyear = GETPOSTINT('search_tms_endyear'); $search_tms_start = dol_mktime(0, 0, 0, $search_tms_startmonth, $search_tms_startday, $search_tms_startyear); $search_tms_end = dol_mktime(23, 59, 59, $search_tms_endmonth, $search_tms_endday, $search_tms_endyear); // Pagination $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page"); if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { $page = 0; } $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; if (!$sortfield) { $sortfield = 'oat.token'; } if (!$sortorder) { $sortorder = 'DESC'; } // $user is current user, $id is id of edited user $canreaduser = ($user->admin || $user->hasRight("user", "user", "read")); $caneditfield = ((($user->id == $id) && $user->hasRight("user", "self", "write")) || (($user->id != $id) && $user->hasRight("user", "user", "write"))); $permissiontodelete = ($user->admin || $caneditfield); // Security check $socid = 0; if ($user->socid > 0) { $socid = $user->socid; } $feature2 = (($socid && $user->hasRight("user", "self", "write")) ? '' : 'user'); $result = restrictedArea($user, 'user', $id, 'user&user', $feature2); if ($user->id != $id && !$canreaduser) { accessforbidden(); } $arrayfields = array( 'oat.token' => array('label' => "ApiToken", 'checked' => '1'), 'e.label' => array('label' => "Entity", 'checked' => '1'), 'oat.datec' => array('label' => "DateCreation", 'checked' => '1'), 'oat.tms' => array('label' => "DateModification", 'checked' => '1'), ); $object = new User($db); $object->fetch($id, '', '', 1); $object->loadRights(); $form = new Form($db); $formadmin = new FormAdmin($db); /* * Actions */ $parameters = array('id' => $socid); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } if (empty($reshook)) { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers $search_token = ''; $search_entity = ''; $search_datec_start = ''; $search_datec_end = ''; $search_tms_start = ''; $search_tms_end = ''; $toselect = array(); } if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation } if ($action == 'update' && ($caneditfield || !empty($user->admin))) { header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id); exit; } if (($action == 'delete' && $confirm == 'yes') && $permissiontodelete) { $db->begin(); $nbok = 0; $TMsg = array(); //$toselect could contain duplicate entries, cf https://github.com/Dolibarr/dolibarr/issues/26244 $unique_arr = array_unique($toselect); foreach ($unique_arr as $toselectid) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."oauth_token"; $sql .= " WHERE rowid = '".$toselectid."'"; $sql .= " AND service = 'dolibarr_rest_api'"; $result = $db->query($sql); if ($result > 0) { $nbok++; } else { setEventMessages($db->error(), null, 'errors'); $error++; break; } } if (empty($error)) { // Message for elements well deleted if ($nbok > 1) { setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs'); } elseif ($nbok > 0) { setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs'); } else { setEventMessages($langs->trans("NoRecordDeleted"), null, 'mesgs'); } $db->commit(); } else { $db->rollback(); } //var_dump($listofobjectthirdparties);exit; } } /* * View */ $person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; $title = $person_name." - ".$langs->trans('Card'); $help_url = ''; $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { /* The fast and low memory method to get and count full list converts the sql into a sql count */ $sqlforcount = 'SELECT COUNT(*) as nbtotalofrecords'; $sqlforcount .= " FROM ".MAIN_DB_PREFIX."oauth_token as oat"; $sqlforcount .= " WHERE entity IN (".$conf->entity.")"; $sqlforcount .= " AND fk_user = ".$id; $sqlforcount .= " AND service = 'dolibarr_rest_api'"; $resql = $db->query($sqlforcount); if ($resql) { $objforcount = $db->fetch_object($resql); $nbtotalofrecords = $objforcount->nbtotalofrecords; } else { dol_print_error($db); } if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } $db->free($resql); } $sql = "SELECT oat.rowid as token_id, oat.token, oat.entity, oat.state as rights, oat.datec as date_creation, oat.tms as date_modification"; if (isModEnabled('multicompany')) { $sql .= ", e.label as entity_name"; } $sql .= " FROM ".MAIN_DB_PREFIX."oauth_token as oat"; if (isModEnabled('multicompany')) { $sql .= " JOIN ".$db->prefix()."entity as e ON oat.entity = e.rowid"; } $sql .= " WHERE oat.fk_user = ".((int) $object->id); $sql .= " AND entity IN (".$conf->entity.")"; $sql .= " AND service = 'dolibarr_rest_api'"; if ($search_token) { $sql .= natural_search('oat.token', $search_token); } if ($search_entity) { $sql .= natural_search('oat.entity', $search_entity); } if ($search_datec_start) { $sql .= " AND oat.datec >= '".$db->idate($search_datec_start)."'"; } if ($search_datec_end) { $sql .= " AND oat.datec <= '".$db->idate($search_datec_end)."'"; } if ($search_tms_start) { $sql .= " AND oat.tms >= '".$db->idate($search_tms_start)."'"; } if ($search_tms_end) { $sql .= " AND oat.tms <= '".$db->idate($search_tms_end)."'"; } $sql .= $db->order($sortfield, $sortorder); if ($limit) { $sql .= $db->plimit($limit + 1, $offset); } $resql = $db->query($sql); $num = $db->num_rows($resql); llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-user page-card_param_ihm'); $param = '&id='.$id; // We always need the id of the user if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.((int) $limit); } if ($search_datec_startday) { $param .= '&search_date_startday='.urlencode((string) ($search_datec_startday)); } if ($search_datec_startmonth) { $param .= '&search_date_startmonth='.urlencode((string) ($search_datec_startmonth)); } if ($search_datec_startyear) { $param .= '&search_date_startyear='.urlencode((string) ($search_datec_startyear)); } if ($search_datec_endday) { $param .= '&search_date_endday='.urlencode((string) ($search_datec_endday)); } if ($search_datec_endmonth) { $param .= '&search_date_endmonth='.urlencode((string) ($search_datec_endmonth)); } if ($search_datec_endyear) { $param .= '&search_date_endyear='.urlencode((string) ($search_datec_endyear)); } if ($search_tms_startday) { $param .= '&search_date_startday='.urlencode((string) ($search_tms_startday)); } if ($search_tms_startmonth) { $param .= '&search_date_startmonth='.urlencode((string) ($search_tms_startmonth)); } if ($search_tms_startyear) { $param .= '&search_date_startyear='.urlencode((string) ($search_tms_startyear)); } if ($search_tms_endday) { $param .= '&search_date_endday='.urlencode((string) ($search_tms_endday)); } if ($search_tms_endmonth) { $param .= '&search_date_endmonth='.urlencode((string) ($search_tms_endmonth)); } if ($search_tms_endyear) { $param .= '&search_date_endyear='.urlencode((string) ($search_tms_endyear)); } $arrayofselected = is_array($toselect) ? $toselect : array(); $head = user_prepare_head($object); $title = $langs->trans("User"); print dol_get_fiche_head($head, 'apitoken', $title, -1, 'user'); $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->transnoentitiesnoconv("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; print '
'; print ''; // Login print ''; if (!empty($object->ldap_sid) && $object->status == 0) { print ''; } else { print ''; } print ''."\n"; print '
'.$langs->trans("Login").''; print $langs->trans("LoginAccountDisableInDolibarr"); print ''; $addadmin = ''; if (property_exists($object, 'admin')) { if (isModEnabled('multicompany') && !empty($object->admin) && empty($object->entity)) { $addadmin .= img_picto($langs->trans("SuperAdministratorDesc"), "redstar", 'class="paddingleft valignmiddle"'); } elseif (!empty($object->admin)) { $addadmin .= img_picto($langs->trans("AdministratorDesc"), "star", 'class="paddingleft valignmiddle"'); } } print showValueWithClipboardCPButton($object->login).$addadmin; print '
'; print '
'; print dol_get_fiche_end(); print ''."\n"; $arrayofmassactions = array( 'predelete' => img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete") ); if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); $morehtmlright = ''; //if (!empty($moreoptions['showhideaddbutton']) && $conf->use_javascript_ajax) { $tmpurlforbutton = DOL_URL_ROOT.'/user/api_token/card.php?id='.$id.'&action=create'; // TODO Permissions ? $morehtmlright .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', $tmpurlforbutton, '', $permtoeditline); $morehtmlright .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', $tmpurlforbutton); //} print '
'."\n"; print ''; print ''; print ''; print ''; print ''; print_barre_liste($langs->trans("ListOfTokensForUser"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, '', 0, $morehtmlright, '', $limit, 0, 0, 1); include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; // TODO : Build the hook management // Other form for add user to group //$parameters = array('caneditgroup' => $permissiontoeditgroup, 'groupslist' => $groupslist, 'exclude' => $exclude); //$reshook = $hookmanager->executeHooks('formAddUserToGroup', $parameters, $object, $action); // Note that $action and $object may have been modified by hook //print $hookmanager->resPrint; if (empty($reshook)) { print ''; print ''; print ''; // Action buttons if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } // Token string if (!empty($arrayfields['oat.token']['checked'])) { print ''; } // Entity if (!empty($arrayfields['e.label']['checked']) && isModEnabled('multicompany')) { print ''; } // Number of perms // We don't search out number of perms because it is a string field, // and we don't want to count into it with sql query print ''; // Date creation if (!empty($arrayfields['oat.datec']['checked'])) { print ''; } // Date modification if (!empty($arrayfields['oat.tms']['checked'])) { print ''; } // Action buttons if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ""; print ''; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } if (!empty($arrayfields['oat.token']['checked'])) { print_liste_field_titre($arrayfields['oat.token']['label'], $_SERVER["PHP_SELF"], 'oat.token', '', $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['e.label']['checked']) && isModEnabled('multicompany')) { print_liste_field_titre($arrayfields['e.label']['label'], $_SERVER["PHP_SELF"], 'e.label', '', $param, '', $sortfield, $sortorder); } print ''; if (!empty($arrayfields['oat.datec']['checked'])) { print_liste_field_titre($arrayfields['oat.datec']['label'], $_SERVER["PHP_SELF"], 'oat.datec', '', $param, '', $sortfield, $sortorder, 'center '); } if (!empty($arrayfields['oat.tms']['checked'])) { print_liste_field_titre($arrayfields['oat.tms']['label'], $_SERVER["PHP_SELF"], 'oat.tms', '', $param, '', $sortfield, $sortorder, 'center '); } if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ''; // List of tokens of user $i = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); if ($num > 0) { while ($i < $imaxinloop) { // Compute number of perms $obj = $db->fetch_object($resql); $numperms = 0; if (!empty($obj->rights)) { $numperms = count(explode(",", $obj->rights)); } print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ''; if (isModEnabled('multicompany')) { print ''; } print ''; print ''; print ''; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ''; $i++; } } else { $colspan = 5; // Base colspan if (isModEnabled('multicompany')) { $colspan++; } print ''; } print "
'; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; print ''; print ''; print ''; print ''; print ''; print '
'; print $form->selectDate($search_datec_start ? $search_datec_start : -1, 'search_datec_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); print '
'; print '
'; print $form->selectDate($search_datec_end ? $search_datec_end : -1, 'search_datec_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); print '
'; print '
'; print '
'; print $form->selectDate($search_tms_start ? $search_tms_start : -1, 'search_tms_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); print '
'; print '
'; print $form->selectDate($search_tms_end ? $search_tms_end : -1, 'search_tms_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); print '
'; print '
'; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; print '
'; print $form->showCheckAddButtons('checkforselect', 1); print ''.$langs->trans("NumberOfPermissions").''; print $form->showCheckAddButtons('checkforselect', 1); print '
'; if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined $selected = 0; if (in_array($obj->token_id, $arrayofselected)) { $selected = 1; } print ''; } print ''; print ''; print dolDecrypt($obj->token); print ''; print ''; print ''; print ''; print $obj->entity_name; print ' '; print ''; print $numperms; print ''; print dol_print_date($db->jdate($obj->date_creation), 'day'); print ''; print dol_print_date($db->jdate($obj->date_modification), 'day'); print ''; if ($massactionbutton || $massaction) { $selected = 0; if (in_array($obj->token_id, $arrayofselected)) { $selected = 1; } print ''; } print '
'.$langs->trans("None").'
"; print '
'; } // End of page llxFooter(); $db->close();