276 lines
12 KiB
PHP
276 lines
12 KiB
PHP
|
<?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 "&", 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' );
|
|||
|
?>
|