2016-09-02 11:17:10 +02:00
< ? php
/*****************************************************************************
* ResetPassword . php
* Contains the controller for the reset password procedure .
*
* Kabuki CMS ( C ) 2013 - 2016 , Aaron van Geffen
*****************************************************************************/
class ResetPassword extends HTMLController
{
public function __construct ()
{
// Already logged in? Then you don't need this.
if ( Registry :: get ( 'user' ) -> isLoggedIn ())
throw new UserFacingException ( 'You are already logged in.' );
// Verifying an existing reset key?
if ( isset ( $_GET [ 'step' ], $_GET [ 'email' ], $_GET [ 'key' ]) && $_GET [ 'step' ] == 2 )
2024-11-05 17:17:14 +01:00
$this -> verifyResetKey ();
else
$this -> requestResetKey ();
}
private function requestResetKey ()
{
parent :: __construct ( 'Reset password - ' . SITE_TITLE );
$form = new ForgotPasswordForm ();
$this -> page -> adopt ( $form );
// Have they submitted an email address yet?
if ( isset ( $_POST [ 'emailaddress' ]) && preg_match ( '~^.+@.+\.[a-z]+$~' , trim ( $_POST [ 'emailaddress' ])))
2016-09-02 11:17:10 +02:00
{
2024-11-05 17:17:14 +01:00
$user = Member :: fromEmailAddress ( $_POST [ 'emailaddress' ]);
2024-11-05 16:44:54 +01:00
if ( ! $user )
2024-11-05 17:17:14 +01:00
{
$form -> adopt ( new Alert ( 'Invalid email address' , 'The email address you provided could not be found in our system. Please try again.' , 'danger' ));
return ;
}
2016-09-02 11:17:10 +02:00
2024-11-05 17:19:59 +01:00
if ( Authentication :: getResetTimeOut ( $user -> getUserId ()) > 0 )
{
// Update the reset time-out to prevent hammering
$resetTimeOut = Authentication :: updateResetTimeOut ( $user -> getUserId ());
// Present it to the user in a readable way
if ( $resetTimeOut > 3600 )
$timeOut = sprintf ( '%d hours' , ceil ( $resetTimeOut / 3600 ));
elseif ( $resetTimeOut > 60 )
$timeOut = sprintf ( '%d minutes' , ceil ( $resetTimeOut / 60 ));
else
$timeOut = sprintf ( '%d seconds' , $resetTimeOut );
$form -> adopt ( new Alert ( 'Password reset token already sent' , 'We already sent a password reset token to this email address recently. ' .
'If no email was received, please wait ' . $timeOut . ' to try again.' , 'error' ));
return ;
}
2024-11-05 17:17:14 +01:00
Authentication :: setResetKey ( $user -> getUserId ());
Email :: resetMail ( $user -> getUserId ());
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
// Show the success message
$this -> page -> clear ();
$box = new DummyBox ( 'An email has been sent' );
$box -> adopt ( new Alert ( '' , 'We have sent an email to ' . $_POST [ 'emailaddress' ] . ' containing details on how to reset your password.' , 'success' ));
$this -> page -> adopt ( $box );
}
}
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
private function verifyResetKey ()
{
$email = rawurldecode ( $_GET [ 'email' ]);
$user = Member :: fromEmailAddress ( $email );
if ( ! $user )
throw new UserFacingException ( 'Invalid email address. Please make sure you copied the full link in the email you received.' );
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
$key = $_GET [ 'key' ];
if ( ! Authentication :: checkResetKey ( $user -> getUserId (), $key ))
throw new UserFacingException ( 'Invalid reset token. Please make sure you copied the full link in the email you received. Note: you cannot use the same token twice.' );
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
parent :: __construct ( 'Reset password - ' . SITE_TITLE );
$form = new PasswordResetForm ( $email , $key );
$this -> page -> adopt ( $form );
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
// Are they trying to set something already?
if ( isset ( $_POST [ 'password1' ], $_POST [ 'password2' ]))
{
$missing = [];
if ( strlen ( $_POST [ 'password1' ]) < 6 || ! preg_match ( '~[^A-z]~' , $_POST [ 'password1' ]))
$missing [] = 'Please fill in a password that is at least six characters long and contains at least one non-alphabetic character (e.g. a number or symbol).' ;
if ( $_POST [ 'password1' ] != $_POST [ 'password2' ])
$missing [] = 'The passwords you entered do not match.' ;
2016-09-02 11:17:10 +02:00
2024-11-05 17:17:14 +01:00
// So, are we good to go?
if ( empty ( $missing ))
{
Authentication :: updatePassword ( $user -> getUserId (), Authentication :: computeHash ( $_POST [ 'password1' ]));
2024-11-05 17:19:59 +01:00
// Consume token, ensuring it isn't used again
Authentication :: consumeResetKey ( $user -> getUserId ());
2024-11-05 17:17:14 +01:00
$_SESSION [ 'login_msg' ] = [ 'Your password has been reset' , 'You can now use the form below to log in to your account.' , 'success' ];
header ( 'Location: ' . BASEURL . '/login/' );
exit ;
2016-09-02 11:17:10 +02:00
}
2024-11-05 17:17:14 +01:00
else
$form -> adopt ( new Alert ( 'Some fields require your attention' , '<ul><li>' . implode ( '</li><li>' , $missing ) . '</li></ul>' , 'danger' ));
2016-09-02 11:17:10 +02:00
}
}
}