Add PnPaaS application and browser installer
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/includes/bootstrap.php';
|
||||
pnpaas_session_start();
|
||||
|
||||
$token = trim((string)($_GET['token'] ?? $_POST['token'] ?? ''));
|
||||
$csrfToken = pnpaas_csrf_token();
|
||||
$error = null;
|
||||
$success = null;
|
||||
$validToken = false;
|
||||
|
||||
if (preg_match('/^[a-f0-9]{64}$/', $token)) {
|
||||
try {
|
||||
$check = pnpaas_db()->prepare(
|
||||
'SELECT id, user_id FROM password_reset_tokens
|
||||
WHERE token_hash = :token_hash AND used_at IS NULL AND expires_at > NOW()
|
||||
LIMIT 1'
|
||||
);
|
||||
$check->execute(['token_hash' => hash('sha256', $token)]);
|
||||
$validToken = is_array($check->fetch());
|
||||
} catch (Throwable $exception) {
|
||||
error_log('PnPaaS password reset validation error: ' . $exception->getMessage());
|
||||
$error = 'Der Zurücksetzungslink ist derzeit nicht verfügbar.';
|
||||
}
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $error === null) {
|
||||
$password = (string)($_POST['password'] ?? '');
|
||||
$passwordConfirmation = (string)($_POST['password_confirmation'] ?? '');
|
||||
if (!pnpaas_valid_csrf((string)($_POST['csrf_token'] ?? ''))) {
|
||||
$error = 'Die Sitzung ist abgelaufen. Bitte öffnen Sie den Link erneut.';
|
||||
} elseif (!$validToken) {
|
||||
$error = 'Der Link ist ungültig oder abgelaufen. Bitte fordern Sie einen neuen Link an.';
|
||||
} elseif (strlen($password) < 12) {
|
||||
$error = 'Das Passwort muss mindestens 12 Zeichen lang sein.';
|
||||
} elseif ($password !== $passwordConfirmation) {
|
||||
$error = 'Die Passwörter stimmen nicht überein.';
|
||||
} else {
|
||||
try {
|
||||
$db = pnpaas_db();
|
||||
$db->beginTransaction();
|
||||
$find = $db->prepare(
|
||||
'SELECT id, user_id FROM password_reset_tokens
|
||||
WHERE token_hash = :token_hash AND used_at IS NULL AND expires_at > NOW()
|
||||
FOR UPDATE'
|
||||
);
|
||||
$find->execute(['token_hash' => hash('sha256', $token)]);
|
||||
$reset = $find->fetch();
|
||||
if (!is_array($reset)) {
|
||||
$db->rollBack();
|
||||
$validToken = false;
|
||||
$error = 'Der Link ist ungültig oder abgelaufen. Bitte fordern Sie einen neuen Link an.';
|
||||
} else {
|
||||
$update = $db->prepare('UPDATE users SET password_hash = :password_hash WHERE id = :user_id AND status = :status');
|
||||
$update->execute([
|
||||
'password_hash' => password_hash($password, PASSWORD_DEFAULT),
|
||||
'user_id' => (int)$reset['user_id'],
|
||||
'status' => 'active',
|
||||
]);
|
||||
$used = $db->prepare('UPDATE password_reset_tokens SET used_at = NOW() WHERE user_id = :user_id');
|
||||
$used->execute(['user_id' => (int)$reset['user_id']]);
|
||||
$db->commit();
|
||||
$success = 'Ihr Passwort wurde geändert. Sie können sich jetzt anmelden.';
|
||||
$validToken = false;
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
if (isset($db) && $db instanceof PDO && $db->inTransaction()) {
|
||||
$db->rollBack();
|
||||
}
|
||||
error_log('PnPaaS password reset update error: ' . $exception->getMessage());
|
||||
$error = 'Das Passwort konnte nicht geändert werden. Bitte versuchen Sie es erneut.';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>PnPaaS – Neues Passwort</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="reset-title">
|
||||
<div class="brand-mark" aria-hidden="true">✦</div>
|
||||
<p class="eyebrow">PnPaaS Administration</p>
|
||||
<h1 id="reset-title">Neues Passwort</h1>
|
||||
<?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><p class="form-footer"><a href="index.php">Zur Anmeldung</a></p><?php elseif ($validToken): ?>
|
||||
<p class="intro">Vergeben Sie ein neues Passwort für Ihr Konto.</p>
|
||||
<form method="post" action="reset-password.php" class="login-form">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="token" value="<?= htmlspecialchars($token, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<label for="password">Neues 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>
|
||||
<button type="submit">Passwort speichern</button>
|
||||
</form>
|
||||
<?php elseif ($error === null): ?>
|
||||
<div class="alert alert-error" role="alert">Der Link ist ungültig oder abgelaufen. Bitte fordern Sie einen neuen Link an.</div>
|
||||
<p class="form-footer"><a href="forgot-password.php">Neuen Link anfordern</a></p>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user