dolibarr 24.0.0-beta
card.php
1<?php
2/* Copyright (C) 2005-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2010-2015 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro.com>
5 * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
6 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
28// Load Dolibarr environment
29require '../../main.inc.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php';
39
40// Load translation files required by page
41$langs->loadLangs(array('admin', 'users', 'errors'));
42$error = 0;
43
44// Security check
45$id = GETPOSTINT('id');
46$action = GETPOST('action', 'aZ09');
47
48if (empty($id) && $action != 'add' && $action != 'create') {
50}
51
52$socid = 0;
53if ($user->socid > 0) {
54 $socid = $user->socid;
55}
56$feature2 = (($socid && $user->hasRight("user", "self", "write")) ? '' : 'user');
57
58// Retrieve needed GETPOSTS for this file
59$toselect = GETPOST('toselect', 'array');
60$tokenid = GETPOST('tokenid', 'aZ09');
61$confirm = GETPOST('confirm', 'alpha');
62$module = GETPOST('module', 'alpha');
63$rights = GETPOSTINT('rights');
64$cancel = GETPOST('cancel', 'alpha');
65$backtopage = GETPOST('backtopage', 'alpha');
66
67// SQL query to retrieve the selected token
68$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";
69if (isModEnabled('multicompany')) {
70 $sql .= ", e.label";
71}
72$sql .= " FROM ".MAIN_DB_PREFIX."oauth_token as oat";
73if (isModEnabled('multicompany')) {
74 $sql .= " JOIN ".$db->prefix()."entity as e ON oat.entity = e.rowid";
75}
76$sql .= " WHERE oat.rowid = ".((int) $tokenid);
77
78$resql = $db->query($sql);
79
80$object = new User($db);
81$object->fetch($id, '', '', 1);
82$object->loadRights();
83
84// Deny access if user not using api
85if (empty($object->api_key)) {
87}
88
89$form = new Form($db);
90$token = $db->fetch_object($resql);
91
92$entity = $conf->entity;
93
94$result = restrictedArea($user, 'user', $id, 'user&user', $feature2);
95
96// $user is current user, $id is id of edited user
97$canreaduser = ($user->admin || ($user->id == $id));
98$canedittoken = ($user->admin || (($user->id == $id) && $user->hasRight("user", "self", "write")));
99
100if (!$canreaduser) {
102}
103
104
105/*
106 * Actions
107 */
108
109$parameters = array('id' => $socid);
110$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
111if ($reshook < 0) {
112 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
113}
114
115if (empty($reshook)) {
116 if (empty($backtopage)) {
117 $backtopage = 'list.php?id='.$object->id;
118 }
119
120 if ($cancel) {
121 if (!empty($backtopage)) {
122 header("Location: ".$backtopage);
123 exit;
124 }
125 $action = '';
126 }
127
128 if ($action == 'add' && $canedittoken) {
129 $tokenstring = GETPOST('api_key', 'alphanohtml');
130 $userid = GETPOSTINT('user');
131 $useridtoadd = !empty($userid) && $userid > 0 ? $userid : $id;
132
133 if (empty($tokenstring)) {
134 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Token")), null, 'errors');
135 $action = 'create';
136 $error++;
137 }
138
139 if (empty($useridtoadd)) {
140 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors');
141 $action = 'create';
142 $error++;
143 }
144
145 // Check if a token already exists for the dolibarr api service duplicates
146 $nbtotalofrecords = '';
147 $sqlforcount = 'SELECT COUNT(*) as nbtotalofrecords';
148 $sqlforcount .= " FROM ".MAIN_DB_PREFIX."oauth_token as oat";
149 $sqlforcount .= " WHERE token = '".$db->escape(dolEncrypt($tokenstring, '', '', 'dolibarr'))."'";
150 $sqlforcount .= " AND service = 'dolibarr_rest_api'";
151 $resql = $db->query($sqlforcount);
152 if ($resql) {
153 $objforcount = $db->fetch_object($resql);
154 $nbtotalofrecords = $objforcount->nbtotalofrecords;
155 } else {
157 $error++;
158 }
159
160 if (isset($nbtotalofrecords) && $nbtotalofrecords > 0) {
161 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentitiesnoconv("Token")), null, 'errors');
162 $action = 'create';
163 $error++;
164 }
165
166 $db->begin();
167
168 if (!$error) {
169 $sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, token, state, fk_user, entity, datec)";
170 $sql .= " VALUES ('dolibarr_rest_api', '".$db->escape(dolEncrypt($tokenstring, '', '', 'dolibarr'))."', 0, ".((int) $useridtoadd).", ".((int) $entity).", '".$db->idate(dol_now())."')";
171 $resql = $db->query($sql);
172 if (!$resql) {
173 $error++;
174 }
175
176 // TODO Manage also ACL permission per token
177
178
179 // TODO Manage also IP permission per token
180 }
181
182 if ($error) {
184 $db->rollback();
185 } else {
186 $insertedtokenid = $db->last_insert_id(MAIN_DB_PREFIX."oauth_token");
187 $db->commit();
188
189 header("Location: " . dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $useridtoadd, 'tokenid' => $insertedtokenid]));
190 exit;
191 }
192 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $canedittoken) {
193 // Remove token
194 $sql = "DELETE FROM ".MAIN_DB_PREFIX."oauth_token";
195 $sql .= " WHERE rowid = ".((int) $tokenid);
196
197 $resql = $db->query($sql);
198
199 if ($resql) {
200 header('Location: list.php?id='.((int) $object->id));
201 exit;
202 } else {
204 }
205 }
206}
207
208
209/*
210 * View
211 */
212
213if ($object->id > 0) {
214 $person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname;
215 $title = $person_name." - ".$langs->trans('ApiTokens');
216} else {
217 $title = $langs->trans("NewToken");
218}
219$help_url = '';
220
221llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-user page-card_param_ihm');
222
223$formconfirm = '';
224
225if ($action == 'delete') {
226 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&tokenid='.$token->token_id, $langs->trans('DeleteToken'), $langs->trans('ConfirmDeleteToken'), 'confirm_delete', '', 0, 1);
227}
228
229print $formconfirm;
230
231if ($action == 'create') {
232 print load_fiche_titre($title, '', 'user');
233 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
234 print '<input type="hidden" name="token" value="'.newToken().'">';
235 print '<input type="hidden" name="action" value="add">';
236 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
237
238 print dol_get_fiche_head();
239
240 print '<table class="border centpercent tableforfieldcreate">';
241
242 if ($user->admin && empty($id)) {
243 print '<tr class="field_ref"><td class="titlefieldcreate fieldrequired">'.$langs->trans('User').'</td>';
244 print '<td class="valuefieldcreate">';
245 print $form->select_dolusers('', 'user', 1, null, 0, '', '', (string) $object->entity, 0, 0, '', 0, '', 'minwidth200 maxwidth500');
246 print '</td></tr>';
247 } else {
248 print '<tr class="field_ref"><td class="titlefieldcreate fieldrequired">'.$langs->trans('User').'</td><td class="valuefieldcreate">'.($person_name ?? '').'</td></tr>';
249 }
250
251 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Token").'</td>';
252 print '<td>';
253 print '<input class="minwidth300 maxwidth400 widthcentpercentminusx" minlength="12" maxlength="128" type="text" id="api_key" name="api_key" value="'.GETPOST('api_key', 'alphanohtml').'" autocomplete="off">';
254 if (!empty($conf->use_javascript_ajax)) {
255 print img_picto($langs->transnoentities('Generate'), 'refresh', 'id="generate_api_key" class="linkobject paddingleft"');
256 }
257 print '</td></tr>';
258 print "</table>\n";
259
260 print dol_get_fiche_end();
261
262 print '<div class="center">';
263 print '<input class="button" name="add" value="'.$langs->trans("Create").'" type="submit">';
264 print '<input class="button button-cancel" value="'.$langs->trans("Cancel").'" name="cancel" type="submit">';
265 print '</div>';
266
267 print "</form>";
268} elseif ($id > 0 && !empty($token)) {
269 $arrayofselected = is_array($toselect) ? $toselect : array();
270
271 $head = user_prepare_head($object);
272
273 $title = $langs->trans("User");
274
275 print dol_get_fiche_head($head, 'apitoken', $title, -1, 'user');
276
277 $tokenvalue = dolDecrypt($token->token);
278
279 $linkback = '<a href="'.DOL_URL_ROOT.'/user/api_token/list.php?id='.$id.'">'.$langs->trans("BackToTokenList").'</a>';
280 $linkback .= '<a href="'.DOL_URL_ROOT.'/user/list.php">'.$langs->trans("BackToList").'</a>';
281
282 $morehtmlref = '<a href="'.DOL_URL_ROOT.'/user/vcard.php?id='.$object->id.'&output=file&file='.urlencode(dol_sanitizeFileName($object->getFullName($langs).'.vcf')).'" class="refid" rel="noopener">';
283 $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
284 $morehtmlref .= '</a>';
285
286 $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id);
287 $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->transnoentitiesnoconv("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover');
288
289 dol_banner_tab($object, 'api_token_card', $linkback, $user->admin, 'rowid', 'ref', $morehtmlref);
290
291 // Tokens info
292 print '<div class="fichecenter">';
293 print '<div class="underbanner clearboth"></div>';
294 print '<table class="border centpercent tableforfield">';
295
296 // Login
297 print '<tr><td class="titlefield">'.$langs->trans("Login").'</td>';
298 if (!empty($object->ldap_sid) && $object->status == 0) {
299 print '<td class="error">';
300 print $langs->trans("LoginAccountDisableInDolibarr");
301 print '</td>';
302 } else {
303 print '<td>';
304 $addadmin = '';
305 if (isModEnabled('multicompany') && !empty($object->admin) && empty($object->entity)) {
306 $addadmin .= img_picto($langs->trans("SuperAdministratorDesc"), "superadmin", 'class="paddingleft valignmiddle"');
307 } elseif (!empty($object->admin)) {
308 $addadmin .= img_picto($langs->trans("AdministratorDesc"), "admin", 'class="paddingleft valignmiddle"');
309 }
310 print showValueWithClipboardCPButton($object->login).$addadmin;
311 print '</td>';
312 }
313 print '</tr>'."\n";
314
315 // Token
316 print '<tr><td class="titlefield">'.$langs->trans("Token").'</td>';
317 print '<td>';
318 print showValueWithClipboardCPButton($tokenvalue, 1, $tokenvalue);
319 print '</td>';
320 print '</tr>'."\n";
321
322 // Creation date
323 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
324 print '<td>';
325 print dol_print_date($db->jdate($token->date_creation), 'dayhour');
326 print '</td>';
327 print '</tr>'."\n";
328
329 // Modification date
330 print '<tr><td class="titlefield">'.$langs->trans("DateModification").'</td>';
331 print '<td>';
332 print dol_print_date($db->jdate($token->date_modification), 'dayhour');
333 print '</td>';
334 print '</tr>'."\n";
335
336 print '</table>';
337 print '<div class="tabsAction">';
338 print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&tokenid='.$token->token_id.'&action=delete&token='.newToken(), '', $canedittoken);
339 print '</div>';
340 print '</div>';
341
342 print dol_get_fiche_end();
343
344
345 print load_fiche_titre($langs->trans("ListOfRightsForToken"), '', 'fa-at');
346
347 print '<!-- Rights section -->'."\n";
348
349 if ($user->admin) {
350 print info_admin($langs->trans("WarningOnlyPermissionOfActivatedModules"));
351 }
352
353 print 'TODO If no ACL given, show message to say permissions are the one of user. If ACL set, show ACL active (common to user permission)and ACL no more active (not own by user)';
354}
355
356if (isModEnabled('api') && $action == 'create') {
357 include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
358 print dolJSToSetRandomPassword('api_key', 'generate_api_key', 1);
359}
360
361// End of page
362llxFooter();
363$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage generation of HTML components Only common components must be here.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled='', $morecss='classlink button bordertransp', $jsonopen='', $jsonclose='', $accesskey='')
Return HTML code to output a button to open a dialog popup box.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
isModEnabled($module)
Is Dolibarr module enabled.
dolJSToSetRandomPassword($htmlname, $htmlnameofbutton='generate_token', $generic=1)
Output javascript to autoset a generated password using default module into a HTML element.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.
dolEncrypt($chain, $key='', $ciphering='', $forceseed='', $obfuscationmode='dolcrypt')
Encode a string with a symmetric encryption.
user_prepare_head(User $object)
Prepare array with list of tabs.