Flatten application into repository root
This commit is contained in:
+175
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/includes/bootstrap.php';
|
||||
pnpaas_session_start();
|
||||
|
||||
if (!empty($_SESSION['pnpaas_admin'])) {
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$csrfToken = pnpaas_csrf_token();
|
||||
$documents = pnpaas_registration_documents();
|
||||
$registrationEnabled = true;
|
||||
foreach ($documents as $document) {
|
||||
if (($document['url'] ?? '') === '' || filter_var($document['url'], FILTER_VALIDATE_URL) === false || !str_starts_with(strtolower($document['url']), 'https://')) {
|
||||
$registrationEnabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$error = null;
|
||||
$success = null;
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = trim((string)($_POST['username'] ?? ''));
|
||||
$email = strtolower(trim((string)($_POST['email'] ?? '')));
|
||||
$firstName = trim((string)($_POST['first_name'] ?? ''));
|
||||
$lastName = trim((string)($_POST['last_name'] ?? ''));
|
||||
$streetAddress = trim((string)($_POST['street_address'] ?? ''));
|
||||
$postalCode = trim((string)($_POST['postal_code'] ?? ''));
|
||||
$city = trim((string)($_POST['city'] ?? ''));
|
||||
$countryCode = strtoupper(trim((string)($_POST['country_code'] ?? 'AT')));
|
||||
$password = (string)($_POST['password'] ?? '');
|
||||
$passwordConfirmation = (string)($_POST['password_confirmation'] ?? '');
|
||||
|
||||
if (!$registrationEnabled) {
|
||||
$error = 'Die Registrierung ist derzeit noch nicht freigeschaltet.';
|
||||
} elseif (!pnpaas_valid_csrf((string)($_POST['csrf_token'] ?? ''))) {
|
||||
$error = 'Die Sitzung ist abgelaufen. Bitte laden Sie die Seite neu.';
|
||||
} elseif (!preg_match('/^[A-Za-z0-9][A-Za-z0-9_.-]{2,79}$/', $username)) {
|
||||
$error = 'Der Benutzername muss 3 bis 80 Zeichen enthalten und darf nur Buchstaben, Zahlen, Punkt, Bindestrich und Unterstrich enthalten.';
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$error = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
} elseif ($firstName === '' || strlen($firstName) > 100 || $lastName === '' || strlen($lastName) > 100) {
|
||||
$error = 'Bitte geben Sie Vor- und Nachnamen ein.';
|
||||
} elseif ($streetAddress === '' || strlen($streetAddress) > 180 || $postalCode === '' || strlen($postalCode) > 20 || $city === '' || strlen($city) > 100 || $countryCode !== 'AT') {
|
||||
$error = 'Bitte geben Sie eine vollständige österreichische Adresse ein.';
|
||||
} elseif ((string)($_POST['consent_terms'] ?? '') !== '1' || (string)($_POST['consent_privacy'] ?? '') !== '1' || (string)($_POST['consent_withdrawal'] ?? '') !== '1') {
|
||||
$error = 'Bitte bestätigen Sie die drei verlinkten Rechtstexte.';
|
||||
} elseif (strlen($password) < 12) {
|
||||
$error = 'Das Passwort muss mindestens 12 Zeichen lang sein.';
|
||||
} elseif (!hash_equals($password, $passwordConfirmation)) {
|
||||
$error = 'Die Passwörter stimmen nicht überein.';
|
||||
} else {
|
||||
try {
|
||||
$db = pnpaas_db();
|
||||
$db->beginTransaction();
|
||||
$db->exec('DELETE FROM account_activation_tokens WHERE expires_at < NOW() OR used_at IS NOT NULL');
|
||||
|
||||
$insertUser = $db->prepare(
|
||||
'INSERT INTO users (username, email, first_name, last_name, street_address, postal_code, city, country_code, password_hash, role, status)
|
||||
VALUES (:username, :email, :first_name, :last_name, :street_address, :postal_code, :city, :country_code, :password_hash, "user", "pending")'
|
||||
);
|
||||
$insertUser->execute([
|
||||
'username' => $username,
|
||||
'email' => $email,
|
||||
'first_name' => $firstName,
|
||||
'last_name' => $lastName,
|
||||
'street_address' => $streetAddress,
|
||||
'postal_code' => $postalCode,
|
||||
'city' => $city,
|
||||
'country_code' => $countryCode,
|
||||
'password_hash' => password_hash($password, PASSWORD_DEFAULT),
|
||||
]);
|
||||
$userId = (int)$db->lastInsertId();
|
||||
$insertConsent = $db->prepare(
|
||||
'INSERT INTO user_consents (user_id, consent_type, document_url, document_version, consented_at, consent_ip)
|
||||
VALUES (:user_id, :consent_type, :document_url, :document_version, NOW(), :consent_ip)'
|
||||
);
|
||||
foreach ($documents as $consentType => $document) {
|
||||
$insertConsent->execute([
|
||||
'user_id' => $userId,
|
||||
'consent_type' => $consentType,
|
||||
'document_url' => $document['url'],
|
||||
'document_version' => $document['version'] !== '' ? $document['version'] : null,
|
||||
'consent_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
|
||||
]);
|
||||
}
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$insertToken = $db->prepare(
|
||||
'INSERT INTO account_activation_tokens (user_id, token_hash, expires_at, requested_ip)
|
||||
VALUES (:user_id, :token_hash, DATE_ADD(NOW(), INTERVAL 24 HOUR), :requested_ip)'
|
||||
);
|
||||
$insertToken->execute([
|
||||
'user_id' => $userId,
|
||||
'token_hash' => hash('sha256', $token),
|
||||
'requested_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
|
||||
]);
|
||||
$db->commit();
|
||||
|
||||
if (!pnpaas_send_account_activation($email, $token)) {
|
||||
error_log('PnPaaS account activation mail could not be sent.');
|
||||
$error = 'Das Konto wurde angelegt, aber die Aktivierungs-E-Mail konnte nicht versendet werden. Bitte wenden Sie sich an den Administrator.';
|
||||
} else {
|
||||
$success = 'Die Registrierung war erfolgreich. Bitte prüfen Sie Ihr E-Mail-Postfach und aktivieren Sie Ihr Konto über den zugesendeten Link.';
|
||||
}
|
||||
} catch (PDOException $exception) {
|
||||
if (isset($db) && $db->inTransaction()) $db->rollBack();
|
||||
if ($exception->getCode() === '23000') {
|
||||
$error = 'Benutzername oder E-Mail-Adresse wird bereits verwendet.';
|
||||
} else {
|
||||
error_log('PnPaaS registration database error: ' . $exception->getMessage());
|
||||
$error = 'Die Registrierung ist derzeit nicht möglich. Bitte versuchen Sie es später erneut.';
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
if (isset($db) && $db->inTransaction()) $db->rollBack();
|
||||
error_log('PnPaaS registration error: ' . $exception->getMessage());
|
||||
$error = 'Die Registrierung ist derzeit nicht möglich. Bitte versuchen Sie es später erneut.';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>PnPaaS – Registrieren</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500;600&family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
</head>
|
||||
<body class="auth-page">
|
||||
<main class="auth-card" aria-labelledby="register-title">
|
||||
<div class="brand-mark" aria-hidden="true">✦</div>
|
||||
<p class="eyebrow">PnPaaS</p>
|
||||
<h1 id="register-title">Konto erstellen</h1>
|
||||
<p class="intro">Registrieren Sie sich. Anschließend erhalten Sie eine E-Mail zur Aktivierung Ihres Kontos.</p>
|
||||
<?php if ($error !== null): ?><div class="alert alert-error" role="alert"><?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?></div><?php endif; ?>
|
||||
<?php if ($success !== null): ?><div class="alert alert-success" role="status"><?= htmlspecialchars($success, ENT_QUOTES, 'UTF-8') ?></div><?php endif; ?>
|
||||
<?php if (!$registrationEnabled): ?><div class="alert alert-error" role="status">Die Registrierung wird freigeschaltet, sobald die drei externen Rechtstexte hinterlegt sind.</div><?php endif; ?>
|
||||
<?php if ($success === null): ?>
|
||||
<form method="post" action="register.php" class="login-form">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<fieldset <?= !$registrationEnabled ? 'disabled' : '' ?> style="border:0; padding:0; margin:0; display:grid; gap:.65rem;">
|
||||
<label for="first_name">Vorname</label>
|
||||
<input id="first_name" name="first_name" type="text" autocomplete="given-name" maxlength="100" required value="<?= htmlspecialchars((string)($_POST['first_name'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="last_name">Nachname</label>
|
||||
<input id="last_name" name="last_name" type="text" autocomplete="family-name" maxlength="100" required value="<?= htmlspecialchars((string)($_POST['last_name'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="street_address">Straße und Hausnummer</label>
|
||||
<input id="street_address" name="street_address" type="text" autocomplete="street-address" maxlength="180" required value="<?= htmlspecialchars((string)($_POST['street_address'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="postal_code">Postleitzahl</label>
|
||||
<input id="postal_code" name="postal_code" type="text" autocomplete="postal-code" maxlength="20" required value="<?= htmlspecialchars((string)($_POST['postal_code'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="city">Ort</label>
|
||||
<input id="city" name="city" type="text" autocomplete="address-level2" maxlength="100" required value="<?= htmlspecialchars((string)($_POST['city'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="country_code">Land</label>
|
||||
<select id="country_code" name="country_code" autocomplete="country" required><option value="AT" selected>Österreich</option></select>
|
||||
<label for="username">Benutzername</label>
|
||||
<input id="username" name="username" type="text" autocomplete="username" minlength="3" maxlength="80" required value="<?= htmlspecialchars((string)($_POST['username'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="email">E-Mail-Adresse</label>
|
||||
<input id="email" name="email" type="email" autocomplete="email" maxlength="254" required value="<?= htmlspecialchars((string)($_POST['email'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="password">Passwort</label>
|
||||
<input id="password" name="password" type="password" autocomplete="new-password" minlength="12" required>
|
||||
<label for="password_confirmation">Passwort wiederholen</label>
|
||||
<input id="password_confirmation" name="password_confirmation" type="password" autocomplete="new-password" minlength="12" required>
|
||||
<?php foreach ($documents as $consentType => $document): ?><label class="consent-line"><input type="checkbox" name="consent_<?= htmlspecialchars($consentType, ENT_QUOTES, 'UTF-8') ?>" value="1" required> <?= $consentType === 'terms' ? 'Ich akzeptiere die' : 'Ich habe die' ?> <a href="<?= htmlspecialchars($document['url'] !== '' ? $document['url'] : '#', ENT_QUOTES, 'UTF-8') ?>" target="_blank" rel="noopener noreferrer"><?= htmlspecialchars($document['title'], ENT_QUOTES, 'UTF-8') ?></a> <?= $consentType === 'terms' ? '.' : 'gelesen.' ?></label><?php endforeach; ?>
|
||||
<button type="submit">Registrieren</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<p class="form-footer"><a href="index.php">Zurück zur Anmeldung</a></p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user