diff --git a/Controller/AuthController.php b/Controller/AuthController.php new file mode 100644 index 0000000..51de72b --- /dev/null +++ b/Controller/AuthController.php @@ -0,0 +1,170 @@ +model = new AuthModel(); + $this->view = $view; + } + + public function showAuthForm() + { + $this->view->setVars([ + 'labels' => [ + "email" => "E-Mail-Adresse", + "password" => "Passwort", + "password_repeat" => "Passwort wiederholen", + "old_password" => "Altes Passwort" + ], + 'errors' => $_SESSION['auth_errors'] ?? [], + 'validData' => $_SESSION['auth_validData'] ?? [] + ]); + unset($_SESSION['auth_errors'], $_SESSION['auth_validData']); + $this->view->render('auth/form'); + } + + public function login() { + $email = $_POST['email']; + $password = $_POST['password']; + + $result = $this->model->login($email, $password); + + if ($result === true) { + $_SESSION['user'] = $email; + + $this->view->setVars([ + 'loginSuccess' => true, + 'email' => $email + ]); + } else { + $this->view->setVars([ + 'errors' => ['login' => is_string($result) ? $result : "Login fehlgeschlagen."], + 'validData' => ['email' => $email], + 'loginSuccess' => false + ]); + } + } + + public function register() { + $data = [ + 'vorname' => $_POST['vorname'] ?? '', + 'nachname' => $_POST['nachname'] ?? '', + 'straße' => $_POST['straße'] ?? '', + 'hausnr' => $_POST['hausnr'] ?? '', + 'postleitzahl' => $_POST['postleitzahl'] ?? '', + 'ort' => $_POST['ort'] ?? '', + 'land' => $_POST['land'] ?? '', + 'tel' => $_POST['tel'] ?? '', + 'email' => $_POST['email'] ?? '', + 'password' => $_POST['password'] ?? '', + 'password_repeat' => $_POST['password_repeat'] ?? '', + 'isAdmin' => $_POST['isAdmin'] ?? false, + ]; + + $errors = []; + + if (!$this->model->checkDoublePw($data['password'], $data['password_repeat'])) { + $errors['password'] = "Passwörter stimmen nicht überein."; + } + + if ($this->pwRequirementCheck($data['password'])) { + $errors + } + + if (empty($errors)) { + $result = $this->model->register($data); + + if ($result === true) { + $this->view->setVars([ + 'success' => "Registrierung war erfolgreich." + ]); + } else { + $errors['register'] = is_string($result) ? $result : "Registrierung fehlgeschlagen."; + } + } + + $this->view->setVars([ + 'errors' => $errors, + 'validData' => $data + ]); + } + + private function pwRequirementCheck($password){ + $error = []; + + if(strlen($password) <= 8) + $error[] = "min 8 Charackter"; + if(!preg_match("/[A-Z]/", $password)) + $error[] = "min one large Character"; + if(!preg_match("/[a-z]/", $password)) + $error[] = "min one small charakter"; + if(!preg_match("/[0-9]/", $password)) + $error[] = "min one number"; + if(!preg_match("[^a-zA-Z0-9\s]", $password)); + $error[] = "min one special character"; + + if(empty($error)) + return true; + else + return $error; + } + + public function forgotPassword() { + $email = $_POST['email'] ?? ''; + if (empty($email)) { + $_SESSION['auth_errors']['email'] = "Bitte E-Mail-Adresse angeben."; + header("Location: /?controller=Auth&do=showAuthForm"); + exit; + } + $this->model->pwForgot($email); + header("Location: /?controller=Auth&do=showConfirmation&msg=pwforgot"); + exit; + } + + public function changePassword() + { + $email = $_POST['email'] ?? ''; + $oldpw = $_POST['old_password'] ?? ''; + $newpw = $_POST['password'] ?? ''; + $repeat = $_POST['password_repeat'] ?? ''; + + if (!$this->model->checkDoublePw($newpw, $repeat)) { + $_SESSION['auth_errors']['password'] = "Neue Passwörter stimmen nicht überein."; + header("Location: /?controller=Auth&do=showAuthForm"); + exit; + } + + $result = $this->model->updatePassword($email, $oldpw, $newpw); + + if ($result === true) { + header("Location: /?controller=Auth&do=showConfirmation&msg=pwchange"); + exit; + } else { + $_SESSION['auth_errors']['password'] = is_string($result) ? $result : "Fehler beim Aktualisieren des Passworts."; + header("Location: /?controller=Auth&do=showAuthForm"); + exit; + } + } + + public function showConfirmation() + { + $messages = [ + 'login' => "Login erfolgreich.", + 'register' => "Registrierung erfolgreich.", + 'pwforgot' => "Ein temporäres Passwort wurde an Ihre E-Mail gesendet.", + 'pwchange' => "Passwort erfolgreich geändert." + ]; + $msgKey = $_GET['msg'] ?? ''; + $message = $messages[$msgKey] ?? "Aktion erfolgreich."; + $this->view->setVars(['message' => $message]); + $this->view->render('auth/confirmation'); + } +} \ No newline at end of file diff --git a/Model/AuthModel.php b/Model/AuthModel.php new file mode 100644 index 0000000..aac8b39 --- /dev/null +++ b/Model/AuthModel.php @@ -0,0 +1,216 @@ +linkDB(); + $sql = "SELECT email, password, validUntil FROM user WHERE email = :email"; + $params = [":email" => $email]; + + try { + $sth = $pdo->prepare($sql); + $sth->execute($params); + $user = $sth->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + new \Blog\Library\ErrorMsg("Fehler beim Abrufen der Benutzerdaten.", $e); + return "Interner Datenbankfehler."; // Nur für Debug sichtbar machen, sonst besser allgemein halten + } + + if (!$user) { + return "Benutzer mit dieser E-Mail wurde nicht gefunden."; + } + + if (!password_verify($password, $user['password'])) { + return "Das eingegebene Passwort ist falsch."; + } + + try { + $now = new DateTime(); + $validUntil = new DateTime($user['validUntil']); + + if ($now > $validUntil) { + return "Ihr Passwort ist abgelaufen. Bitte setzen Sie ein neues über \"Passwort vergessen\"."; + } + } catch (\Exception $e) { + new \Blog\Library\ErrorMsg("Fehler beim Verarbeiten des Gültigkeitsdatums.", $e); + return "Fehler bei der Passwortprüfung."; + } + + return true; + } + + public function register($data) + { + $rtn = $this->pwRequirementCheck($data['password']); + if ($rtn !== true) { + return $rtn; + } + + if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { + return "Bitte geben Sie eine gültige E-Mail ein."; + } + + $requiredFields = [ + 'email', 'password', 'straße', 'hausnr', 'ort', 'postleitzahl', + 'land', 'vorname', 'nachname', 'tel' + ]; + + foreach ($requiredFields as $field) { + if (empty($data[$field])) { + return "Bitte füllen Sie alle Felder aus."; + } + } + + if ($this->userExistsByEmail($data['email'])) { + return "Ein Account mit dieser E-Mail existiert bereits."; + } + + $hashedPassword = password_hash($data['password'], PASSWORD_DEFAULT); + + $sql = "INSERT INTO user (email, password, straße, hausnr, ort, postleitzahl, land,vorname, nachname, tel, isAdmin) + VALUES (:email, :password, :straße, :hausnr, :ort, :postleitzahl, :land,:vorname, :nachname, :tel, :isAdmin)"; + + $params = [ + ':email' => $data['email'], + ':password' => $hashedPassword, + ':straße' => $data['straße'], + ':hausnr' => $data['hausnr'], + ':ort' => $data['ort'], + ':postleitzahl'=> $data['postleitzahl'], + ':land'=> $data['land'], + ':vorname' => $data['vorname'], + ':nachname'=> $data['nachname'], + ':tel' => $data['tel'], + ':isAdmin' => $data['isAdmin'] ? 1 : 0, + ]; + + try { + $pdo = $this->linkDB(); + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + return true; + } catch (PDOException $e) { + new \Blog\Library\ErrorMsg("Fehler beim Schreiben der Daten.", $e); + return false; + } + } + + private function userExistsByEmail($email) { + try { + $pdo = $this->linkDB(); + + $sql = "SELECT userid FROM user WHERE email = :email"; + $params = [':email' => $email]; + + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + + return (bool) $stmt->fetch(); + } catch (\PDOException $e) { + new \Blog\Library\ErrorMsg("Fehler bei der E-Mail-Prüfung", $e); + return false; + } + } + + public function pwForgot($email){ + $randomPw = bin2hex(random_bytes(12 / 2)); + $hashedPassword = password_hash($randomPw, PASSWORD_DEFAULT); + + $this->forgottenPwUpdate($email, $hashedPassword); + + $betreff = "Passwort zurücksetzen bei bibArts"; + $nachricht = "Hallo,\n\nhier ihr temporäres Passwort:\n\n $randomPw \n\n Bitte beachten Sie, dass das Passwort nur 2 stunden Gülltig ist. \nViele Grüße,\nbibArts Team"; + + $header = "From: noreply@edu.bib.de\r\n"; + $header .= "Content-Type: text/plain; charset=UTF-8\r\n"; + + $maxTries = 5; + $try = 0; + $success = false; + + while ($try < $maxTries && !$success) { + $erfolg = mail($email, $betreff, $nachricht, $header); + $try++; + if (!$erfolg) { + error_log("Mailversuch $try an $email fehlgeschlagen."); + sleep(1); + } + } + } + + private function forgottenPwUpdate($email, $hashedPassword) + { + try{ + $pdo = $this->linkDB(); + + $sqlCheck = "SELECT COUNT(*) FROM user WHERE email = :email"; + $stmt = $pdo->prepare($sqlCheck); + $stmt->execute([':email' => $email]); + if ($stmt->fetchColumn() == 0) { + return false; + } + + $validUntil = (new DateTime())->add(new DateInterval('PT2H'))->format('Y-m-d H:i:s'); + + + $sql = "UPDATE user + SET password = :password, validUntil = :validUntil + WHERE email = :email"; + + $stmt = $pdo->prepare($sql); + return $stmt->execute([ + ':email' => $email, + ':password' => $hashedPassword, + ':validUntil' => $validUntil + ]); + } catch (PDOException $e) { + new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren der Daten.", $e); + die; + return false; + } + } + + public function updatePassword($email, $oldpw, $newpw){ + if(!$this->login($email, $oldpw)) { + return false; + } + + $requiredFields = [$email, $oldpw, $newpw]; + foreach ($requiredFields as $field) { + if (empty($field)) { + return "Bitte füllen Sie alle Felder aus"; + } + } + $hashedPassword = password_hash($newpw, PASSWORD_DEFAULT); + + $sql = "INSERT INTO user (email, password) + VALUES (:email, :password)"; + + try{ + $pdo = $this->linkDB(); + $stmt = $pdo->prepare($sql); + return $stmt->execute([ + ':email' => $email, + ':password' => $hashedPassword, + ]); + } catch (PDOException $e) { + new \Blog\Library\ErrorMsg("Fehler beim Schreiben der Daten.", $e); + die; + } + } + + public function checkDoublePw($password1, $password2){ + if($password1 === $password2){ + return true; + } + else + return false; + } +} diff --git a/Views/Auth/login.phtml b/Views/Auth/login.phtml new file mode 100644 index 0000000..685fe4f --- /dev/null +++ b/Views/Auth/login.phtml @@ -0,0 +1,33 @@ + + + +
+ +
+ + +
+

Login für Benutzer erfolgreich

+ Weiter +
+ + + +
+ + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/Views/Auth/register.phtml b/Views/Auth/register.phtml new file mode 100644 index 0000000..4d2f91c --- /dev/null +++ b/Views/Auth/register.phtml @@ -0,0 +1,61 @@ + + + +
+

+
+ + + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/bibarts.sql b/bibarts.sql index 26761c3..b376265 100644 --- a/bibarts.sql +++ b/bibarts.sql @@ -108,4 +108,37 @@ VALUES INSERT INTO News (name, beschreibung, datum) VALUES ('Neuer Standort eröffnet', 'Unsere Galerie in Köln ist jetzt geöffnet!', '2025-06-01'), - ('Frühbucher-Rabatt', 'Sichern Sie sich jetzt 15% Rabatt auf unsere Sommerausstellung.', '2025-05-20'); \ No newline at end of file + ('Frühbucher-Rabatt', 'Sichern Sie sich jetzt 15% Rabatt auf unsere Sommerausstellung.', '2025-05-20'); + +--Änderungen: + +ALTER TABLE austellung + ADD preis decimal NOT NULL + +ALTER TABLE ticket + DROP COLUMN preis + + +ALTER TABLE user + MODIFY COLUMN userid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE ticket + MODIFY COLUMN ticketid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE standort + MODIFY COLUMN standortid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE news + MODIFY COLUMN newsid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE gutschein + MODIFY COLUMN gutscheinid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE ausstellung + MODIFY COLUMN austellungid INT NOT NULL AUTO_INCREMENT; + +ALTER TABLE user + MODIFY COLUMN isAdmin BOOLEAN DEFAULT FALSE; + +ALTER TABLE user + ADD validUntil DATETIME NOT NULL DEFAULT '3025-01-01 00:00:00'; \ No newline at end of file