Skip to content

Commit

Permalink
Merge pull request #26 from TEAM-7-SAD/SPD-78-SPD-79
Browse files Browse the repository at this point in the history
Spd 78 spd 79
  • Loading branch information
Carl-Tabuso authored May 26, 2024
2 parents 8620adc + 8c55e77 commit 0224ad8
Show file tree
Hide file tree
Showing 9 changed files with 716 additions and 163 deletions.
2 changes: 1 addition & 1 deletion src/includes/mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
$mail = new PHPMailer(true);

// Enable verbose debug output. Uncomment if needed—debugging purposes
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// $mail->SMTPDebug = SMTP::DEBUG_SERVER;

// Send using SMTP
$mail->isSMTP();
Expand Down
115 changes: 90 additions & 25 deletions src/includes/process-reset-password.php
Original file line number Diff line number Diff line change
@@ -1,37 +1,102 @@
<?php
include_once str_replace('/', DIRECTORY_SEPARATOR, 'file-utilities.php');
require_once FileUtils::normalizeFilePath('db-connector.php');
require_once FileUtils::normalizeFilePath('session-handler.php');
include_once FileUtils::normalizeFilePath('error-reporting.php');
include_once FileUtils::normalizeFilePath('default-timezone.php');

$token = $_POST["token"];
$token_hash = hash("sha256", $token);
$response = ['success' => false, 'message' => ''];

$sql = "SELECT * FROM user WHERE reset_token_hash = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("s", $token_hash);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if($_SERVER["REQUEST_METHOD"] === "POST") {

if ($row === NULL) {
$_SESSION['error_message'] = 'Your password reset link was not found.';
header("Location: ../login.php");
exit();
}
$token = $_POST['token'] ?? NULL;
$password = $_POST['newPassword'] ?? NULL;
$password_confirmation = $_POST['confirmPassword'] ?? NULL;

if (strtotime($row["reset_token_expires_at"]) <= time()) {
$_SESSION['error_message'] = 'Your password reset link has expired.';
header("Location: ../login.php");
exit();
}
if(empty($password) || empty($password_confirmation)) {
$response['message'] = 'Password input fields cannot be empty.';
echo json_encode($response);
exit();
}

if($password !== $password_confirmation) {
$response['message'] = 'Passwords do not match.';
echo json_encode($response);
exit();
}

$password_hash = password_hash($_POST["password"], PASSWORD_DEFAULT);
$validate_new_password = newPasswordValidation($password);

$sql = "UPDATE user SET password = ?, reset_token_hash = NULL, reset_token_expires_at = NULL WHERE id = ?";
if($validate_new_password) {
$response['message'] = $validate_new_password;
echo json_encode($response);
exit();
}

$token_hash = hash('sha256', $token);

$stmt = $db->prepare($sql);
$stmt->bind_param("ss", $password_hash, $row["id"]);
$stmt->execute();
$sql = "SELECT email, reset_token_hash, reset_token_expires_at FROM user WHERE reset_token_hash = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("s", $token_hash);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();

if (!$row) {
$_SESSION['error_message'] = 'Your password reset link was not found.';
header("Location: ../login.php");
exit();
}

$expiry_time = strtotime($row["reset_token_expires_at"]);
$current_time = time();

if ($expiry_time <= $current_time) {
$_SESSION['error_message'] = 'Your password reset link has expired.';
header("Location: ../login.php");
exit();
}

$new_password = password_hash($password, PASSWORD_DEFAULT);

$sql = "UPDATE user SET password = ?, reset_token_hash = NULL, reset_token_expires_at = NULL WHERE email = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param('ss', $new_password, $row['email']);
$success = $stmt->execute();

if($success) {
$response['success'] = true;
$response['message'] = 'Password reset successful.';
echo json_encode($response);
exit();
}
else {
$response['message'] = "Failed to reset your password. Please try again.";
echo json_encode($response);
exit();
}
exit();
}

header("Location: ../login.php");
exit();
// Validate new password
function newPasswordValidation($password) {
if (strlen($password) < 8 || strlen($password) > 20) {
return "Your password must be between 8 and 20 characters long.";
}
if (!preg_match("/\d/", $password)) {
return "Your password must contain at least 1 number.";
}
if (!preg_match("/[A-Z]/", $password)) {
return "Your password must contain at least 1 uppercase letter.";
}
if (!preg_match("/[a-z]/", $password)) {
return "Your password must contain at least 1 lowercase letter.";
}
if (!preg_match("/[\W_]/", $password)) {
return "Your password must contain at least 1 special character.";
}
if (preg_match("/\s/", $password)) {
return "Your password must not contain any spaces.";
}
return "";
}
112 changes: 62 additions & 50 deletions src/includes/send-password-reset.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,66 +5,78 @@
include_once FileUtils::normalizeFilePath('error-reporting.php');
include_once FileUtils::normalizeFilePath('default-timezone.php');

if(!isset($_POST['send-email-btn'])) {
$_SESSION['error_message'] = 'Something went wrong.';
header("Location: ../login.php");
exit();
}

$email = $_POST["email"];
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$_SESSION['error_message'] = 'Please provide a valid email';
header("Location: ../login.php");
exit();
}

// Check if email exists
$sql = "SELECT email FROM user WHERE email = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param('s', $email);
$stmt->execute();
$row = $stmt->get_result();

if($row->num_rows === 0) {
$_SESSION['error_message'] = 'User with this email does not exist.';
header("Location: ../login.php");
exit();
}
$response = ['success' => false, 'message' => 'An error occurred'];

if($_SERVER["REQUEST_METHOD"] === "POST") {

$token = bin2hex(random_bytes(16));
$token_hash = hash("sha256", $token);
$expiry = date("Y-m-d H:i:s", time() + 60 * 30);
$email = $_POST["email"] ?? NULL;

$sql = "UPDATE user SET reset_token_hash = ?, reset_token_expires_at = ? WHERE email = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("sss", $token_hash, $expiry, $email);
$stmt->execute();
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response['message'] = 'Please provide a valid email address';
echo json_encode($response);
exit();
}

if ($db->affected_rows) {
// Check if email exists
$sql = "SELECT email FROM user WHERE BINARY email = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();

if ($result->num_rows === 0) {
$response['message'] = 'User with this email does not exist.';
echo json_encode($response);
exit();
}

$mail = require __DIR__ . "/mailer.php";
$token = bin2hex(random_bytes(16));
$token_hash = hash("sha256", $token);
$expiry = date("Y-m-d H:i:s", time() + 60 * 30);

$sql = "UPDATE user SET reset_token_hash = ?, reset_token_expires_at = ? WHERE email = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("sss", $token_hash, $expiry, $email);
$stmt->execute();

if ($stmt->affected_rows > 0) {
$subject = "Password Reset";
$body = <<<END
Click <a href="http://localhost/SweetAvenuePOS/src/reset-password.php?token=$token">here</a>
to reset your password.
END;

if (sendEmail($email, $subject, $body)) {
$response['success'] = true;
$response['message'] = 'Password reset link sent successfully.';
echo json_encode($response);
} else {
$response['message'] = 'Failed to send password reset link. Please try again.';
echo json_encode($response);
exit();
}
}
else {
$response['message'] = 'Failed to generate password reset link. Please try again.';
echo json_encode($response);
exit();
}
}

$mail->setFrom("[email protected]");
$mail->addAddress($email);
$mail->Subject = "Password Reset";
$mail->Body = <<<END

Click <a href="http://localhost/SweetAvenuePOS/src/reset-password.php?token=$token">here</a>
to reset your password.
function sendEmail($recipientEmail, $subject, $body) {

END;
$mail = require FileUtils::normalizeFilePath(__DIR__ . '/mailer.php');

try {

$mail->setFrom('[email protected]', 'Sweet Avenue');
$mail->addAddress($recipientEmail);
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();

return true;
} catch (Exception $e) {

echo "Message could not be sent. Mailer error: {$mail->ErrorInfo}";

return false;
}

}
header("Location: ../login.php");
exit();
}
106 changes: 98 additions & 8 deletions src/javascript/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,101 @@ function avoidSpace(event) {
}

// Toggle show password
function myFunction() {
var x = document.getElementById("password");
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
}
function togglePassword() {
const passwordInput = document.getElementById("password");
const isPassword = passwordInput.type === "password";
passwordInput.type = isPassword ? "text" : "password";
}

document.addEventListener("DOMContentLoaded", function () {
const sendButton = document.querySelector("#sendEmailBtn");
const emailInput = document.querySelector("#email");

// Initially disable the Send button
sendButton.disabled = true;

const validateEmail = () => {
const email = emailInput.value;
// Email format validation
const isValid = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(
email
);

if (!isValid) {
emailInput.classList.add("is-invalid");
emailInput.classList.remove("was-validated");
emailInput.classList.remove("is-valid");
document.querySelector("#email-error").textContent =
"Please provide a valid email address.";
document.querySelector("#email-valid").textContent = "";
} else {
emailInput.classList.remove("is-invalid");
emailInput.classList.add("is-valid");
emailInput.classList.add("was-validated");
document.querySelector("#email-error").textContent = "";
document.querySelector("#email-valid").textContent = "Looks right!";
}

sendButton.disabled = !isValid;
};

// Validate the email input on input and change events
emailInput.addEventListener("input", validateEmail);
emailInput.addEventListener("change", validateEmail);

// Password Reset Link
$("#sendEmailBtn").click(function (event) {
event.preventDefault();
const email = $("#email").val();
if (!/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(email)) {
// Basic email format validation
const emailError = document.querySelector("#email-error");
emailError.textContent = "Please provide a valid email address.";
emailInput.classList.add("is-invalid");
return;
}

// Disable the button while the request is being processed
sendButton.disabled = true;
sendButton.innerHTML = `<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Sending...`;

$.ajax({
url: "includes/send-password-reset.php",
type: "POST",
data: { email: email },
dataType: "json",
success: function (response) {
if (response.success) {
$("#forgotPasswordModal").hide();
Swal.fire({
title: "Success!",
text: response.message,
icon: "success",
confirmButtonColor: "#C57C47",
confirmButtonText: "Got it!",
}).then(() => {
location.reload();
});
} else {
const emailError = document.querySelector("#email-error");
emailError.textContent = response.message;
emailInput.classList.remove("is-valid");
emailInput.classList.add("is-invalid");
}
},
error: function (xhr, status, error) {
console.error(xhr.responseText);
},
complete: function () {
// Reset the button content and enable it after the request is complete (whether success or error)
sendButton.innerHTML = "Send Link";
sendButton.disabled = false;
},
});
});

// Disable the "Send" button after it's clicked
$("#sendEmailBtn").click(function () {
$(this).prop("disabled", true);
});
});
Loading

0 comments on commit 0224ad8

Please sign in to comment.