1
0
Fork 0

Finalize "forgot password" feature

master
Anonymous Contributor 2023-08-23 18:16:36 +02:00
parent 1ee795a399
commit eda4c5a030
6 changed files with 66 additions and 45 deletions

View File

@ -38,10 +38,10 @@ function htmlToPlain($message): string {
return $messageNew;
}
function sendMail($message, $subject, $title, $preheader): bool {
include_once('../lib/phpmailer/Exception.php');
include_once('../lib/phpmailer/PHPMailer.php');
include_once('../lib/phpmailer/SMTP.php');
function sendMail($email, $message, $subject, $title, $preheader): bool {
include_once('lib/phpmailer/Exception.php');
include_once('lib/phpmailer/PHPMailer.php');
include_once('lib/phpmailer/SMTP.php');
include_once('app/HTML.php');
global $RUNTIME;
@ -53,6 +53,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
$mailer->Port = $RUNTIME['SMTP']['PORT'];
$mailer->Username = $RUNTIME['SMTP']['ADDRESS'];
$mailer->Password = $RUNTIME['SMTP']['PASS'];
$mailer->SMTPAuth = true;
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mailer->setFrom($RUNTIME['SMTP']['ADDRESS'], $RUNTIME['SMTP']['NAME']);
@ -61,7 +62,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
$mailer->isHTML(true);
$mailer->Subject = $subject;
$mailHtml = new HTML();
$mailHtml->importHTML("email.html");
$mailHtml->importHTML("mail.html");
$mailHtml->setHTMLTitle($title);
$mailHtml->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
$mailHtml->ReplaceLayoutInhalt('%%PREHEADER%%', $preheader);

View File

@ -15,21 +15,25 @@
if(!$validator->isValid($_POST)) {
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Bitte gebe deinen Benutzernamen (Vor- und Nachname) und die dazugehörige E-Mail-Adresse ein');
$HTML->ReplaceLayoutInhalt('%%MESSAGECOLOR%%', 'red');
$HTML->build();
echo $HTML->ausgabe();
}
else {
$nameParts = explode(" ", $_POST['username']);
$email = strtolower(trim($_POST['email']));
$getAccount = $RUNTIME['pdo']->prepare('SELECT Email,FirstName,LastName,PrincipalID FROM UserAccounts WHERE FirstName = ? AND LastName = ? AND Email = ?');
$getAccount = $RUNTIME['PDO']->prepare('SELECT Email,FirstName,LastName,PrincipalID FROM UserAccounts WHERE FirstName = ? AND LastName = ? AND Email = ?');
$getAccount->execute([trim($nameParts[0]), trim($nameParts[1]), $email]);
$validRequest = $getAccount->rowCount() == 1;
$uuid;
$name;
if($res = $getAccount->fetch()) {
$email = $res['Email'];
$uuid = $res['PrincipalID'];
$name = $res['FirstName'].' '.$res['LastName'];
}
foreach($blockedDomains as $domain) {
foreach($RUNTIME['RESET_BLOCKED_DOMAINS'] as $domain) {
if(str_ends_with($email, $domain)) {
$validRequest = false;
}
@ -42,7 +46,7 @@
fastcgi_finish_request();
if($validRequest) {
$getReqTime = $RUNTIME['pdo']->prepare('SELECT RequestTime FROM PasswordResetTokens WHERE PrincipalID=?');
$getReqTime = $RUNTIME['PDO']->prepare('SELECT RequestTime FROM PasswordResetTokens WHERE PrincipalID=?');
$getReqTime->execute([$uuid]);
if(($res = $getReqTime->fetch()) && time() - $res['RequestTime'] < 900) {
return;
@ -50,10 +54,10 @@
require_once 'app/utils.php';
$token = generateToken(32);
$setToken = $RUNTIME['pdo']->prepare('REPLACE INTO PasswordResetTokens(PrincipalID,Token,RequestTime) VALUES(?,?,?)');
$setToken = $RUNTIME['PDO']->prepare('REPLACE INTO PasswordResetTokens(PrincipalID,Token,RequestTime) VALUES(?,?,?)');
$setToken->execute([$uuid, $token, time()]);
sendMail(str_replace('%%NAME%%', $name, str_replace('%%RESET_LINK%%', 'https://'.$RUNTIME['DOMAIN'].'/index.php?page=reset-password&token='.$token, MESSAGE)), "Zurücksetzung des Passworts für ".$name, 'Dein Passwort zurücksetzen', 'Folge diesen Anweisungen, um ein neues Passwort für deinen 4Creative-Account festzulegen');
sendMail($email, str_replace('%%NAME%%', $name, str_replace('%%RESET_LINK%%', 'https://'.$RUNTIME['DOMAIN'].'/index.php?page=reset-password&token='.$token, MESSAGE)), "Zurücksetzung des Passworts für ".$name, 'Dein Passwort zurücksetzen', 'Folge diesen Anweisungen, um ein neues Passwort für deinen 4Creative-Account festzulegen');
}
}
}

View File

@ -1,19 +1,27 @@
<?php
const MESSAGE = 'Hallo %%NAME%%,<br/><br/>das Passwort für deinen 4Creative-Account wurde soeben über die Funktion "Passwort vergessen" geändert.<br/><br/>Solltest du diese Änderung nicht selbst durchgeführt haben, wende dich bitte umgehend per E-Mail (info@4creative.net) oder Discord (@ikeytan) an uns.';
const TOKEN_INVALID = 'Dieser Link zur Passwortzurücksetzung ist nicht gültig. Bitte klicke oder kopiere den Link aus der E-Mail, die du erhalten hast.';
const TOKEN_EXPIRED = 'Dein Link zur Passwortzurücksetzung ist abgelaufen. Klicke <a href="index.php?page=forgot">hier</a>, um eine neue Anfrage zu senden.';
function displayTokenError() {
function displayTokenError($message) {
$HTML = new HTML();
$HTML->importHTML("error.html");
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Dieser Link zur Passwortzurücksetzung ist nicht gültig. Bitte klicke oder kopiere den Link aus der E-Mail, die du erhalten hast.');
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
$HTML->build();
echo $HTML->ausgabe();
exit();
}
function displayPage($err) {
if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
displayTokenError(TOKEN_INVALID);
}
$HTML = new HTML();
$HTML->setHTMLTitle("");
$HTML->importHTML("reset-password.html");
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $err);
$HTML->ReplaceLayoutInhalt('%%RESET_TOKEN%%', htmlspecialchars($_GET['token']));
$HTML->build();
echo $HTML->ausgabe();
exit();
@ -36,16 +44,29 @@
displayPage('Dein Passwort muss mindestens '.$RUNTIME['PASSWORD_MIN_LENGTH'].' Zeichen lang sein.');
}
$getUuid = $RUNTIME['PDO']->prepare('SELECT PrincipalID,FirstName,LastName FROM PasswordResetTokens JOIN UserAccounts ON PasswordResetTokens.PrincipalID = PasswordResetTokens.PrincipalID WHERE Token = ?');
if($getUuid->rowCount() == 0) {
displayTokenError();
$getReq = $RUNTIME['PDO']->prepare('SELECT UserAccounts.PrincipalID AS UUID,FirstName,LastName,Email,Token,RequestTime FROM PasswordResetTokens JOIN UserAccounts ON UserAccounts.PrincipalID = PasswordResetTokens.PrincipalID WHERE Token = ?');
$getReq->execute([$_POST['resetToken']]);
if($getReq->rowCount() == 0) {
displayTokenError(TOKEN_INVALID);
}
$res = $getUuid->fetch();
$uuid = $res['PrincipalID'];
$res = $getReq->fetch();
if(!hash_equals($res['Token'], $_POST['resetToken'])) {
displayTokenError(TOKEN_INVALID);
}
$uuid = $res['UUID'];
$name = $res['FirstName'].' '.$res['LastName'];
$getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE Token = ?');
$getToken->execute([$_POST['resetToken']]);
$getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE PrincipalID = ? AND Token = ?');
$getToken->execute([$uuid, $_POST['resetToken']]);
if($getToken->rowCount() == 0) {
displayTokenError(TOKEN_INVALID);
}
if(time() - $res['RequestTime'] > 86400) {
displayTokenError(TOKEN_EXPIRED);
}
$salt = bin2hex(random_bytes(16));
$hash = md5(md5(trim($_POST['password'])).':'.$salt);
@ -57,7 +78,7 @@
$_SESSION['loginMessageColor'] = 'darkgreen';
require_once 'app/utils.php';
sendMail(str_replace('%%NAME%%', $name, MESSAGE), 'Passwort für '.$name.' zurückgesetzt', 'Passwort geändert', 'Das Passwort für deinen 4Creative-Account wurde soeben zurückgesetzt');
sendMail($res['Email'], str_replace('%%NAME%%', $name, MESSAGE), 'Passwort für '.$name.' zurückgesetzt', 'Passwort geändert', 'Das Passwort für deinen 4Creative-Account wurde soeben zurückgesetzt');
header('Location: index.php?page=login');
exit();
@ -65,8 +86,4 @@
}
displayPage('');
if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
displayTokenError();
}
?>

View File

@ -22,7 +22,7 @@
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100 p-t-50 p-b-90">
<form class="login100-form validate-form flex-sb flex-w" action="index.php?page=forgot-request" method="post">
<form class="login100-form validate-form flex-sb flex-w" action="index.php?page=forgot" method="post">
<span class="login100-form-title p-b-51">
Passwort vergessen
</span>
@ -32,7 +32,7 @@
</div>
<div class="wrap-input100 validate-input m-b-16" data-validate="Bitte gebe deinen Benutzernamen an.">
<input class="input100" type="text" name="username" value="%%LASTUSERNAME%%" placeholder="Benutzername">
<input class="input100" type="text" name="username" placeholder="Benutzername">
<span class="focus-input100"></span>
</div>

View File

@ -1,9 +1,8 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<!DOCTYPE html>
<html lang="de">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
img {
border: none;
@ -23,17 +22,17 @@
-webkit-text-size-adjust: 100%;
}
</style>
</head>
<body>
</head>
<body>
<span class="preheader" style="display: none">%%PREHEADER%%</span>
<div class="container" style="background-color: #afafaf">
<div class="header" style="background-color: #434343; height: 128px">
<img style="float: left; height: 100%" src="https://4creative.net/images/4Creative-Logo-neu.png" alt="Logo">
<h2 style="vertical-align: middle">%%EchoTitle%%</h2>
<div class="header" style="background-color: #434343; height: 64px">
<img style="vertical-align: middle; height: 100%" src="https://4creative.net/images/4Creative-Logo-neu.png" alt="Logo">
<h2 style="vertical-align: middle; color: #fff; font-weight: bold; margin: 0 0 0 10px; display: inline">%%EchoTitle%%</h2>
</div>
<div class="content" style="background-color: #fff">
<div class="content" style="background-color: #fff; padding: 2px">
%%MESSAGE%%
</div>
</div>
</body>
</body>
</html>

View File

@ -22,7 +22,7 @@
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100 p-t-50 p-b-90">
<form class="login100-form validate-form flex-sb flex-w" action="index.php?page=forgot-request" method="post">
<form class="login100-form validate-form flex-sb flex-w" action="index.php?page=reset-password&token=%%RESET_TOKEN%%" method="post">
<span class="login100-form-title p-b-51">
Neues Passwort festlegen
</span>