Files
praxis-creutzburg-web/intern/register.php
T
clemensandClaude Opus 5 e5f6482811 Fehlerausgabe, stiller Mailversand und fehlende Registrierungs-Mail
Drei zusammenhaengende Punkte aus der Analyse des Login-Problems.

1. PHP-Fehler wurden an Besucher ausgegeben

display_errors war in impfwarteliste.php (oeffentlich), intern/
impfwarteliste.php, intern/neueanfrage.php, den beiden neueanfrage-old
Sicherungen und zeiterfassung/api/vacations.php fest eingeschaltet.
Die oeffentliche Impfwarteliste zeigte Patienten bei einem Fatal Error
sogar Meldung, Dateipfad und Zeilennummer. Ueberall auf log_errors
umgestellt: E_ALL wird weiterhin vollstaendig erfasst, landet aber im
Server-Log statt auf der Seite. Der Shutdown-Handler der Impfwarteliste
protokolliert die Details und zeigt nur noch einen neutralen Hinweis.
Auch register.php gab die rohe Exception-Meldung aus.

2. SendMailMessageSilent() verschluckte jeden Fehler

Der catch-Block war leer. Ein SMTP-Ausfall war dadurch von aussen nicht
von einem falschen Code zu unterscheiden - der Benutzer landete auf
verify_2fa.php und wartete auf eine Mail, die nie kam. Die Funktion
protokolliert jetzt und liefert einen bool zurueck. login.php wertet
das aus, nimmt bei Fehlschlag den 2FA-Datensatz und die Session-Vormerkung
zurueck und sagt es auf der Login-Seite, statt weiterzuleiten.
Nebenbei entfernt: ein uebrig gebliebenes echo, das den Mailserver-Namen
mitten in die Seite schrieb, sowie ein zweites mysqli_fetch_assoc() auf
demselben Result, das nur NULL liefern konnte.

3. register.php verschickte keine Bestaetigungsmail

mailreg blieb 0, jeder neue Benutzer landete nach dem Login auf der
Aufforderung, die Authentifizierung selbst anzustossen. Die Mail geht
jetzt direkt nach der Registrierung raus. Erzeugung und Text liegen in
der neuen Funktion sendeAuthentifizierungsMail(), die authmeldung.php
ebenfalls benutzt - dort wurde der Rueckgabewert des Versands bisher
einer Variablen zugewiesen und nie ausgewertet, die Seite meldete
Erfolg auch bei fehlgeschlagenem Versand.

Der Versand laeuft nach dem commit(), deshalb prueft der catch-Block in
register.php jetzt inTransaction(), bevor er rollBack() aufruft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:53:10 +02:00

233 lines
7.5 KiB
PHP

<?php
session_start();
require_once(__DIR__ . "/../inc/config.inc.php");
require_once(__DIR__ . "/../inc/functions.inc.php");
include("templates/header.inc.php")
?>
<div class="container main-container registration-form">
<h1>Registrierung</h1>
<?php
$showFormular = true; //Variable ob das Registrierungsformular anezeigt werden soll
if(isset($_GET['register'])) {
$error = false;
$vorname = trim($_POST['vorname']);
$nachname = trim($_POST['nachname']);
$email = trim($_POST['email']);
$passwort = $_POST['passwort'];
$passwort2 = $_POST['passwort2'];
$tele = trim($_POST['tele']);
$geburtstag = trim($_POST['geburtstag']);
$ort = trim($_POST['ort']);
$strasse = trim($_POST['strasse']);
$plz = trim($_POST['plz']);
$kassenart = trim($_POST['kassenart']);
if(empty($vorname) || empty($nachname) || empty($email)) {
echo 'Bitte alle Felder ausfüllen<br>';
$error = true;
}
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo 'Bitte eine gültige E-Mail-Adresse eingeben<br>';
$error = true;
}
if(strlen($passwort) == 0) {
echo 'Bitte ein Passwort angeben<br>';
$error = true;
}
if($passwort != $passwort2) {
echo 'Die Passwörter müssen übereinstimmen<br>';
$error = true;
}
//Überprüfe, dass die E-Mail-Adresse noch nicht registriert wurde
if(!$error) {
$statement = $pdo->prepare("SELECT * FROM intern_users WHERE email = :email");
$result = $statement->execute(array('email' => $email));
$user = $statement->fetch();
if($user !== false) {
echo 'Diese E-Mail-Adresse ist bereits vergeben<br>';
$error = true;
}
}
//Keine Fehler, wir können den Nutzer registrieren
if (!$error) {
$pdo->beginTransaction();
try {
// Passwort hashen
$passwort_hash = password_hash($passwort, PASSWORD_DEFAULT);
// intern_users
$stmt = $pdo->prepare("
INSERT INTO intern_users
(kassenart, plz, strasse, ort, geburtstag, tele, email, passwort, vorname, nachname)
VALUES
(:kassenart, :plz, :strasse, :ort, :geburtstag, :tele, :email, :passwort, :vorname, :nachname)
");
$stmt->execute([
':kassenart' => $kassenart,
':plz' => $plz,
':strasse' => $strasse,
':ort' => $ort,
':geburtstag' => $geburtstag,
':tele' => $tele,
':email' => $email,
':passwort' => $passwort_hash,
':vorname' => $vorname,
':nachname' => $nachname
]);
// user-Tabelle: Insert oder Update über UNIQUE(mail)
$stmt = $pdo->prepare("
INSERT INTO persons
(vorname, nachname, geburtstag, email, tele, ort, plz, strasse)
VALUES
(:vorname, :nachname, :geburtstag, :email, :tele, :ort, :plz, :strasse)
ON DUPLICATE KEY UPDATE
vorname = VALUES(vorname),
nachname = VALUES(nachname),
geburtstag = VALUES(geburtstag),
tele = VALUES(tele),
ort = VALUES(ort),
plz = VALUES(plz),
strasse = VALUES(strasse)
");
$stmt->execute([
':vorname' => $vorname,
':nachname' => $nachname,
':geburtstag' => $geburtstag,
':email' => $email,
':tele' => $tele,
':ort' => $ort,
':plz' => $plz,
':strasse' => $strasse
]);
// User-ID holen
$stmt = $pdo->prepare("SELECT person_id FROM persons WHERE email = :mail");
$stmt->execute([':mail' => $email]);
$userid = $stmt->fetchColumn();
$pdo->commit();
echo 'Du wurdest erfolgreich registriert. <a href="login.php">Zum Login</a><br>';
$showFormular = false;
// Bisher wurde hier keine Mail verschickt: mailreg blieb 0 und jeder
// neue Benutzer landete nach dem Login auf der Aufforderung, die
// Authentifizierung selbst anzustossen. Den Link gibt es jetzt sofort.
$stmt = $pdo->prepare("SELECT id, vorname, email FROM intern_users WHERE email = :email LIMIT 1");
$stmt->execute([':email' => $email]);
$neuerUser = $stmt->fetch(PDO::FETCH_ASSOC);
if ($neuerUser && sendeAuthentifizierungsMail($pdo, $neuerUser, $organisationsname)) {
echo 'Wir haben Ihnen eine E-Mail geschickt. Bitte bestätigen Sie darin '
. 'Ihre Adresse, damit Sie das Konto vollständig nutzen können.<br>';
} else {
echo 'Die Bestätigungs-E-Mail konnte gerade nicht versendet werden. '
. 'Sie können sie nach dem Login jederzeit erneut anfordern.<br>';
}
} catch (Exception $e) {
// Der Mailversand laeuft nach dem commit(). Ohne diese Pruefung
// wuerde ein Fehler dort in rollBack() ohne offene Transaktion
// laufen und die Seite mit einem Fatal Error abbrechen.
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
// Interne Fehlermeldungen gehoeren ins Log, nicht auf die Seite.
error_log('register.php: Registrierung fehlgeschlagen: ' . $e->getMessage());
echo 'Bei der Registrierung ist ein Fehler aufgetreten. '
. 'Bitte versuchen Sie es später noch einmal oder rufen Sie uns an.<br>';
}
}
}
if($showFormular) {
?>
<form action="?register=1" method="post">
<div class="form-group">
<label for="inputVorname">Vorname:</label>
<input type="text" id="inputVorname" size="40" maxlength="250" name="vorname" class="form-control" required>
</div>
<div class="form-group">
<label for="inputNachname">Nachname:</label>
<input type="text" id="inputNachname" size="40" maxlength="250" name="nachname" class="form-control" required>
</div>
<div class="form-group">
<label for="inputGeburtstag">Geburtstag:</label>
<input type="date" id="inputGeburtstag" size="40" maxlength="250" name="geburtstag" class="form-control" required>
</div>
<div class="form-group">
<label for="inputTelefon">Telefon:</label>
<input type="text" id="inputTelefon" size="40" maxlength="250" name="tele" class="form-control" required>
</div>
<div class="form-group">
<label for="inputStrasse">Straße, Hausnummer:</label>
<input type="text" id="inputStrasse" size="40" maxlength="250" name="strasse" class="form-control" required>
</div>
<div class="form-group">
<label for="inputPLZ">PLZ:</label>
<input type="text" id="inputPLZ" size="40" maxlength="250" name="plz" class="form-control" required>
</div>
<div class="form-group">
<label for="inputOrt">Ort:</label>
<input type="text" id="inputOrt" size="40" maxlength="250" name="ort" class="form-control" required>
</div>
<div class="form-group">
<label for="inputkassenart">Kassen-/ Privatpatient:</label>
<select class="form-control" id="inputkassenart" name="kassenart" required />
<option value="0" >Kassenpatient</option>
<option value="1" >Privat versichert</option>
</select>
</div>
<div class="form-group">
<label for="inputEmail">E-Mail:</label>
<input type="email" id="inputEmail" size="40" maxlength="250" name="email" class="form-control" required>
</div>
<div class="form-group">
<label for="inputPasswort">Dein Passwort:</label>
<input type="password" id="inputPasswort" size="40" maxlength="250" name="passwort" class="form-control" required>
</div>
<div class="form-group">
<label for="inputPasswort2">Passwort wiederholen:</label>
<input type="password" id="inputPasswort2" size="40" maxlength="250" name="passwort2" class="form-control" required>
</div>
<div class="form-group">
<label for="inputPasswort2">Ich stimme den <a href="https://www.praxis-creutzburg.de/datenschutz.php">Datenschutz-Richtlinien</a> und der Verarbeitung meiner personenbezogenen Daten zu.</label>
<input type="checkbox" id="verarbeitung" name="verarbeitung" required>
</div>
<button type="submit" class="btn btn-lg btn-primary btn-block">Registrieren</button>
</form>
<?php
} //Ende von if($showFormular)
?>
</div>
<?php
include("templates/footer.inc.php")
?>