dolibarr 19.0.4
oauthlogintokens.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2014-2018 Frederic France <frederic.france@netlogic.fr>
4 * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Load Dolibarr environment
27require '../main.inc.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
29require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php';
30require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
31
32use OAuth\Common\Storage\DoliStorage;
33
34$supportedoauth2array = getSupportedOauth2Array();
35
36// Load translation files required by the page
37$langs->loadLangs(array('admin', 'printing', 'oauth'));
38
39$action = GETPOST('action', 'aZ09');
40$mode = GETPOST('mode', 'alpha');
41$value = GETPOST('value', 'alpha');
42$varname = GETPOST('varname', 'alpha');
43$driver = GETPOST('driver', 'alpha');
44
45if (!empty($driver)) {
46 $langs->load($driver);
47}
48
49if (!$mode) {
50 $mode = 'setup';
51}
52
53if (!$user->admin) {
55}
56
57
58/*
59 * Action
60 */
61
62/*if (($mode == 'test' || $mode == 'setup') && empty($driver))
63{
64 setEventMessages($langs->trans('PleaseSelectaDriverfromList'), null);
65 header("Location: ".$_SERVER['PHP_SELF'].'?mode=config');
66 exit;
67}*/
68
69if ($action == 'setconst' && $user->admin) {
70 $error = 0;
71 $db->begin();
72
73 $setupconstarray = GETPOST('setupdriver', 'array');
74
75 foreach ($setupconstarray as $setupconst) {
76 //print '<pre>'.print_r($setupconst, true).'</pre>';
77
78 $constname = dol_escape_htmltag($setupconst['varname']);
79 $constvalue = dol_escape_htmltag($setupconst['value']);
80 $consttype = dol_escape_htmltag($setupconst['type']);
81 $constnote = dol_escape_htmltag($setupconst['note']);
82
83 $result = dolibarr_set_const($db, $constname, $constvalue, $consttype, 0, $constnote, $conf->entity);
84 if (!($result > 0)) {
85 $error++;
86 }
87 }
88
89 if (!$error) {
90 $db->commit();
91 setEventMessages($langs->trans("SetupSaved"), null);
92 } else {
93 $db->rollback();
94 dol_print_error($db);
95 }
96 $action = '';
97}
98
99if ($action == 'setvalue' && $user->admin) {
100 $db->begin();
101
102 $result = dolibarr_set_const($db, $varname, $value, 'chaine', 0, '', $conf->entity);
103 if (!($result > 0)) {
104 $error++;
105 }
106
107 if (!$error) {
108 $db->commit();
109 setEventMessages($langs->trans("SetupSaved"), null);
110 } else {
111 $db->rollback();
112 dol_print_error($db);
113 }
114 $action = '';
115}
116
117
118/*
119 * View
120 */
121
122// Define $urlwithroot
123$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
124$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
125//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
126
127$form = new Form($db);
128
129llxHeader('', $langs->trans("TokenManager"));
130
131$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
132print load_fiche_titre($langs->trans('ConfigOAuth'), $linkback, 'title_setup');
133
135
136print dol_get_fiche_head($head, 'tokengeneration', '', -1, '');
137
138if (GETPOST('error')) {
139 setEventMessages(GETPOST('error'), null, 'errors');
140}
141
142if ($mode == 'setup' && $user->admin) {
143 print '<span class="opacitymedium">'.$langs->trans("OAuthSetupForLogin")."</span><br><br>\n";
144
145 // Define $listinsetup
146 foreach ($conf->global as $key => $val) {
147 if (!empty($val) && preg_match('/^OAUTH_.*_ID$/', $key)) {
148 $provider = preg_replace('/_ID$/', '', $key);
149 $listinsetup[] = array(
150 $provider.'_NAME',
151 $provider.'_ID',
152 $provider.'_SECRET',
153 $provider.'_URLAUTHORIZE', // For custom oauth links
154 $provider.'_SCOPE' // For custom oauth links
155 );
156 }
157 }
158
159 $oauthstateanticsrf = bin2hex(random_bytes(128/8));
160
161 // $list is defined into oauth.lib.php to the list of supporter OAuth providers.
162 if (!empty($listinsetup)) {
163 foreach ($listinsetup as $key) {
164 $supported = 0;
165 $keyforsupportedoauth2array = $key[0]; // May be OAUTH_GOOGLE_NAME or OAUTH_GOOGLE_xxx_NAME
166 $keyforsupportedoauth2array = preg_replace('/^OAUTH_/', '', $keyforsupportedoauth2array);
167 $keyforsupportedoauth2array = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array);
168 if (preg_match('/^.*-/', $keyforsupportedoauth2array)) {
169 $keybeforeprovider = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
170 $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array);
171 } else {
172 $keybeforeprovider = $keyforsupportedoauth2array;
173 $keyforprovider = '';
174 }
175 $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
176 $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
177
178
179 $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : ''));
180
181 $shortscope = '';
182 if (getDolGlobalString($key[4])) {
183 $shortscope = getDolGlobalString($key[4]);
184 }
185 $state = $shortscope; // TODO USe a better state
186
187 // Define $urltorenew, $urltodelete, $urltocheckperms
188 if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') {
189 // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service).
190 // We pass this param list in to 'state' because we need it before and after the redirect.
191
192 // Note: github does not accept csrf key inside the state parameter (only known values)
193 $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($shortscope).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
194 $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
195 $urltocheckperms = 'https://github.com/settings/applications/';
196 } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') {
197 // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service).
198 // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes
199 // We pass this key list into the param 'state' because we need it before and after the redirect.
200 $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
201 $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
202 $urltocheckperms = 'https://security.google.com/settings/security/permissions';
203 } elseif (!empty($supportedoauth2array[$keyforsupportedoauth2array]['returnurl'])) {
204 $urltorenew = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
205 $urltodelete = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
206 $urltocheckperms = '';
207 } else {
208 $urltorenew = '';
209 $urltodelete = '';
210 $urltocheckperms = '';
211 }
212
213 if ($urltorenew) {
214 $urltorenew .= '&keyforprovider='.urlencode($keyforprovider);
215 }
216 if ($urltodelete) {
217 $urltodelete .= '&keyforprovider='.urlencode($keyforprovider);
218 }
219
220 // Show value of token
221 $tokenobj = null;
222 // Token
223 require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
224 // Dolibarr storage
225 $storage = new DoliStorage($db, $conf, $keyforprovider);
226 try {
227 // $OAUTH_SERVICENAME is for example 'Google-keyforprovider'
228 print '<!-- '.$OAUTH_SERVICENAME.' -->'."\n";
229 $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
230 //print $storage->token.'<br>';
231 //print $tokenobj->getExtraParams()['id_token'].'<br>';
232 //print $tokenobj->getAccessToken().'<br>';
233 } catch (Exception $e) {
234 // Return an error if token not found
235 //print $e->getMessage();
236 }
237
238 // Set other properties
239 $refreshtoken = false;
240 $expiredat = '';
241
242 $expire = false;
243 // Is token expired or will token expire in the next 30 seconds
244 if (is_object($tokenobj)) {
245 $expire = ($tokenobj->getEndOfLife() !== $tokenobj::EOL_NEVER_EXPIRES && $tokenobj->getEndOfLife() !== $tokenobj::EOL_UNKNOWN && time() > ($tokenobj->getEndOfLife() - 30));
246 }
247 if ($key[1] != '' && $key[2] != '') {
248 if (is_object($tokenobj)) {
249 $refreshtoken = $tokenobj->getRefreshToken();
250
251 $endoflife = $tokenobj->getEndOfLife();
252 if ($endoflife == $tokenobj::EOL_NEVER_EXPIRES) {
253 $expiredat = $langs->trans("Never");
254 } elseif ($endoflife == $tokenobj::EOL_UNKNOWN) {
255 $expiredat = $langs->trans("Unknown");
256 } else {
257 $expiredat = dol_print_date($endoflife, "dayhour", 'tzuserrel');
258 }
259 }
260 }
261
262 $submit_enabled = 0;
263
264 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?mode=setup&amp;driver='.$driver.'" autocomplete="off">';
265 print '<input type="hidden" name="token" value="'.newToken().'">';
266 print '<input type="hidden" name="action" value="setconst">';
267
268 print '<div class="div-table-responsive-no-min">';
269 print '<table class="noborder centpercent">'."\n";
270
271 // Api Name
272 $label = $langs->trans($keyforsupportedoauth2array);
273 print '<tr class="liste_titre">';
274 print '<th class="titlefieldcreate">';
275 print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"');
276 if ($label == $keyforsupportedoauth2array) {
277 print $supportedoauth2array[$keyforsupportedoauth2array]['name'];
278 } else {
279 print $label;
280 }
281 if ($keyforprovider) {
282 print ' (<b>'.$keyforprovider.'</b>)';
283 } else {
284 print ' (<b>'.$langs->trans("NoName").'</b>)';
285 }
286 print '</th>';
287 print '<th></th>';
288 print '<th></th>';
289 print "</tr>\n";
290
291 print '<tr class="oddeven">';
292 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
293 //var_dump($key);
294 print $langs->trans("OAuthIDSecret").'</td>';
295 print '<td>';
296 print '<span class="opacitymedium">'.$langs->trans("SeePreviousTab").'</span>';
297 print '</td>';
298 print '<td>';
299 print '</td>';
300 print '</tr>'."\n";
301
302 // Scopes
303 print '<tr class="oddeven">';
304 print '<td>'.$langs->trans("Scopes").'</td>';
305 print '<td colspan="2">';
306 $currentscopes = getDolGlobalString($key[4]);
307 print $currentscopes;
308 print '</td></tr>';
309
310 print '<tr class="oddeven">';
311 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
312 //var_dump($key);
313 print $langs->trans("IsTokenGenerated");
314 print '</td>';
315 print '<td>';
316 if (is_object($tokenobj)) {
317 print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '.dol_print_date($storage->date_modification, 'dayhour').' state='.dol_escape_htmltag($storage->state));
318 } else {
319 print '<span class="opacitymedium">'.$langs->trans("NoAccessToken").'</span>';
320 }
321 print '</td>';
322 print '<td width="50%">';
323 // Links to delete/checks token
324 if (is_object($tokenobj)) {
325 //test on $storage->hasAccessToken($OAUTH_SERVICENAME) ?
326 if ($urltodelete) {
327 print '<a class="button smallpaddingimp" href="'.$urltodelete.'">'.$langs->trans('DeleteAccess').'</a><br>';
328 } else {
329 print '<span class="opacitymedium">'.$langs->trans('GoOnTokenProviderToDeleteToken').'</span><br>';
330 }
331 }
332 // Request remote token
333 if ($urltorenew) {
334 print '<a class="button smallpaddingimp" href="'.$urltorenew.'">'.$langs->trans('GetAccess').'</a>';
335 print $form->textwithpicto('', $langs->trans('RequestAccess'));
336 print '<br>';
337 }
338 // Check remote access
339 if ($urltocheckperms) {
340 print '<br>'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': <a href="'.$urltocheckperms.'" target="_'.strtolower($OAUTH_SERVICENAME).'">'.$urltocheckperms.'</a>';
341 }
342 print '</td>';
343 print '</tr>';
344
345 print '<tr class="oddeven">';
346 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
347 //var_dump($key);
348 print $langs->trans("Token").'</td>';
349 print '<td colspan="2">';
350
351 if (is_object($tokenobj)) {
352 $tokentoshow = $tokenobj->getAccessToken();
353 print '<span class="" title="'.dol_escape_htmltag($tokentoshow).'">'.showValueWithClipboardCPButton($tokentoshow, 1, dol_trunc($tokentoshow, 32)).'</span><br>';
354 //print 'Refresh: '.$tokenobj->getRefreshToken().'<br>';
355 //print 'EndOfLife: '.$tokenobj->getEndOfLife().'<br>';
356 //var_dump($tokenobj->getExtraParams());
357 /*print '<br>Extra: <br><textarea class="quatrevingtpercent">';
358 print ''.join(',',$tokenobj->getExtraParams());
359 print '</textarea>';*/
360 }
361 print '</td>';
362 print '</tr>'."\n";
363
364 if (is_object($tokenobj)) {
365 // Token refresh
366 print '<tr class="oddeven">';
367 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
368 //var_dump($key);
369 print $langs->trans("TOKEN_REFRESH");
370 print '</td>';
371 print '<td colspan="2">';
372 print '<span class="" title="'.dol_escape_htmltag($refreshtoken).'">'.showValueWithClipboardCPButton($refreshtoken, 1, dol_trunc($refreshtoken, 32)).'</span>';
373 print '</td>';
374 print '</tr>';
375
376 // Token expired
377 print '<tr class="oddeven">';
378 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
379 //var_dump($key);
380 print $langs->trans("TOKEN_EXPIRED");
381 print '</td>';
382 print '<td colspan="2">';
383 print yn($expire);
384 print '</td>';
385 print '</tr>';
386
387 // Token expired at
388 print '<tr class="oddeven">';
389 print '<td'.(empty($key['required']) ? '' : ' class="required"').'>';
390 //var_dump($key);
391 print $langs->trans("TOKEN_EXPIRE_AT");
392 print '</td>';
393 print '<td colspan="2">';
394 print $expiredat;
395 print '</td>';
396 print '</tr>';
397 }
398
399 print '</table>';
400 print '</div>';
401
402 if (!empty($driver)) {
403 if ($submit_enabled) {
404 print $form->buttonsSaveCancel("Modify", '');
405 }
406 }
407
408 print '</form>';
409 print '<br>';
410 }
411 }
412}
413
414if ($mode == 'test' && $user->admin) {
415 print $langs->trans('PrintTestDesc'.$driver)."<br><br>\n";
416
417 print '<div class="div-table-responsive-no-min">';
418 print '<table class="noborder centpercent">';
419 if (!empty($driver)) {
420 require_once DOL_DOCUMENT_ROOT.'/core/modules/printing/'.$driver.'.modules.php';
421 $classname = 'printing_'.$driver;
422 $langs->load($driver);
423 $printer = new $classname($db);
424 //print '<pre>'.print_r($printer, true).'</pre>';
425 if (count($printer->getlistAvailablePrinters())) {
426 if ($printer->listAvailablePrinters() == 0) {
427 print $printer->resprint;
428 } else {
429 setEventMessages($printer->error, $printer->errors, 'errors');
430 }
431 } else {
432 print $langs->trans('PleaseConfigureDriverfromList');
433 }
434 }
435
436 print '</table>';
437 print '</div>';
438}
439
440if ($mode == 'userconf' && $user->admin) {
441 print $langs->trans('PrintUserConfDesc'.$driver)."<br><br>\n";
442
443 print '<div class="div-table-responsive">';
444 print '<table class="noborder centpercent">';
445 print '<tr class="liste_titre">';
446 print '<th>'.$langs->trans("User").'</th>';
447 print '<th>'.$langs->trans("PrintModule").'</th>';
448 print '<th>'.$langs->trans("PrintDriver").'</th>';
449 print '<th>'.$langs->trans("Printer").'</th>';
450 print '<th>'.$langs->trans("PrinterLocation").'</th>';
451 print '<th>'.$langs->trans("PrinterId").'</th>';
452 print '<th>'.$langs->trans("NumberOfCopy").'</th>';
453 print '<th class="center">'.$langs->trans("Delete").'</th>';
454 print "</tr>\n";
455 $sql = "SELECT p.rowid, p.printer_name, p.printer_location, p.printer_id, p.copy, p.module, p.driver, p.userid, u.login";
456 $sql .= " FROM ".MAIN_DB_PREFIX."printing as p, ".MAIN_DB_PREFIX."user as u WHERE p.userid = u.rowid";
457 $resql = $db->query($sql);
458 while ($obj = $db->fetch_object($resql)) {
459 print '<tr class="oddeven">';
460 print '<td>'.$obj->login.'</td>';
461 print '<td>'.$obj->module.'</td>';
462 print '<td>'.$obj->driver.'</td>';
463 print '<td>'.$obj->printer_name.'</td>';
464 print '<td>'.$obj->printer_location.'</td>';
465 print '<td>'.$obj->printer_id.'</td>';
466 print '<td>'.$obj->copy.'</td>';
467 print '<td class="center">'.img_picto($langs->trans("Delete"), 'delete').'</td>';
468 print "</tr>\n";
469 }
470 print '</table>';
471 print '</div>';
472}
473
474print dol_get_fiche_end();
475
476// End of page
477llxFooter();
478$db->close();
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage generation of HTML components Only common components must be here.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
showValueWithClipboardCPButton($valuetocopy, $showonlyonhover=1, $texttoshow='')
Create a button to copy $valuetocopy in the clipboard (for copy and paste feature).
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getSupportedOauth2Array()
Return array of tabs to used on pages to setup cron module.
oauthadmin_prepare_head()
Return array of tabs to used on pages to setup cron module.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.