Merge branch 'Dolibarr:develop' into develop

This commit is contained in:
Marc 2023-01-17 12:33:48 +01:00 committed by GitHub
commit a10d889374
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 117 additions and 66 deletions

View File

@ -36,9 +36,10 @@ if (!defined('NOREQUIREAJAX')) {
if (!defined('NOREQUIRESOC')) { if (!defined('NOREQUIRESOC')) {
define('NOREQUIRESOC', '1'); define('NOREQUIRESOC', '1');
} }
if (!defined('NOREQUIRETRAN')) { // We need langs because the getRandomPassword may use user language to define some rules of pass generation
/*if (!defined('NOREQUIRETRAN')) {
define('NOREQUIRETRAN', '1'); define('NOREQUIRETRAN', '1');
} }*/
// Load Dolibarr environment // Load Dolibarr environment
require '../../main.inc.php'; require '../../main.inc.php';
@ -55,9 +56,9 @@ top_httphead();
//print '<!-- Ajax page called with url '.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]).' -->'."\n"; //print '<!-- Ajax page called with url '.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]).' -->'."\n";
// Registering the location of boxes // Return a new generated password
if ($action) { if ($action) {
if ($action == 'getrandompassword' && ($user->admin || $user->rights->api->apikey->generate)) { if ($action == 'getrandompassword') {
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$generic = GETPOST('generic') ? true : false; $generic = GETPOST('generic') ? true : false;
echo getRandomPassword($generic); echo getRandomPassword($generic);

View File

@ -8593,11 +8593,11 @@ abstract class CommonObject
* @param int $maxHeight Max height of original image when size='small' (so we can use original even if small requested). If 0, always use 'small' thumb image. * @param int $maxHeight Max height of original image when size='small' (so we can use original even if small requested). If 0, always use 'small' thumb image.
* @param int $maxWidth Max width of original image when size='small' * @param int $maxWidth Max width of original image when size='small'
* @param int $nolink Do not add a href link to view enlarged imaged into a new tab * @param int $nolink Do not add a href link to view enlarged imaged into a new tab
* @param int $notitle Do not add title tag on image * @param int|string $overwritetitle Do not add title tag on image
* @param int $usesharelink Use the public shared link of image (if not available, the 'nophoto' image will be shown instead) * @param int $usesharelink Use the public shared link of image (if not available, the 'nophoto' image will be shown instead)
* @return string Html code to show photo. Number of photos shown is saved in this->nbphoto * @return string Html code to show photo. Number of photos shown is saved in this->nbphoto
*/ */
public function show_photos($modulepart, $sdir, $size = 0, $nbmax = 0, $nbbyrow = 5, $showfilename = 0, $showaction = 0, $maxHeight = 120, $maxWidth = 160, $nolink = 0, $notitle = 0, $usesharelink = 0) public function show_photos($modulepart, $sdir, $size = 0, $nbmax = 0, $nbbyrow = 5, $showfilename = 0, $showaction = 0, $maxHeight = 120, $maxWidth = 160, $nolink = 0, $overwritetitle = 0, $usesharelink = 0)
{ {
// phpcs:enable // phpcs:enable
global $conf, $user, $langs; global $conf, $user, $langs;
@ -8700,8 +8700,12 @@ abstract class CommonObject
// Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine // Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine
$alt = $langs->transnoentitiesnoconv('File').': '.$relativefile; $alt = $langs->transnoentitiesnoconv('File').': '.$relativefile;
$alt .= ' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height']; $alt .= ' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height'];
if ($notitle) { if ($overwritetitle) {
if (is_numeric($overwritetitle)) {
$alt = ''; $alt = '';
} else {
$alt = $overwritetitle;
}
} }
$addphotorefcss = 1; $addphotorefcss = 1;

View File

@ -164,7 +164,7 @@ class HookManager
// Define type of hook ('output' or 'addreplace'). // Define type of hook ('output' or 'addreplace').
$hooktype = 'addreplace'; $hooktype = 'addreplace';
// TODO Remove hooks with type 'output' (exemple createFrom). All hooks must be converted into 'addreplace' hooks. // TODO Remove hooks with type 'output' (exemple createFrom). All hooks must be converted into 'addreplace' hooks.
if (!in_array($method, array( if (in_array($method, array(
'createFrom', 'createFrom',
'dashboardMembers', 'dashboardMembers',
'dashboardEmailings', 'dashboardEmailings',

View File

@ -2122,14 +2122,14 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi
$maxvisiblephotos = 1; $maxvisiblephotos = 1;
} }
if ($showimage) { if ($showimage) {
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'.$object->show_photos('product', $conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0).'</div>'; $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'.$object->show_photos('product', $conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, 0, $width, 0, '').'</div>';
} else { } else {
if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) { if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) {
$nophoto = ''; $nophoto = '';
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>'; $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>';
} else { // Show no photo link } else { // Show no photo link
$nophoto = '/public/theme/common/nophoto.png'; $nophoto = '/public/theme/common/nophoto.png';
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo'.$modulepart.($cssclass ? ' '.$cssclass : '').'" alt="No photo"'.($width ? ' style="width: '.$width.'px"' : '').' src="'.DOL_URL_ROOT.$nophoto.'"></div>'; $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo'.$modulepart.($cssclass ? ' '.$cssclass : '').'" title="'.dol_escape_htmltag($langs->trans("UploadAnImageToSeeAPhotoHere", $langs->transnoentitiesnoconv("Documents"))).'" alt="No photo"'.($width ? ' style="width: '.$width.'px"' : '').' src="'.DOL_URL_ROOT.$nophoto.'"></div>';
} }
} }
} elseif ($object->element == 'ticket') { } elseif ($object->element == 'ticket') {

View File

@ -560,10 +560,11 @@ function getRandomPassword($generic = false, $replaceambiguouschars = null, $len
* *
* @param string $htmlname HTML name of element to insert key into * @param string $htmlname HTML name of element to insert key into
* @param string $htmlnameofbutton HTML name of button * @param string $htmlnameofbutton HTML name of button
* @param int $generic 1=Return a generic pass, 0=Return a pass following setup rules
* @return string HTML javascript code to set a password * @return string HTML javascript code to set a password
* @see getRandomPassword() * @see getRandomPassword()
*/ */
function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token') function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token', $generic = 1)
{ {
global $conf; global $conf;
@ -571,10 +572,10 @@ function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token
print "\n".'<!-- Js code to suggest a security key --><script type="text/javascript">'; print "\n".'<!-- Js code to suggest a security key --><script type="text/javascript">';
print '$(document).ready(function () { print '$(document).ready(function () {
$("#'.dol_escape_js($htmlnameofbutton).'").click(function() { $("#'.dol_escape_js($htmlnameofbutton).'").click(function() {
console.log("We click on the button to suggest a key"); console.log("We click on the button '.dol_escape_js($htmlnameofbutton).' to suggest a key. We will fill '.dol_escape_js($htmlname).'");
$.get( "'.DOL_URL_ROOT.'/core/ajax/security.php", { $.get( "'.DOL_URL_ROOT.'/core/ajax/security.php", {
action: \'getrandompassword\', action: \'getrandompassword\',
generic: true, generic: '.($generic ? '1' : '0').',
token: \''.dol_escape_js(newToken()).'\' token: \''.dol_escape_js(newToken()).'\'
}, },
function(result) { function(result) {

View File

@ -91,18 +91,6 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes
dol_syslog("functions_dolibarr::check_user_password_dolibarr bad date end validity", LOG_WARNING); dol_syslog("functions_dolibarr::check_user_password_dolibarr bad date end validity", LOG_WARNING);
return '--bad-login-validity--'; return '--bad-login-validity--';
} }
// If there is an invalidation date, check that the current session date is not before this date
if ($obj->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"])) {
dol_syslog("functions_dolibarr::check_user_password_dolibarr user has a date for session invalidation = ".$obj->flagdelsessionsbefore." and session date = ".$_SESSION["dol_logindate"]);
$datetmp = $db->jdate($obj->flagdelsessionsbefore, 'gmt');
if ($datetmp > $now) {
// Load translation files required by the page
$langs->loadLangs(array('main', 'errors'));
$_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange");
dol_syslog("functions_dolibarr::check_user_password_dolibarr session was invalidated", LOG_WARNING);
return '--bad-login-validity--';
}
}
$passclear = $obj->pass; $passclear = $obj->pass;
$passcrypted = $obj->pass_crypted; $passcrypted = $obj->pass_crypted;

View File

@ -63,3 +63,25 @@ function check_user_password_http($usertotest, $passwordtotest, $entitytotest)
return $login; return $login;
} }
/**
* Decode the value found into the Authorization HTTP header.
* Ex: "Authorization: Basic bG9naW46cGFzcw==", $value is "Basic bG9naW46cGFzcw==" and after base64decode is "login:pass"
* Note: the $_SERVER["REMOTE_USER"] contains only the login used in the HTTP Basic form
* Method not used yet, but we keep it for some dev/test purposes.
*
* @param string $value Ex: $_SERVER["REMOTE_USER"]
* @return Object object.login & object.password
*/
function decodeHttpBasicAuth($value)
{
$encoded_basic_auth = substr($value, 6); // Remove the "Basic " string
$decoded_basic_auth = base64_decode($encoded_basic_auth);
$credentials_basic_auth = explode(':', $decoded_basic_auth);
return (object) [
'username'=> $credentials_basic_auth[0],
'password' => $credentials_basic_auth[1]
];
}

View File

@ -931,7 +931,7 @@ class InterfaceActionsAuto extends DolibarrTriggers
$object->sendtoid = 0; $object->sendtoid = 0;
} else { } else {
// TODO Merge all previous cases into this generic one // TODO Merge all previous cases into this generic one
// $action = BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... // $action = PASSWORD, BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ...
// Can also be a value defined by an external module like SENTBYSMS, COMPANY_SENTBYSMS, MEMBER_SENTBYSMS, ... // Can also be a value defined by an external module like SENTBYSMS, COMPANY_SENTBYSMS, MEMBER_SENTBYSMS, ...
// Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function). // Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function).
// Note that these key can be set in agenda setup, only if defined into llx_c_action_trigger // Note that these key can be set in agenda setup, only if defined into llx_c_action_trigger

View File

@ -303,6 +303,7 @@ ErrorValueForTooLow=Value for <b>%s</b> is too low
ErrorValueCantBeNull=Value for <b>%s</b> can't be null ErrorValueCantBeNull=Value for <b>%s</b> can't be null
ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission
ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s) ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s)
ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password change. Please relogin.
# Warnings # Warnings
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.
@ -325,6 +326,7 @@ WarningPaymentDateLowerThanInvoiceDate=Payment date (%s) is earlier than invoice
WarningTooManyDataPleaseUseMoreFilters=Too many data (more than %s lines). Please use more filters or set the constant %s to a higher limit. WarningTooManyDataPleaseUseMoreFilters=Too many data (more than %s lines). Please use more filters or set the constant %s to a higher limit.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent. WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent.
WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action. WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action.
WarningYourPasswordWasModifiedPleaseLogin=Your password was modified. For security purpose you will have to login now with your new password.
WarningAnEntryAlreadyExistForTransKey=An entry already exists for the translation key for this language WarningAnEntryAlreadyExistForTransKey=An entry already exists for the translation key for this language
WarningNumberOfRecipientIsRestrictedInMassAction=Warning, number of different recipient is limited to <b>%s</b> when using the mass actions on lists WarningNumberOfRecipientIsRestrictedInMassAction=Warning, number of different recipient is limited to <b>%s</b> when using the mass actions on lists
WarningDateOfLineMustBeInExpenseReportRange=Warning, the date of line is not in the range of the expense report WarningDateOfLineMustBeInExpenseReportRange=Warning, the date of line is not in the range of the expense report

View File

@ -1220,3 +1220,4 @@ NoSpecificContactAddressBis=This tab is dedicated to force specific contacts or
HideOnVCard=Hide %s HideOnVCard=Hide %s
AddToContacts=Add address to my contacts AddToContacts=Add address to my contacts
LastAccess=Last access LastAccess=Last access
UploadAnImageToSeeAPhotoHere=Upload an image from the tab %s to see a photo here

View File

@ -66,7 +66,8 @@ LinkedToDolibarrUser=Link to user
LinkedToDolibarrThirdParty=Link to third party LinkedToDolibarrThirdParty=Link to third party
CreateDolibarrLogin=Create a user CreateDolibarrLogin=Create a user
CreateDolibarrThirdParty=Create a third party CreateDolibarrThirdParty=Create a third party
LoginAccountDisableInDolibarr=Account disabled in Dolibarr. LoginAccountDisableInDolibarr=Account disabled in Dolibarr
PASSWORDInDolibarr=Password modified in Dolibarr
UsePersonalValue=Use personal value UsePersonalValue=Use personal value
ExportDataset_user_1=Users and their properties ExportDataset_user_1=Users and their properties
DomainUser=Domain user %s DomainUser=Domain user %s

View File

@ -943,26 +943,35 @@ if (!defined('NOLOGIN')) {
dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG);
$resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1));
if ($resultFetchUser <= 0 || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])) {
if ($resultFetchUser <= 0) { if ($resultFetchUser <= 0) {
// Account has been removed after login // Account has been removed after login
dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING);
} else {
// Session is no more valid
dol_syslog("The user has a date for session invalidation = ".$user->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions.");
}
session_destroy(); session_destroy();
session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie
session_name($sessionname); session_name($sessionname);
session_start(); session_start();
if ($resultFetchUser == 0) { if ($resultFetchUser == 0) {
// Load translation files required by page
$langs->loadLangs(array('main', 'errors')); $langs->loadLangs(array('main', 'errors'));
$_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login); $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login);
$user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login='.$login; $user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login='.$login;
} } elseif ($resultFetchUser < 0) {
if ($resultFetchUser < 0) {
$_SESSION["dol_loginmesg"] = $user->error; $_SESSION["dol_loginmesg"] = $user->error;
$user->trigger_mesg = $user->error; $user->trigger_mesg = $user->error;
} else {
$langs->loadLangs(array('main', 'errors'));
$_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange");
$user->trigger_mesg = 'ErrorUserSessionWasInvalidated - login='.$login;
} }
// Call trigger // Call trigger
@ -975,7 +984,7 @@ if (!defined('NOLOGIN')) {
// Hooks on failed login // Hooks on failed login
$action = ''; $action = '';
$hookmanager->initHooks(array('login')); $hookmanager->initHooks(array('login'));
$parameters = array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); $parameters = array('dol_authmode' => (isset($dol_authmode) ? $dol_authmode : ''), 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
$reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) { if ($reshook < 0) {
$error++; $error++;

View File

@ -257,13 +257,8 @@ if (empty($reshook)) {
if ($action == 'add') { if ($action == 'add') {
$error = 0; $error = 0;
if (!GETPOST('label', 'alpha') || !GETPOST('bank', 'alpha')) {
if (!GETPOST('label', 'alpha')) { if (!GETPOST('label', 'alpha')) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors');
}
if (!GETPOST('bank', 'alpha')) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankName")), null, 'errors');
}
$action = 'create'; $action = 'create';
$error++; $error++;
} }
@ -274,6 +269,8 @@ if (empty($reshook)) {
$companybankaccount->socid = $object->id; $companybankaccount->socid = $object->id;
$companybankaccount->fetch_thirdparty();
$companybankaccount->bank = GETPOST('bank', 'alpha'); $companybankaccount->bank = GETPOST('bank', 'alpha');
$companybankaccount->label = GETPOST('label', 'alpha'); $companybankaccount->label = GETPOST('label', 'alpha');
$companybankaccount->courant = GETPOST('courant', 'alpha'); $companybankaccount->courant = GETPOST('courant', 'alpha');
@ -293,6 +290,12 @@ if (empty($reshook)) {
$companybankaccount->datec = dol_now(); $companybankaccount->datec = dol_now();
$companybankaccount->status = 1; $companybankaccount->status = 1;
$companybankaccount->bank = trim($companybankaccount->bank);
if (empty($companybankaccount->bank) && !empty($companybankaccount->thirdparty)) {
$companybankaccount->bank = $langs->trans("Bank").' '.$companybankaccount->thirdparty->name;
}
$companybankaccount->bic = str_replace(' ', '', $companybankaccount->bic);
$db->begin(); $db->begin();
// This test can be done only once properties were set // This test can be done only once properties were set
@ -1980,7 +1983,7 @@ if ($socid && $action == 'create' && $permissiontoaddupdatepaymentinformation) {
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>'; print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>';
print '<td><input class="minwidth200" type="text" id="label" name="label" value="'.(GETPOSTISSET('label') ? GETPOST('label') : $object->name).'"></td></tr>'; print '<td><input class="minwidth200" type="text" id="label" name="label" value="'.(GETPOSTISSET('label') ? GETPOST('label') : $object->name).'"></td></tr>';
print '<tr><td class="fieldrequired">'.$langs->trans("Bank").'</td>'; print '<tr><td>'.$langs->trans("Bank").'</td>';
print '<td><input class="minwidth200" type="text" id="bank" name="bank" value="'.GETPOST('bank').'"></td></tr>'; print '<td><input class="minwidth200" type="text" id="bank" name="bank" value="'.GETPOST('bank').'"></td></tr>';
// Show fields of bank account // Show fields of bank account

View File

@ -521,7 +521,14 @@ if (empty($reshook)) {
} }
if (!$error) { if (!$error) {
$ret = $object->update($user); $passwordismodified = 0;
if (!empty($object->pass)) {
if ($object->pass != $object->pass_indatabase && !dol_verifyHash($object->pass, $object->pass_indatabase_crypted)) {
$passwordismodified = 1;
}
}
$ret = $object->update($user); // This may include call to setPassword if password has changed
if ($ret < 0) { if ($ret < 0) {
$error++; $error++;
if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
@ -615,6 +622,13 @@ if (empty($reshook)) {
$langs->load("errors"); $langs->load("errors");
setEventMessages($langs->transnoentitiesnoconv("WarningYourLoginWasModifiedPleaseLogin"), null, 'warnings'); setEventMessages($langs->transnoentitiesnoconv("WarningYourLoginWasModifiedPleaseLogin"), null, 'warnings');
} }
if ($passwordismodified && $object->login == $user->login) { // Current user has changed its password
$error++;
$langs->load("errors");
setEventMessages($langs->transnoentitiesnoconv("WarningYourPasswordWasModifiedPleaseLogin"), null, 'warnings');
header("Location: ".DOL_URL_ROOT.'/user/card.php?id='.$object->id);
exit;
}
} else { } else {
$db->rollback(); $db->rollback();
} }
@ -1023,7 +1037,10 @@ if ($action == 'create' || $action == 'adduserldap') {
$valuetoshow .= preg_replace('/./i', '*', $ldap_pass); $valuetoshow .= preg_replace('/./i', '*', $ldap_pass);
} else { } else {
// We do not use a field password but a field text to show new password to use. // We do not use a field password but a field text to show new password to use.
$valuetoshow .= ($valuetoshow ? ' + '.$langs->trans("DolibarrPassword") : '').'<input maxsize="32" type="text" name="password" value="'.dol_escape_htmltag($password).'" autocomplete="new-password">'; $valuetoshow .= ($valuetoshow ? ' + '.$langs->trans("DolibarrPassword") : '').'<input class="minwidth300 maxwidth400 widthcentpercentminusx" maxsize="32" type="text" id="password" name="password" value="'.dol_escape_htmltag($password).'" autocomplete="new-password">';
if (!empty($conf->use_javascript_ajax)) {
$valuetoshow .= '&nbsp;'.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_password" class="linkobject"');
}
} }
} }
@ -1044,7 +1061,7 @@ if ($action == 'create' || $action == 'adduserldap') {
//$generated_password = getRandomPassword(false); //$generated_password = getRandomPassword(false);
print '<tr><td>'.$langs->trans("ApiKey").'</td>'; print '<tr><td>'.$langs->trans("ApiKey").'</td>';
print '<td>'; print '<td>';
print '<input class="minwidth300 widthcentpercentminusx" maxsize="32" type="text" id="api_key" name="api_key" value="'.GETPOST('api_key', 'alphanohtml').'" autocomplete="off">'; print '<input class="minwidth300 maxwidth400 widthcentpercentminusx" maxsize="32" type="text" id="api_key" name="api_key" value="'.GETPOST('api_key', 'alphanohtml').'" autocomplete="off">';
if (!empty($conf->use_javascript_ajax)) { if (!empty($conf->use_javascript_ajax)) {
print '&nbsp;'.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_api_key" class="linkobject"'); print '&nbsp;'.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_api_key" class="linkobject"');
} }
@ -2392,7 +2409,7 @@ if ($action == 'create' || $action == 'adduserldap') {
} }
if (preg_match('/dolibarr/', $dolibarr_main_authentication)) { if (preg_match('/dolibarr/', $dolibarr_main_authentication)) {
if ($caneditpassword) { if ($caneditpassword) {
$valuetoshow .= ($valuetoshow ? (' '.$langs->trans("or").' ') : '').'<input maxlength="128" type="password" class="flat" name="password" value="'.dol_escape_htmltag($object->pass).'" autocomplete="new-password">'; $valuetoshow .= ($valuetoshow ? (' '.$langs->trans("or").' ') : '').'<input maxlength="128" type="password" class="flat" id="password" name="password" value="'.dol_escape_htmltag($object->pass).'" autocomplete="new-password">';
} else { } else {
$valuetoshow .= ($valuetoshow ? (' '.$langs->trans("or").' ') : '').preg_replace('/./i', '*', $object->pass); $valuetoshow .= ($valuetoshow ? (' '.$langs->trans("or").' ') : '').preg_replace('/./i', '*', $object->pass);
} }
@ -2875,11 +2892,10 @@ if ($action == 'create' || $action == 'adduserldap') {
} }
if (!empty($conf->api->enabled)) { if (!empty($conf->api->enabled)) {
$constname = 'api_key';
// Add button to autosuggest a key // Add button to autosuggest a key
include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
print dolJSToSetRandomPassword($constname, 'generate_api_key'); print dolJSToSetRandomPassword('password', 'generate_password', 0);
print dolJSToSetRandomPassword('api_key', 'generate_api_key', 1);
} }
// End of page // End of page

View File

@ -276,6 +276,7 @@ class User extends CommonObject
public $datelastlogin; public $datelastlogin;
public $datepreviouslogin; public $datepreviouslogin;
public $flagdelsessionsbefore;
public $iplastlogin; public $iplastlogin;
public $ippreviouslogin; public $ippreviouslogin;
public $datestartvalidity; public $datestartvalidity;
@ -441,6 +442,7 @@ class User extends CommonObject
$sql .= " u.tms as datem,"; $sql .= " u.tms as datem,";
$sql .= " u.datelastlogin as datel,"; $sql .= " u.datelastlogin as datel,";
$sql .= " u.datepreviouslogin as datep,"; $sql .= " u.datepreviouslogin as datep,";
$sql .= " u.flagdelsessionsbefore,";
$sql .= " u.iplastlogin,"; $sql .= " u.iplastlogin,";
$sql .= " u.ippreviouslogin,"; $sql .= " u.ippreviouslogin,";
$sql .= " u.datelastpassvalidation,"; $sql .= " u.datelastpassvalidation,";
@ -575,6 +577,7 @@ class User extends CommonObject
$this->datem = $this->db->jdate($obj->datem); $this->datem = $this->db->jdate($obj->datem);
$this->datelastlogin = $this->db->jdate($obj->datel); $this->datelastlogin = $this->db->jdate($obj->datel);
$this->datepreviouslogin = $this->db->jdate($obj->datep); $this->datepreviouslogin = $this->db->jdate($obj->datep);
$this->flagdelsessionsbefore = $this->db->jdate($obj->flagdelsessionsbefore, 'gmt');
$this->iplastlogin = $obj->iplastlogin; $this->iplastlogin = $obj->iplastlogin;
$this->ippreviouslogin = $obj->ippreviouslogin; $this->ippreviouslogin = $obj->ippreviouslogin;
$this->datestartvalidity = $this->db->jdate($obj->datestartvalidity); $this->datestartvalidity = $this->db->jdate($obj->datestartvalidity);
@ -2031,9 +2034,9 @@ class User extends CommonObject
// Update password // Update password
if (!empty($this->pass)) { if (!empty($this->pass)) {
if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) { if ($this->pass != $this->pass_indatabase && !dol_verifyHash($this->pass, $this->pass_indatabase_crypted)) {
// If a new value for password is set and different than the one crypted into database // If a new value for password is set and different than the one crypted into database
$result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass); $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass, 0, 1);
if ($result < 0) { if ($result < 0) {
return -5; return -5;
} }

View File

@ -204,7 +204,7 @@ class UserTest extends PHPUnit\Framework\TestCase
$newlocalobject=new User($this->savdb); $newlocalobject=new User($this->savdb);
$newlocalobject->initAsSpecimen(); $newlocalobject->initAsSpecimen();
$this->changeProperties($newlocalobject); $this->changeProperties($newlocalobject);
$this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','flagdelsessionsbefore','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected
return $localobject; return $localobject;
} }