Compare commits

...

10 Commits

Author SHA1 Message Date
ce23d839a3 Register und login gefixt 2025-06-30 09:56:52 +02:00
36d6364cd0 Auth angepasst 2025-06-27 10:24:21 +02:00
Max538
5477e7fdd8 fixed sql 2025-06-23 14:23:00 +02:00
Max538
db526e5bb2 implemented Controller logic 2025-06-23 14:22:43 +02:00
Max538
dd6e98fe28 implemented update pw function 2025-06-23 14:14:25 +02:00
Max538
5965e1df81 implemented input validation for register function 2025-06-23 10:35:55 +02:00
Max538
8d4376d313 fixed login function 2025-06-23 10:17:17 +02:00
Max538
49a8f6a1dc added database sql skript with changes 2025-06-16 15:12:51 +02:00
Max538
78e1e72eba implemented authmodel 2025-06-16 15:12:28 +02:00
Max538
4fa775f326 implemented authcontroller logic 2025-06-16 15:12:13 +02:00
5 changed files with 618 additions and 0 deletions

View File

@ -0,0 +1,170 @@
<?php
namespace Blog\Controller;
use Blog\Model\AuthModel;
class AuthController
{
private $model;
private $view;
public function __construct($view)
{
$this->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');
}
}

216
Model/AuthModel.php Normal file
View File

@ -0,0 +1,216 @@
<?php
namespace Blog\Model;
use DateTime;
use PDO;
use PDOException;
class AuthModel extends Database
{
public function login(string $email, string $password)
{
$pdo = $this->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;
}
}

33
Views/Auth/login.phtml Normal file
View File

@ -0,0 +1,33 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<?php if (!empty($errors['login'])): ?>
<div class="error">
<?php echo htmlspecialchars($errors['login']); ?>
</div>
<?php elseif (!empty($loginSuccess)): ?>
<div class="msg">
<p>Login für Benutzer <?php echo htmlspecialchars($_SESSION["user"]); ?> erfolgreich</p>
<a href="?controller=Welcome&do=showWelcome">Weiter</a>
</div>
<?php else: ?>
<!-- Formular anzeigen -->
<form method="post">
<input type="hidden" name="controller" value="Auth">
<input type="hidden" name="do" value="login">
<label for="email">E-Mail:</label>
<input type="email" name="email" id="email" value="<?= htmlspecialchars($validData['email'] ?? '') ?>">
<label for="password">Passwort:</label>
<input type="password" name="password" id="password">
<button type="submit">Einloggen</button>
</form>
<?php endif; ?>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

61
Views/Auth/register.phtml Normal file
View File

@ -0,0 +1,61 @@
<?php include dirname(__DIR__).'/header.phtml'; ?>
<?php if (!empty($success)) : ?>
<div class="success-message" style="color: green; margin-bottom: 1em;">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<?php if (!empty($errors)) : ?>
<div class="error-messages" style="color: red; margin-bottom: 1em;">
<ul>
<?php foreach ($errors as $field => $error) : ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form action="?controller=Auth&do=register" method="post">
<label for="vorname">Vorname:</label>
<input type="text" name="vorname" id="vorname" value="<?php echo htmlspecialchars($validData['vorname'] ?? ''); ?>" required>
<label for="nachname">Nachname:</label>
<input type="text" name="nachname" id="nachname" value="<?php echo htmlspecialchars($validData['nachname'] ?? ''); ?>" required>
<label for="straße">Straße:</label>
<input type="text" name="straße" id="straße" value="<?php echo htmlspecialchars($validData['straße'] ?? ''); ?>" required>
<label for="hausnr">Hausnummer:</label>
<input type="text" name="hausnr" id="hausnr" value="<?php echo htmlspecialchars($validData['hausnr'] ?? ''); ?>" required>
<label for="postleitzahl">Postleitzahl:</label>
<input type="text" name="postleitzahl" id="postleitzahl" value="<?php echo htmlspecialchars($validData['postleitzahl'] ?? ''); ?>" required>
<label for="ort">Ort:</label>
<input type="text" name="ort" id="ort" value="<?php echo htmlspecialchars($validData['ort'] ?? ''); ?>" required>
<label for="land">Land:</label>
<input type="text" name="land" id="land" value="<?php echo htmlspecialchars($validData['land'] ?? ''); ?>" required>
<label for="tel">Telefonnummer:</label>
<input type="text" name="tel" id="tel" value="<?php echo htmlspecialchars($validData['tel'] ?? ''); ?>">
<label for="email">E-Mail-Adresse:</label>
<input type="email" name="email" id="email" value="<?php echo htmlspecialchars($validData['email'] ?? ''); ?>" required>
<label for="password">Passwort:</label>
<input type="password" name="password" id="password" required>
<label for="password_repeat">Passwort wiederholen:</label>
<input type="password" name="password_repeat" id="password_repeat" required>
<label for="isAdmin">
<input type="checkbox" name="isAdmin" id="isAdmin" value="1" <?php echo (!empty($validData['isAdmin'])) ? 'checked' : ''; ?>>
Admin-Rechte
</label>
<button type="submit">Registrieren</button>
</form>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

138
bibarts.sql Normal file
View File

@ -0,0 +1,138 @@
CREATE TABLE user (
userid INT AUTO_INCREMENT PRIMARY KEY,
vorname VARCHAR(50),
nachname VARCHAR(50),
straße VARCHAR(100),
hausnr VARCHAR(10),
postleitzahl VARCHAR(10),
ort VARCHAR(50),
land VARCHAR(50),
tel VARCHAR(20),
email VARCHAR(100) UNIQUE,
isAdmin BOOLEAN DEFAULT FALSE,
password VARCHAR(255)
);
CREATE TABLE standort (
standortid INT AUTO_INCREMENT PRIMARY KEY,
straße VARCHAR(100),
hausnr VARCHAR(10),
postleitzahl VARCHAR(10),
ort VARCHAR(50),
land VARCHAR(50),
tel VARCHAR(20),
email VARCHAR(100)
);
CREATE TABLE ausstellung (
austellungid INT AUTO_INCREMENT PRIMARY KEY,
standortid INT,
datum_von DATE,
datum_bis DATE,
name VARCHAR(100),
beschreibung TEXT,
max_tickets INT,
FOREIGN KEY (standortid) REFERENCES Standort(standortid)
);
CREATE TABLE ticket (
ticketid INT AUTO_INCREMENT PRIMARY KEY,
userid INT,
eventid INT,
kaufdatum DATE,
gültigkeitsdatum DATE,
preis DECIMAL(10,2),
FOREIGN KEY (userid) REFERENCES User(userid),
FOREIGN KEY (eventid) REFERENCES Ausstellung(austellungid)
);
CREATE TABLE gutschein (
gutscheinid INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) UNIQUE,
rabatt INT CHECK (rabatt BETWEEN 0 AND 100),
eventid INT,
gültigkeit DATE,
FOREIGN KEY (eventid) REFERENCES Ausstellung(austellungid)
);
CREATE TABLE news (
newsid INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
beschreibung TEXT,
datum DATE
);
--Testdaten
INSERT INTO user (vorname, nachname, straße, hausnr, postleitzahl, ort, land, tel, email, isAdmin, password)
VALUES
('Max', 'Muster', 'Musterstraße', '1', '12345', 'Musterstadt', 'Deutschland', '0123456789', 'max@muster.de', FALSE, 'passwort123'),
('Anna', 'Beispiel', 'Beispielweg', '5a', '54321', 'Beispielstadt', 'Deutschland', '0987654321', 'anna@beispiel.de', TRUE, 'adminpass');
INSERT INTO standort (straße, hausnr, postleitzahl, ort, land, tel, email)
VALUES
('Galeriestraße', '10', '10115', 'Berlin', 'Deutschland', '030123456', 'kontakt@galerie-berlin.de'),
('Kunstallee', '22b', '50667', 'Köln', 'Deutschland', '0221123456', 'info@kunst-koeln.de');
INSERT INTO ausstellung (standortid, datum_von, datum_bis, name, beschreibung, max_tickets)
VALUES
(1, '2025-07-01', '2025-08-31', 'Moderne Meisterwerke', 'Eine Sammlung moderner Kunstwerke aus Europa.', 200),
(2, '2025-09-10', '2025-10-20', 'Kunst der Antike', 'Ausstellung antiker Skulpturen und Gemälde.', 150);
INSERT INTO gutschein (code, rabatt, eventid, gültigkeit)
VALUES
('SOMMER2025', 15, 1, '2025-08-31'),
('HERBST25', 25, 2, '2025-10-15');
INSERT INTO ticket (userid, eventid, kaufdatum, gültigkeitsdatum, preis)
VALUES
(1, 1, '2025-06-01', '2025-07-15', 12.50),
(2, 2, '2025-06-05', '2025-09-15', 10.00);
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');
--Ä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';