TimeTrex/interface/html5/client/ForgotPassword.php

276 lines
12 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*********************************************************************************
*
* TimeTrex is a Workforce Management program developed by
* TimeTrex Software Inc. Copyright (C) 2003 - 2021 TimeTrex Software Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY TIMETREX, TIMETREX DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License for more
* details.
*
*
* You should have received a copy of the GNU Affero General Public License along
* with this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
*
* You can contact TimeTrex headquarters at Unit 22 - 2475 Dobbin Rd. Suite
* #292 West Kelowna, BC V4T 2E9, Canada or at email address info@timetrex.com.
*
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by TimeTrex" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by TimeTrex".
*
********************************************************************************/
require_once( '../../../includes/global.inc.php' );
forceNoCacheHeaders(); //Send headers to disable caching.
TTi18n::chooseBestLocale();
extract( FormVariables::GetVariables(
[
'action',
'email',
'key',
'email_sent',
'password',
'password2',
] ) );
$rl = TTNew( 'RateLimit' ); /** @var RateLimit $rl */
$rl->setID( 'client_contact_password_reset_' . Misc::getRemoteIPAddress() );
$rl->setAllowedCalls( 10 );
$rl->setTimeFrame( 900 ); //15 minutes
$validator = new Validator();
//All HTML special chars are encoded prior to getting here, which makes things like "&" be saved as "&amp;", corrupting passwords.
$password = FormVariables::reverseSanitize( $password );
$password2 = FormVariables::reverseSanitize( $password2 );
$action = Misc::findSubmitButton();
Debug::Text( 'Action: ' . $action, __FILE__, __LINE__, __METHOD__, 10 );
switch ( $action ) {
case 'change_password':
Debug::Text( 'Change Password: ' . $key, __FILE__, __LINE__, __METHOD__, 10 );
if ( $rl->check() == false ) {
Debug::Text( 'Excessive change password attempts... Preventing resets from: ' . Misc::getRemoteIPAddress() . ' for up to 15 minutes...', __FILE__, __LINE__, __METHOD__, 10 );
sleep( 5 ); //Excessive password attempts, sleep longer.
$action = 'reset_password';
} else {
$cclf = TTnew( 'ClientContactListFactory' ); /** @var ClientContactListFactory $cclf */
$cclf->getByPasswordResetKey( $key );
if ( $cclf->getRecordCount() == 1 ) {
Debug::Text( 'FOUND Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$cc_obj = $cclf->getCurrent();
if ( $cc_obj->checkPasswordResetKey( $key ) == true ) {
$user_name = $cc_obj->getUserName();
//Make sure passwords match
if ( $password == $password2 ) {
//Change password
$cc_obj->setPassword( $password ); //Password reset key is cleared when password is changed.
if ( $cc_obj->isValid() ) {
$cc_obj->Save();
Debug::Text( 'Password Change succesful!', __FILE__, __LINE__, __METHOD__, 10 );
$rl->delete(); //Clear password reset rate limit upon successful reset.
//Redirect::Page( URLBuilder::getURL( array('password_reset' => 1 ), 'Login.php' ) );
Redirect::Page( 'https://www.timetrex.com/store?step=login' );
}
} else {
$validator->isTrue( 'password', false, 'Passwords do not match' );
}
} else {
Debug::Text( 'DID NOT FIND Valid Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$action = 'reset_password';
}
} else {
Debug::Text( 'DID NOT FIND Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$action = 'reset_password';
}
Debug::text( 'Change Password Failed! Attempt: ' . $rl->getAttempts(), __FILE__, __LINE__, __METHOD__, 10 );
sleep( ( $rl->getAttempts() * 0.5 ) ); //If email is incorrect, sleep for some time to slow down brute force attacks.
}
break;
case 'password_reset':
//Debug::setVerbosity( 11 );
Debug::Text( 'Key: ' . $key, __FILE__, __LINE__, __METHOD__, 10 );
if ( $rl->check() == false ) {
Debug::Text( 'Excessive reset password attempts... Preventing resets from: ' . Misc::getRemoteIPAddress() . ' for up to 15 minutes...', __FILE__, __LINE__, __METHOD__, 10 );
sleep( 5 ); //Excessive password attempts, sleep longer.
$action = 'reset_password';
} else {
$cclf = TTnew( 'ClientContactListFactory' ); /** @var ClientContactListFactory $cclf */
$cclf->getByPasswordResetKey( $key );
if ( $cclf->getRecordCount() == 1 ) {
Debug::Text( 'FOUND Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$cc_obj = $cclf->getCurrent();
if ( $cc_obj->checkPasswordResetKey( $key ) == true ) {
$user_name = $cc_obj->getUserName();
$rl->delete(); //Clear password reset rate limit upon successful reset.
} else {
Debug::Text( 'DID NOT FIND Valid Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$action = 'reset_password';
}
} else {
Debug::Text( 'DID NOT FIND Password reset key! ', __FILE__, __LINE__, __METHOD__, 10 );
$action = 'reset_password';
}
Debug::text( 'Reset Password Failed! Attempt: ' . $rl->getAttempts(), __FILE__, __LINE__, __METHOD__, 10 );
sleep( ( $rl->getAttempts() * 0.5 ) ); //If email is incorrect, sleep for some time to slow down brute force attacks.
}
break;
case 'reset_password':
//Debug::setVerbosity( 11 );
Debug::Text( 'Email: ' . $email, __FILE__, __LINE__, __METHOD__, 10 );
if ( $rl->check() == false ) {
Debug::Text( 'Excessive reset password attempts... Preventing resets from: ' . Misc::getRemoteIPAddress() . ' for up to 15 minutes...', __FILE__, __LINE__, __METHOD__, 10 );
sleep( 5 ); //Excessive password attempts, sleep longer.
$validator->isTrue( 'email', false, TTi18n::getText( 'Email address was not found in our database (z)' ) );
} else {
$cclf = TTnew( 'ClientContactListFactory' ); /** @var ClientContactListFactory $cclf */
//$cclf->getByHomeEmailOrWorkEmail( $email );
$cclf->getByUserName( $email );
if ( $cclf->getRecordCount() == 1 ) {
$cc_obj = $cclf->getCurrent();
$cc_obj->sendPasswordResetEmail();
Debug::Text( 'Found USER! ', __FILE__, __LINE__, __METHOD__, 10 );
$rl->delete(); //Clear password reset rate limit upon successful login.
Redirect::Page( URLBuilder::getURL( [ 'email_sent' => 1, 'email' => $email ], Environment::getBaseURL() . 'html5/client/ForgotPassword.php' ) );
} else {
//Error
Debug::Text( 'DID NOT FIND USER! ', __FILE__, __LINE__, __METHOD__, 10 );
$validator->isTrue( 'email', false, 'Email address was not found in our database' );
}
Debug::text( 'Reset Password Failed! Attempt: ' . $rl->getAttempts(), __FILE__, __LINE__, __METHOD__, 10 );
sleep( ( $rl->getAttempts() * 0.5 ) ); //If email is incorrect, sleep for some time to slow down brute force attacks.
}
break;
default:
break;
}
$BASE_URL = '../';
$META_TITLE = TTi18n::getText( 'Password Reset' );
require( '../../../includes/Header.inc.php' );
?>
<div id="contentContainer" class="content-container">
<div class="container">
<div class="row">
<div class="col-12">
<div id="contentBox-ForgotPassword">
<div class="textTitle2"><?php echo TTi18n::getText( 'Password Reset' ) ?></div>
<?php
if ( $action == 'password_reset' || $action == 'change_password' ) {
?>
<?php if ( !$validator->isValid() ) { ?>
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>
<?php echo TTi18n::getText( 'Incorrect Input!' ); ?>
<script language=JavaScript>
var form_modified = true;
</script>
<br>
<?php echo $validator->geterrors(); ?>
</div>
<?php } ?>
<form method="post" name="password_reset" class="form-horizontal" action="">
<div class="form-group row">
<label class="col-sm-3 col-xs-12 control-label"><?php echo TTi18n::getText( 'Email:' ) ?> </label>
<div class="col-sm-9 col-xs-12">
<p class="form-control-static"><?php echo $user_name; ?></p>
</div>
</div>
<div class="form-group row">
<label for="password"
class="col-xs-12 col-sm-3 control-label"><?php echo TTi18n::getText( 'New Password:' ) ?> </label>
<div class="col-xs-12 col-sm-9">
<input type="password" id="password" class="form-control" name="password"
autocomplete="new-password">
</div>
</div>
<div class="form-group row">
<label for="password2"
class="col-xs-12 col-sm-3 control-label"><?php echo TTi18n::getText( 'New Password (confirm):' ) ?> </label>
<div class="col-xs-12 col-sm-9">
<input type="password" id="password2" class="form-control" name="password2"
autocomplete="new-password">
</div>
</div>
<input type="hidden" name="key" value="<?php echo $key; ?>">
<input type="submit" class="button btn btn-default" name="action:change_password"
value="<?php echo TTi18n::getText( 'Change Password' ) ?>">
</form>
<?php
} else {
if ( $email_sent == 1 ) {
?>
<div id="rowWarning" class="text-center">
<?php echo TTi18n::getText( 'An email has been sent to' ) . ' <b>' . $email . '</b> ' . TTi18n::getText( 'with instructions on how to change your password.' ); ?>
</div>
</div>
<?php
} else {
?>
<?php if ( !$validator->isValid() ) { ?>
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>
<?php echo TTi18n::getText( 'Incorrect Input!' ); ?>
<script language=JavaScript>
var form_modified = true;
</script>
<br>
<?php echo $validator->geterrors(); ?>
</div>
<?php } ?>
<form method="post" name="password_reset" class="form-horizontal" action="">
<div class="form-group row">
<label for="email"
class="col-xs-12 col-sm-3 control-label"><?php echo TTi18n::getText( 'Email Address:' ); ?> </label>
<div class="col-xs-12 col-sm-9">
<input type="text" id="email" class="form-control" name="email"
value="<?php echo $email; ?>">
</div>
</div>
<input type="submit" class="button btn btn-default" name="action:reset_password"
value="<?php echo TTi18n::getText( 'Reset Password' ); ?>">
</form>
</div>
<?php
}
}
?>
</div>
</div>
</div>
</div>
</div>
<?php
require( '../../../includes/Footer.inc.php' );
?>