first commit
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
ini_set('display_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
session_start();
|
||||
|
||||
$config = require __DIR__ . '/../config/database.php';
|
||||
|
||||
$dsn = sprintf(
|
||||
'mysql:host=%s;dbname=%s;charset=%s',
|
||||
$config['host'],
|
||||
$config['dbname'],
|
||||
$config['charset'] ?? 'utf8mb4'
|
||||
);
|
||||
|
||||
$pdo = new PDO(
|
||||
$dsn,
|
||||
$config['user'],
|
||||
$config['pass'],
|
||||
[
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]
|
||||
);
|
||||
|
||||
$errors = [];
|
||||
$successMessage = '';
|
||||
|
||||
const DEFAULT_LOCATION_NAME = 'Sternwarte Sonneberg';
|
||||
const DEFAULT_LOCATION_LATITUDE = 50.377;
|
||||
const DEFAULT_LOCATION_LONGITUDE = 11.189;
|
||||
const DEFAULT_LOCATION_ELEVATION = 640.0;
|
||||
const DEFAULT_LOCATION_TIMEZONE = 'Europe/Berlin';
|
||||
const DEFAULT_SATELLITE_ID = 61;
|
||||
|
||||
function sendRegistrationNotification(string $username, string $email, ?string $displayName): void
|
||||
{
|
||||
$to = 'tm@astronomiemuseum.de';
|
||||
$subject = 'Neue Registrierung bei SkyView';
|
||||
$safeDisplayName = $displayName !== null && $displayName !== '' ? $displayName : '-';
|
||||
|
||||
$messageLines = [
|
||||
'Ein neuer Benutzer hat sich registriert.',
|
||||
'',
|
||||
'Benutzername: ' . $username,
|
||||
'E-Mail: ' . $email,
|
||||
'Anzeigename: ' . $safeDisplayName,
|
||||
'Zeitpunkt: ' . date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$headers = [
|
||||
'MIME-Version: 1.0',
|
||||
'Content-Type: text/plain; charset=UTF-8',
|
||||
'From: noreply@astronomiemuseum.de',
|
||||
'Reply-To: ' . $email,
|
||||
];
|
||||
|
||||
try {
|
||||
mail(
|
||||
$to,
|
||||
$subject,
|
||||
implode(PHP_EOL, $messageLines),
|
||||
implode("\r\n", $headers)
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
error_log('Registration notification mail failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$displayName = trim($_POST['display_name'] ?? '');
|
||||
$password = $_POST['password'] ?? '';
|
||||
$passwordRepeat = $_POST['password_repeat'] ?? '';
|
||||
|
||||
if ($username === '') {
|
||||
$errors[] = 'Bitte einen Benutzernamen eingeben.';
|
||||
} elseif (mb_strlen($username) < 3) {
|
||||
$errors[] = 'Der Benutzername muss mindestens 3 Zeichen lang sein.';
|
||||
} elseif (mb_strlen($username) > 50) {
|
||||
$errors[] = 'Der Benutzername darf maximal 50 Zeichen lang sein.';
|
||||
}
|
||||
|
||||
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = 'Bitte eine gültige E-Mail-Adresse eingeben.';
|
||||
}
|
||||
|
||||
if ($password === '') {
|
||||
$errors[] = 'Bitte ein Passwort eingeben.';
|
||||
} elseif (strlen($password) < 8) {
|
||||
$errors[] = 'Das Passwort muss mindestens 8 Zeichen lang sein.';
|
||||
}
|
||||
|
||||
if ($passwordRepeat === '') {
|
||||
$errors[] = 'Bitte das Passwort wiederholen.';
|
||||
} elseif ($password !== $passwordRepeat) {
|
||||
$errors[] = 'Die Passwörter stimmen nicht überein.';
|
||||
}
|
||||
|
||||
if ($displayName !== '' && mb_strlen($displayName) > 100) {
|
||||
$errors[] = 'Der Anzeigename darf maximal 100 Zeichen lang sein.';
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$stmtCheck = $pdo->prepare("
|
||||
SELECT `id`
|
||||
FROM `app_users`
|
||||
WHERE `username` = :username OR `email` = :email
|
||||
LIMIT 1
|
||||
");
|
||||
$stmtCheck->execute([
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
]);
|
||||
|
||||
if ($stmtCheck->fetch()) {
|
||||
$errors[] = 'Benutzername oder E-Mail-Adresse ist bereits vergeben.';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$pdo->beginTransaction();
|
||||
|
||||
try {
|
||||
$stmtInsert = $pdo->prepare("
|
||||
INSERT INTO `app_users` (
|
||||
`username`,
|
||||
`email`,
|
||||
`password_hash`,
|
||||
`display_name`,
|
||||
`role`,
|
||||
`is_active`,
|
||||
`created_at`,
|
||||
`updated_at`
|
||||
) VALUES (
|
||||
:username,
|
||||
:email,
|
||||
:password_hash,
|
||||
:display_name,
|
||||
'user',
|
||||
0,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
");
|
||||
|
||||
$stmtInsert->execute([
|
||||
':username' => $username,
|
||||
':email' => $email,
|
||||
':password_hash' => $passwordHash,
|
||||
':display_name' => $displayName !== '' ? $displayName : null,
|
||||
]);
|
||||
|
||||
$userId = (int)$pdo->lastInsertId();
|
||||
|
||||
$stmtInsertLocation = $pdo->prepare("
|
||||
INSERT INTO `app_user_locations` (
|
||||
`user_id`,
|
||||
`name`,
|
||||
`latitude`,
|
||||
`longitude`,
|
||||
`elevation`,
|
||||
`timezone`,
|
||||
`is_default`,
|
||||
`created_at`,
|
||||
`updated_at`
|
||||
) VALUES (
|
||||
:user_id,
|
||||
:name,
|
||||
:latitude,
|
||||
:longitude,
|
||||
:elevation,
|
||||
:timezone,
|
||||
1,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
");
|
||||
$stmtInsertLocation->execute([
|
||||
':user_id' => $userId,
|
||||
':name' => DEFAULT_LOCATION_NAME,
|
||||
':latitude' => DEFAULT_LOCATION_LATITUDE,
|
||||
':longitude' => DEFAULT_LOCATION_LONGITUDE,
|
||||
':elevation' => DEFAULT_LOCATION_ELEVATION,
|
||||
':timezone' => DEFAULT_LOCATION_TIMEZONE,
|
||||
]);
|
||||
|
||||
$stmtInsertSatellite = $pdo->prepare("
|
||||
INSERT INTO `app_user_satellites` (
|
||||
`user_id`,
|
||||
`satellite_id`,
|
||||
`is_favorite`,
|
||||
`created_at`
|
||||
) VALUES (
|
||||
:user_id,
|
||||
:satellite_id,
|
||||
1,
|
||||
NOW()
|
||||
)
|
||||
");
|
||||
$stmtInsertSatellite->execute([
|
||||
':user_id' => $userId,
|
||||
':satellite_id' => DEFAULT_SATELLITE_ID,
|
||||
]);
|
||||
|
||||
$pdo->commit();
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
sendRegistrationNotification(
|
||||
$username,
|
||||
$email,
|
||||
$displayName !== '' ? $displayName : null
|
||||
);
|
||||
|
||||
$successMessage = 'Die Registrierung war erfolgreich. Das Konto wurde angelegt und muss noch freigeschaltet werden.';
|
||||
|
||||
$_POST = [];
|
||||
}
|
||||
}
|
||||
$loggedIn = false;
|
||||
?>
|
||||
<?php require __DIR__ . '/header.php'; ?>
|
||||
|
||||
<div class="auth-wrap">
|
||||
<div class="card auth-card">
|
||||
<h2>Registrieren</h2>
|
||||
|
||||
<p class="hint" style="margin-bottom:1.2rem;">Nach der Registrierung wird das Konto zunächst deaktiviert und später freigeschaltet.</p>
|
||||
|
||||
<?php if ($successMessage !== ''): ?>
|
||||
<p class="msg-success"><?= htmlspecialchars($successMessage, ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<ul class="msg-error">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="" class="form-stack">
|
||||
<div class="form-group">
|
||||
<label for="username">Benutzername</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
required
|
||||
maxlength="50"
|
||||
value="<?= htmlspecialchars($_POST['username'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="display_name">Anzeigename <span class="form-optional">(optional)</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="display_name"
|
||||
name="display_name"
|
||||
maxlength="100"
|
||||
value="<?= htmlspecialchars($_POST['display_name'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email">E-Mail-Adresse</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
required
|
||||
maxlength="190"
|
||||
value="<?= htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Passwort</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password_repeat">Passwort wiederholen</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password_repeat"
|
||||
name="password_repeat"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-full">Konto anlegen</button>
|
||||
</form>
|
||||
|
||||
<p class="form-footer">Bereits registriert? <a href="login.php">Anmelden</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require __DIR__ . '/footer.php'; ?>
|
||||
Reference in New Issue
Block a user