i am new in MVC programming, especially CodeIgniter4, i made a login/register system, it works fine,
and i implemented a password reset system :
1- when a user click reset password link a form appears
2- u put your email address and u click submit (the data is sent for validation)
3- if the email is valid and exist in the database a reset link is sent to the user,
4- when the user click the link it redirect him to the reset form
5- u enter your new password and confirm
her is my code :
1- route.php
$routes->post('sendresetlink', 'ResetPwdController::sendresetlink');
$routes->get('redirect/(:num)/(:any)', 'ResetPwdController::loadResetPage/$1/$2'); // 1st param is id, 2nd is token
$routes->post('resetpassword', 'ResetPwdController::updatepassword');
2- ResetPwdController.php
//---------------------------->->- Reset password : step 1
public function sendresetlink()
{
$userModel = new UserModel();
$toEmail = $this->request->getVar('email2');
$row = $userModel->where('email', $toEmail)->first();
if ($row) {
$mail = new PHPMailer(true);
try {
//Server settings
// $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = 'smtp.gmail.com'; //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = '[email protected]'; //SMTP username
$mail->Password = 'E123456'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
$mail->CharSet = 'UTF-8';
//Recipients
$date = getServerTimestamp();
$mail->setFrom('[email protected]', "Reset password email {$date}");
$mail->addAddress($toEmail); //Add a recipient
// $pwd = generate_password(8);
$token = generate_token();
$id = $row["id"];
$url = generate_url("redirect", $id, $token);
$link = "<a href='" . $url . "'>reset password</a>";
$mail->isHTML(true);
//Set email format to HTML
$mail->Subject = 'Password recovery';
$mail->Body = 'Your new password : click the link below ' . $link;
$mail->AltBody = 'Your new password : click the link below ' . $link;
$mail->send();
$data = ['token' => $token, 'token_active' => 1, 'token_date' => getServerTimestamp()];
$userModel->where('id', $id)
->set($data)
->update();
echo json_encode(1); //ok msg sent with token
} catch (Exception $e) {
$ajaxresponse = $mail->ErrorInfo;
echo json_encode($ajaxresponse); //message not sent
}
} else {
echo json_encode(2); //wrong email adress
}
}
//---------------------------->->- Reset password : step 2
public function loadResetPage($id, $token)
{
$userModel = new UserModel();
$row = $userModel->find($id);
if ($row) {
if (isValidToken($row, $token)) {
$data = array('id' => $id, 'token' => $token);
echo view('resetpassword', $data); // return view => call a view , return redirect => route
// return redirect()->to('ResetPwdController');
} else {
echo "<h1>Error 1 : Bad link !</h1>";
return 0;
}
} else {
echo "<h1>Error 2 : Bad user !</h1>";
return 0;
}
}
//------------------------------ Reset password : step 3
public function updatepassword()
{
$rules = [
'password' => [
'label' => 'Password',
'rules' => 'required|min_length[4]|max_length[50]|alpha_numeric',
'errors' => [
'required' => 'password is required',
'min_length' => 'min length is 5',
'max_length' => 'max length is 50',
'alpha_numeric' => 'add alpha and numeric',
]
],
'confpwd' => [
'label' => 'Confirm Password',
'rules' => 'required|matches[password]',
'errors' => [
'required' => 'retype password',
'matches' => 'password dont matches',
],
]
];
if ($this->validate($rules)) {
$userModel = new UserModel();
$id = $this->request->getVar('id');
$token = $this->request->getVar('token');
$row = $userModel->find($id);
if ($row) {
if (isValidToken($row, $token)) {
$data = [
'password' => password_hash($this->request->getVar('password'), PASSWORD_DEFAULT),
'token_active' => 0,
'token' => '',
'token_date' => ''
];
$userModel->update($id, $data);
echo json_encode(1);
} else {
echo json_encode(2); //bad token or expired link
}
} else {
echo json_encode(3); //bad id link
}
} else {
echo json_encode($this->validator->listErrors());
}
}
3 – my custom helper
function generate_token($len = 25)
{
$dumpdata = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
$token = substr(str_shuffle($dumpdata), 0, $len);
return $token;
}
//------------------------------------------------------
function generate_password($len = 8)
{
$dumpdata = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#&$%_";
$token = substr(str_shuffle($dumpdata), 0, $len);
return $token;
}
//------------------------------------------------------
function generate_url(...$segments)
{
$url = base_url();
foreach ($segments as $seg) {
$url .= '/' . $seg;
}
return $url;
}
//------------------------------------------------------
function getServerTimestamp()
{
date_default_timezone_set('Africa/Algiers');
$stamp = date('Y-m-d H:i:s');
return $stamp;
}
//------------------------------------------------------
function isValidToken($data, $token, $period=24)
{
$date = date(getServerTimestamp());
$diff = date_diff2($data['token_date'], $date);
//print_r("Reset : {$row['token_date']}<br>Server : {$date}<br>Period : {$diff['asString']}");
$period_second = $period*60*60;
return ($data['token'] == $token &&
$data['token_active'] == 1 &&
$diff['exceeded'] > 0 &&
$diff['exceeded'] <= $period_second //validation limit $period_second = $period*60*60
);
}
//------------------------------------------------------
function date_diff2($date1, $date2)
{
$diff = strtotime($date2) - strtotime($date1);
if ($diff <= 0) {
$asString = "[<br> <b>valid :</b> 0 <br><b>Period : </b>00:00:00:00:00:00<br> Diff : </b>" . strval($diff) . "<br>]";
$result = array(
'valid' => 0,
'year' => 0,
'month' => 0,
'days' => 0,
'hours' => 0,
'minutes' => 0,
'seconds' => 0,
'exceeded' => $diff,
'asString' => $asString
);
return $result;
}
$years = floor($diff / (365 * 60 * 60 * 24));
$months = floor(($diff - $years * 365 * 60 * 60 * 24) / (30 * 60 * 60 * 24));
$days = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24) / (60 * 60 * 24));
$hours = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24 - $days * 60 * 60 * 24) / (60 * 60));
$minutes = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24 - $days * 60 * 60 * 24 - $hours * 60 * 60) / 60);
$seconds = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24 - $days * 60 * 60 * 24 - $hours * 60 * 60 - $minutes * 60));
$asString = '[ <br> <b>valid :</b> 1 <br><b>Period : </b>' .
strval($years) . ":" .
strval($months) . ":" .
strval($days) . ":" .
strval($hours) . ":" .
strval($minutes) . ":" .
strval($seconds) . "<br> <b>Diff : </b>" .
strval($diff) . "<br>]";
$result = array(
'valid' => 1,
'year' => $years,
'month' => $months,
'days' => $days,
'hours' => $hours,
'minutes' => $minutes,
'seconds' => $seconds,
'exceeded' => $diff,
'asString' => $asString
);
return $result;
}
my issue is as so i am getting an error :
when submitting data in reset form the it don’t send data to the right route and the URL in the browser is the same as the email link
help please
i do not know if it is because of echo view or my logic is wrong?