Finalize "forgot password" feature
							parent
							
								
									1ee795a399
								
							
						
					
					
						commit
						eda4c5a030
					
				|  | @ -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); | ||||
|  |  | |||
|  | @ -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'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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(); | ||||
|     } | ||||
| ?>
 | ||||
|  | @ -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> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| <!doctype html> | ||||
| <html> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title></title> | ||||
|       <style> | ||||
| <!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; | ||||
|             -ms-interpolation-mode: bicubic; | ||||
|  | @ -22,18 +21,18 @@ | |||
|             -ms-text-size-adjust: 100%; | ||||
|             -webkit-text-size-adjust: 100%; | ||||
|         } | ||||
|         </style> | ||||
|    </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> | ||||
|     </style> | ||||
| </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: 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> | ||||
|     </div> | ||||
| </body> | ||||
| </html> | ||||
|  | @ -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> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Anonymous Contributor
						Anonymous Contributor