Finalize "forgot password" feature
parent
1ee795a399
commit
eda4c5a030
|
@ -38,10 +38,10 @@ function htmlToPlain($message): string {
|
||||||
return $messageNew;
|
return $messageNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMail($message, $subject, $title, $preheader): bool {
|
function sendMail($email, $message, $subject, $title, $preheader): bool {
|
||||||
include_once('../lib/phpmailer/Exception.php');
|
include_once('lib/phpmailer/Exception.php');
|
||||||
include_once('../lib/phpmailer/PHPMailer.php');
|
include_once('lib/phpmailer/PHPMailer.php');
|
||||||
include_once('../lib/phpmailer/SMTP.php');
|
include_once('lib/phpmailer/SMTP.php');
|
||||||
include_once('app/HTML.php');
|
include_once('app/HTML.php');
|
||||||
global $RUNTIME;
|
global $RUNTIME;
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
|
||||||
$mailer->Port = $RUNTIME['SMTP']['PORT'];
|
$mailer->Port = $RUNTIME['SMTP']['PORT'];
|
||||||
$mailer->Username = $RUNTIME['SMTP']['ADDRESS'];
|
$mailer->Username = $RUNTIME['SMTP']['ADDRESS'];
|
||||||
$mailer->Password = $RUNTIME['SMTP']['PASS'];
|
$mailer->Password = $RUNTIME['SMTP']['PASS'];
|
||||||
|
$mailer->SMTPAuth = true;
|
||||||
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||||
|
|
||||||
$mailer->setFrom($RUNTIME['SMTP']['ADDRESS'], $RUNTIME['SMTP']['NAME']);
|
$mailer->setFrom($RUNTIME['SMTP']['ADDRESS'], $RUNTIME['SMTP']['NAME']);
|
||||||
|
@ -61,7 +62,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
|
||||||
$mailer->isHTML(true);
|
$mailer->isHTML(true);
|
||||||
$mailer->Subject = $subject;
|
$mailer->Subject = $subject;
|
||||||
$mailHtml = new HTML();
|
$mailHtml = new HTML();
|
||||||
$mailHtml->importHTML("email.html");
|
$mailHtml->importHTML("mail.html");
|
||||||
$mailHtml->setHTMLTitle($title);
|
$mailHtml->setHTMLTitle($title);
|
||||||
$mailHtml->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
|
$mailHtml->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
|
||||||
$mailHtml->ReplaceLayoutInhalt('%%PREHEADER%%', $preheader);
|
$mailHtml->ReplaceLayoutInhalt('%%PREHEADER%%', $preheader);
|
||||||
|
|
|
@ -15,21 +15,25 @@
|
||||||
if(!$validator->isValid($_POST)) {
|
if(!$validator->isValid($_POST)) {
|
||||||
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Bitte gebe deinen Benutzernamen (Vor- und Nachname) und die dazugehörige E-Mail-Adresse ein');
|
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Bitte gebe deinen Benutzernamen (Vor- und Nachname) und die dazugehörige E-Mail-Adresse ein');
|
||||||
$HTML->ReplaceLayoutInhalt('%%MESSAGECOLOR%%', 'red');
|
$HTML->ReplaceLayoutInhalt('%%MESSAGECOLOR%%', 'red');
|
||||||
|
$HTML->build();
|
||||||
|
echo $HTML->ausgabe();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$nameParts = explode(" ", $_POST['username']);
|
$nameParts = explode(" ", $_POST['username']);
|
||||||
$email = strtolower(trim($_POST['email']));
|
$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]);
|
$getAccount->execute([trim($nameParts[0]), trim($nameParts[1]), $email]);
|
||||||
$validRequest = $getAccount->rowCount() == 1;
|
$validRequest = $getAccount->rowCount() == 1;
|
||||||
|
$uuid;
|
||||||
|
$name;
|
||||||
if($res = $getAccount->fetch()) {
|
if($res = $getAccount->fetch()) {
|
||||||
$email = $res['Email'];
|
$email = $res['Email'];
|
||||||
$uuid = $res['PrincipalID'];
|
$uuid = $res['PrincipalID'];
|
||||||
$name = $res['FirstName'].' '.$res['LastName'];
|
$name = $res['FirstName'].' '.$res['LastName'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($blockedDomains as $domain) {
|
foreach($RUNTIME['RESET_BLOCKED_DOMAINS'] as $domain) {
|
||||||
if(str_ends_with($email, $domain)) {
|
if(str_ends_with($email, $domain)) {
|
||||||
$validRequest = false;
|
$validRequest = false;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +46,7 @@
|
||||||
fastcgi_finish_request();
|
fastcgi_finish_request();
|
||||||
|
|
||||||
if($validRequest) {
|
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]);
|
$getReqTime->execute([$uuid]);
|
||||||
if(($res = $getReqTime->fetch()) && time() - $res['RequestTime'] < 900) {
|
if(($res = $getReqTime->fetch()) && time() - $res['RequestTime'] < 900) {
|
||||||
return;
|
return;
|
||||||
|
@ -50,10 +54,10 @@
|
||||||
|
|
||||||
require_once 'app/utils.php';
|
require_once 'app/utils.php';
|
||||||
$token = generateToken(32);
|
$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()]);
|
$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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
<?php
|
<?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 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 = new HTML();
|
||||||
$HTML->importHTML("error.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();
|
$HTML->build();
|
||||||
|
echo $HTML->ausgabe();
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayPage($err) {
|
function displayPage($err) {
|
||||||
|
if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
|
||||||
|
displayTokenError(TOKEN_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
$HTML = new HTML();
|
$HTML = new HTML();
|
||||||
$HTML->setHTMLTitle("");
|
$HTML->setHTMLTitle("");
|
||||||
$HTML->importHTML("reset-password.html");
|
$HTML->importHTML("reset-password.html");
|
||||||
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $err);
|
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $err);
|
||||||
|
$HTML->ReplaceLayoutInhalt('%%RESET_TOKEN%%', htmlspecialchars($_GET['token']));
|
||||||
$HTML->build();
|
$HTML->build();
|
||||||
echo $HTML->ausgabe();
|
echo $HTML->ausgabe();
|
||||||
exit();
|
exit();
|
||||||
|
@ -36,16 +44,29 @@
|
||||||
displayPage('Dein Passwort muss mindestens '.$RUNTIME['PASSWORD_MIN_LENGTH'].' Zeichen lang sein.');
|
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 = ?');
|
$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 = ?');
|
||||||
if($getUuid->rowCount() == 0) {
|
$getReq->execute([$_POST['resetToken']]);
|
||||||
displayTokenError();
|
if($getReq->rowCount() == 0) {
|
||||||
|
displayTokenError(TOKEN_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $getUuid->fetch();
|
$res = $getReq->fetch();
|
||||||
$uuid = $res['PrincipalID'];
|
|
||||||
|
if(!hash_equals($res['Token'], $_POST['resetToken'])) {
|
||||||
|
displayTokenError(TOKEN_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uuid = $res['UUID'];
|
||||||
$name = $res['FirstName'].' '.$res['LastName'];
|
$name = $res['FirstName'].' '.$res['LastName'];
|
||||||
$getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE Token = ?');
|
$getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE PrincipalID = ? AND Token = ?');
|
||||||
$getToken->execute([$_POST['resetToken']]);
|
$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));
|
$salt = bin2hex(random_bytes(16));
|
||||||
$hash = md5(md5(trim($_POST['password'])).':'.$salt);
|
$hash = md5(md5(trim($_POST['password'])).':'.$salt);
|
||||||
|
@ -57,7 +78,7 @@
|
||||||
$_SESSION['loginMessageColor'] = 'darkgreen';
|
$_SESSION['loginMessageColor'] = 'darkgreen';
|
||||||
|
|
||||||
require_once 'app/utils.php';
|
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');
|
header('Location: index.php?page=login');
|
||||||
exit();
|
exit();
|
||||||
|
@ -65,8 +86,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
displayPage('');
|
displayPage('');
|
||||||
|
|
||||||
if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
|
|
||||||
displayTokenError();
|
|
||||||
}
|
|
||||||
?>
|
?>
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="limiter">
|
<div class="limiter">
|
||||||
<div class="container-login100">
|
<div class="container-login100">
|
||||||
<div class="wrap-login100 p-t-50 p-b-90">
|
<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">
|
<span class="login100-form-title p-b-51">
|
||||||
Passwort vergessen
|
Passwort vergessen
|
||||||
</span>
|
</span>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wrap-input100 validate-input m-b-16" data-validate="Bitte gebe deinen Benutzernamen an.">
|
<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>
|
<span class="focus-input100"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width" />
|
<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" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<title></title>
|
|
||||||
<style>
|
<style>
|
||||||
img {
|
img {
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -23,17 +22,17 @@
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<span class="preheader" style="display: none">%%PREHEADER%%</span>
|
<span class="preheader" style="display: none">%%PREHEADER%%</span>
|
||||||
<div class="container" style="background-color: #afafaf">
|
<div class="container" style="background-color: #afafaf">
|
||||||
<div class="header" style="background-color: #434343; height: 128px">
|
<div class="header" style="background-color: #434343; height: 64px">
|
||||||
<img style="float: left; height: 100%" src="https://4creative.net/images/4Creative-Logo-neu.png" alt="Logo">
|
<img style="vertical-align: middle; height: 100%" src="https://4creative.net/images/4Creative-Logo-neu.png" alt="Logo">
|
||||||
<h2 style="vertical-align: middle">%%EchoTitle%%</h2>
|
<h2 style="vertical-align: middle; color: #fff; font-weight: bold; margin: 0 0 0 10px; display: inline">%%EchoTitle%%</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" style="background-color: #fff">
|
<div class="content" style="background-color: #fff; padding: 2px">
|
||||||
%%MESSAGE%%
|
%%MESSAGE%%
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="limiter">
|
<div class="limiter">
|
||||||
<div class="container-login100">
|
<div class="container-login100">
|
||||||
<div class="wrap-login100 p-t-50 p-b-90">
|
<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">
|
<span class="login100-form-title p-b-51">
|
||||||
Neues Passwort festlegen
|
Neues Passwort festlegen
|
||||||
</span>
|
</span>
|
||||||
|
|
Loading…
Reference in New Issue