diff --git a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml b/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml deleted file mode 100644 index 4fccad1..0000000 --- a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908.xml +++ /dev/null @@ -1,1833 +0,0 @@ - - - - - 3.51.1 - - - - - - - - - - - - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - window - - - 1 - - - 1 - - - 1 - - - - 1 - 1 - - - - - 1 - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - - - 1 - - - - - window - - - window - - - window - - - - - - 1 - 1 - - - 1 - 1 - - - 1 - - - window - - - - 1 - - - window - - - 1 - - - 1 - 1 - - - - - - 1 - - - - - 1 - - - 1 - - - window - - - window - - - 1 - - - 1 - - - 1 - 1 - - - 1 - - - 1 - 1 - - - 1 - - - 1 - - - 1 - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 1 - - - 1 - window - - - 1 - window - - - 1 - 1 - - - 1 - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - window - - - 1 - window - - - 1 - 1 - - - 1 - 1 - - - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - 1 - - - 1 - 1 - - - window - - - window - - - window - - - - window - - - window - - - window - - - window - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - aggregate - - - 1 - - - 1 - - - - - - 1 - 1 - - - window - - - aggregate - - - 1 - 1 - - - window - - - 1 - - - aggregate - - - window - - - window - - - 1 - - - 1 - - - - - - - - window - - - 1 - - - 1 - - - 1 - - - 1 - 1 - - - - 1 - - - 1 - - - - - window - - - 1 - - - 1 - - - - - - 1 - - - 1 - - - window - - - 1 - - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - 1 - - - - - 1 - - - - aggregate - - - - 1 - 1 - - - window - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - window - - - 1 - - - 1 - - - 1 - 1 - - - 1 - - - window - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 1 - - - 1 - - - 1 - - - aggregate - - - aggregate - - - 1 - - - 1 - 2026-06-05.07:13:27 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - R - - - R - - - R - - - R - - - R - - - R - - - 1 - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - R - - - 1 - - - 2 - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - R - - - R - - - 1 - - - 2 - - - 3 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - 2 - - - 3 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 2 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - R - - - 1 - - - 1 -
- - 1 - TEXT|0s - - - 2 - TEXT|0s - - - 3 - TEXT|0s - - - 4 - INT|0s - - - 5 - TEXT|0s - -
-
\ No newline at end of file diff --git a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta b/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta deleted file mode 100644 index 8dab49c..0000000 --- a/.idea/dataSources/315cb5c9-2b0f-435b-b602-59823b160908/storage_v2/_src_/schema/main.uQUzAA.meta +++ /dev/null @@ -1,2 +0,0 @@ -#n:main -! [0, 0, null, null, -2147483648, -2147483648] diff --git a/content/deleteAccount.php b/content/deleteAccount.php deleted file mode 100644 index c9e0a12..0000000 --- a/content/deleteAccount.php +++ /dev/null @@ -1,19 +0,0 @@ -deleteUser($_SESSION["user_email"]); -} - -$_SESSION = []; -session_destroy(); - -header("Location: index.php"); -exit(); \ No newline at end of file diff --git a/index.php b/index.php index cd4ea48..d02673d 100644 --- a/index.php +++ b/index.php @@ -17,12 +17,12 @@ if ($pfad === "register") { } if ($pfad === "logout") { - include_once "content/logout.php"; + include_once "content/logout-controller.php"; exit(); } if ($pfad === "deleteAccount") { - include_once "content/deleteAccount.php"; + include_once "content/deleteAccount-controller.php"; exit(); } ?> diff --git a/php/controller/createArticle-controller.php b/php/controller/createArticle-controller.php index 5e72e68..a39a409 100644 --- a/php/controller/createArticle-controller.php +++ b/php/controller/createArticle-controller.php @@ -3,7 +3,6 @@ SESSION_START(); require_once '../model/LocalArticleManager.php'; require_once '../model/ArticleManager.php'; require_once '../validator/article-validator.php'; -require_once "../model/LocalUserManager.php"; if ($_SERVER["REQUEST_METHOD"] === "POST") { $_SESSION["old_title"] = $_POST["title"] ?? ''; diff --git a/php/controller/deleteAccount-controller.php b/php/controller/deleteAccount-controller.php new file mode 100644 index 0000000..8d42198 --- /dev/null +++ b/php/controller/deleteAccount-controller.php @@ -0,0 +1,30 @@ +deleteUser($_SESSION["user_email"]); + } + + $_SESSION = []; + session_destroy(); + + header("Location: index.php"); + exit(); + +} catch (Exception $e) { + + $_SESSION["message"] = "internal_error"; + + header("Location: index.php?pfad=profile"); + exit(); +} \ No newline at end of file diff --git a/php/controller/login-controller.php b/php/controller/login-controller.php index 8e2c2ec..28090cf 100644 --- a/php/controller/login-controller.php +++ b/php/controller/login-controller.php @@ -1,8 +1,7 @@ findUser($email); + $dao = UserManager::getInstance(); - if ($user && password_verify($password, $user["password"])) { + $email = $_POST["email"] ?? ""; + $password = $_POST["password"] ?? ""; + + $user = $dao->findUser($email); + + if ($user && password_verify($password, $user["password"])) { - if (isset($user["vorname"]) && isset($user["nachname"])) { $_SESSION["user"] = $user["vorname"] . " " . $user["nachname"]; + $_SESSION["user_email"] = $user["email"]; + + header("Location: index.php"); + exit(); + } else { - $_SESSION["user"] = $user["username"] ?? ""; + $error = "Login fehlgeschlagen. Bitte überprüfe deine Eingaben."; } - $_SESSION["user_email"] = $user["email"]; - - header("Location: index.php"); - exit(); - - } else { - $error = "Login fehlgeschlagen. Bitte überprüfe deine Eingaben."; + } catch (Exception $e) { + $error = "Es ist ein interner Fehler aufgetreten. Bitte versuche es erneut."; } } \ No newline at end of file diff --git a/content/logout.php b/php/controller/logout-controller.php similarity index 100% rename from content/logout.php rename to php/controller/logout-controller.php diff --git a/php/controller/profile-controller.php b/php/controller/profile-controller.php index 720175d..e183b20 100644 --- a/php/controller/profile-controller.php +++ b/php/controller/profile-controller.php @@ -1,6 +1,6 @@ findUser($_SESSION["user_email"] ?? ""); @@ -38,15 +38,15 @@ try { $_GET["edit"] = "1"; } elseif (!userNameValidator($vorname)) { - $error = "Der Vorname muss 2 bis 50 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten."; + $error = "Der Vorname muss 2 bis 20 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten."; $_GET["edit"] = "1"; } elseif (!userNameValidator($nachname)) { - $error = "Der Nachname muss 2 bis 50 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten."; + $error = "Der Nachname muss 2 bis 20 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten."; $_GET["edit"] = "1"; } elseif (!userOptionalPasswordValidator($password)) { - $error = "Das Passwort muss 8 bis 72 Zeichen lang sein."; + $error = "Das Passwort muss 5 bis 12 Zeichen lang sein."; $_GET["edit"] = "1"; } else { diff --git a/php/controller/profileArticles-controller.php b/php/controller/profileArticles-controller.php index 49a9ea1..9842500 100644 --- a/php/controller/profileArticles-controller.php +++ b/php/controller/profileArticles-controller.php @@ -5,10 +5,10 @@ require_once 'php/model/Article.php'; require_once 'php/model/ArticleManager.php'; -require_once "../model/LocalUserManager.php"; +require_once "php/model/UserManager.php"; try { - $dao = new LocalUserManager(); + $dao = UserManager::getInstance(); $user = $dao->findUser($_SESSION["user_email"] ?? ""); $author = $user["email"]; diff --git a/php/controller/register-controller.php b/php/controller/register-controller.php index 5a0de05..3224eff 100644 --- a/php/controller/register-controller.php +++ b/php/controller/register-controller.php @@ -1,6 +1,6 @@ getConnection(); + + $db->exec(" + CREATE TABLE IF NOT EXISTS users ( + email TEXT PRIMARY KEY, + vorname TEXT NOT NULL, + nachname TEXT NOT NULL, + password TEXT NOT NULL + ); + "); + + unset($db); + + } catch (PDOException $e) { + throw new RuntimeException("Benutzerdatenbank konnte nicht erstellt werden."); + } + } + + /** + * Baut eine Verbindung zur SQLite-Datenbank auf. + * + * @return PDO Datenbankverbindung + * + * @throws RuntimeException wenn keine Verbindung hergestellt werden kann + */ + private function getConnection() + { + try { + $dsn = 'sqlite:' . __DIR__ . '/../../db/users.db'; + + $db = new PDO($dsn, null, null); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + return $db; + + } catch (PDOException $e) { + throw new RuntimeException("Verbindung zur Benutzerdatenbank fehlgeschlagen."); + } + } + + /** + * Gibt die Singleton-Instanz des DatabaseUserManagers zurück. + * + * @return DatabaseUserManager Instanz des DatabaseUserManagers + */ + public static function getInstance() + { + if (self::$instance == null) { + self::$instance = new DatabaseUserManager(); + } + + return self::$instance; + } + + /** + * Sucht einen Benutzer anhand seiner E-Mail-Adresse. + * + * @param string $email E-Mail-Adresse des Benutzers + * + * @return array|null Benutzerdaten als Array oder null, + * wenn kein Benutzer gefunden wurde + * + * @throws RuntimeException wenn der Benutzer nicht geladen werden kann + */ public function findUser($email) { - // TODO: Implement findUser() method. + try { + $db = $this->getConnection(); + + $sql = "SELECT * FROM users WHERE email = :email"; + $command = $db->prepare($sql); + + $command->execute([ + ":email" => $email + ]); + + $user = $command->fetch(PDO::FETCH_ASSOC); + + return $user ?: null; + + } catch (PDOException $e) { + throw new RuntimeException("Benutzer konnte nicht geladen werden."); + } } + /** + * Fügt einen neuen Benutzer in die Datenbank ein. + * + * Die Speicherung erfolgt innerhalb einer Transaktion. + * Doppelte E-Mail-Adressen werden durch den Primary Key verhindert. + * + * @param string $email E-Mail-Adresse des Benutzers + * @param string $vorname Vorname des Benutzers + * @param string $nachname Nachname des Benutzers + * @param string $password Passwort-Hash des Benutzers + * + * @return void + * + * @throws InvalidArgumentException wenn die E-Mail-Adresse bereits verwendet wird + * @throws RuntimeException wenn der Benutzer nicht gespeichert werden kann + */ public function addUser($email, $vorname, $nachname, $password) { - // TODO: Implement addUser() method. + try { + $db = $this->getConnection(); + $db->beginTransaction(); + + $sql = " + INSERT INTO users (email, vorname, nachname, password) + VALUES (:email, :vorname, :nachname, :password) + "; + + $command = $db->prepare($sql); + + $command->execute([ + ":email" => $email, + ":vorname" => $vorname, + ":nachname" => $nachname, + ":password" => $password + ]); + + $db->commit(); + + } catch (PDOException $e) { + if (isset($db) && $db->inTransaction()) { + $db->rollBack(); + } + + if ($e->getCode() === "23000") { + throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet."); + } + + throw new RuntimeException("Benutzer konnte nicht gespeichert werden."); + } } + /** + * Aktualisiert die Daten eines bestehenden Benutzers. + * + * Optional kann zusätzlich das Passwort geändert werden. + * Wenn kein neues Passwort übergeben wird, bleibt das alte Passwort erhalten. + * + * @param string $oldEmail Aktuelle E-Mail-Adresse des Benutzers + * @param string $newEmail Neue E-Mail-Adresse des Benutzers + * @param string $vorname Neuer Vorname des Benutzers + * @param string $nachname Neuer Nachname des Benutzers + * @param string|null $password Neues Passwort oder null + * + * @return bool true, wenn der Benutzer aktualisiert wurde, + * sonst false + * + * @throws InvalidArgumentException wenn die neue E-Mail-Adresse bereits verwendet wird + * @throws RuntimeException wenn der Benutzer nicht aktualisiert werden kann + */ public function updateUser($oldEmail, $newEmail, $vorname, $nachname, $password = null) { - // TODO: Implement updateUser() method. + try { + $db = $this->getConnection(); + + if (!empty($password)) { + $sql = " + UPDATE users + SET email = :newEmail, + vorname = :vorname, + nachname = :nachname, + password = :password + WHERE email = :oldEmail + "; + + $params = [ + ":newEmail" => $newEmail, + ":vorname" => $vorname, + ":nachname" => $nachname, + ":password" => password_hash($password, PASSWORD_DEFAULT), + ":oldEmail" => $oldEmail + ]; + } else { + $sql = " + UPDATE users + SET email = :newEmail, + vorname = :vorname, + nachname = :nachname + WHERE email = :oldEmail + "; + + $params = [ + ":newEmail" => $newEmail, + ":vorname" => $vorname, + ":nachname" => $nachname, + ":oldEmail" => $oldEmail + ]; + } + + $command = $db->prepare($sql); + $command->execute($params); + + return $command->rowCount() > 0; + + } catch (PDOException $e) { + if ($e->getCode() === "23000") { + throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet."); + } + + throw new RuntimeException("Benutzer konnte nicht aktualisiert werden."); + } } + /** + * Löscht einen Benutzer anhand seiner E-Mail-Adresse. + * + * @param string $email E-Mail-Adresse des zu löschenden Benutzers + * + * @return bool true, wenn der Benutzer gelöscht wurde, + * sonst false + * + * @throws RuntimeException wenn der Benutzer nicht gelöscht werden kann + */ public function deleteUser($email) { - // TODO: Implement deleteUser() method. - } + try { + $db = $this->getConnection(); + $sql = "DELETE FROM users WHERE email = :email"; + $command = $db->prepare($sql); + + $command->execute([ + ":email" => $email + ]); + + return $command->rowCount() > 0; + + } catch (PDOException $e) { + throw new RuntimeException("Benutzer konnte nicht gelöscht werden."); + } + } } \ No newline at end of file diff --git a/php/model/UserManager.php b/php/model/UserManager.php index 1ff7b28..3068087 100644 --- a/php/model/UserManager.php +++ b/php/model/UserManager.php @@ -1,10 +1,32 @@ findUser("mustermann@web.de") == null) { + $userManager->addUser( + "mustermann@web.de", + "Max", + "Mustermann", + password_hash("test12345", PASSWORD_DEFAULT) + ); + } + + return $userManager; } } \ No newline at end of file diff --git a/php/validator/user-validator.php b/php/validator/user-validator.php index 80dd996..0f789cf 100644 --- a/php/validator/user-validator.php +++ b/php/validator/user-validator.php @@ -1,13 +1,33 @@ = 8 && $zeichenAnzahl <= 72; + return $zeichenAnzahl >= 5 && $zeichenAnzahl <= 12; } +/** + * Prüft ein optionales Passwort. + * + * Ein leeres Passwort ist erlaubt und bedeutet, + * dass das bestehende Passwort unverändert bleibt. + * Falls ein Passwort angegeben wurde, wird es + * mit den normalen Passwortregeln geprüft. + * + * @param string|null $password Zu prüfendes Passwort + * + * @return bool true wenn das Passwort gültig oder leer ist, + * sonst false + */ function userOptionalPasswordValidator($password) { if (!isset($password) || $password === '') {