web - refactor core modules, harden authorization, simplify endpoints
This commit is contained in:
@@ -1,159 +1,324 @@
|
||||
<?php /* Name: reset-password.php
|
||||
Beschreibung: Passwort-Reset per SMS OTP (3 Schritte)
|
||||
- Schritt 1: E-Mail eingeben → OTP per SMS
|
||||
- Schritt 2: OTP-Code verifizieren
|
||||
- Schritt 3: Neues Passwort setzen */
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
|
||||
$step = $_GET["step"] ?? "email";
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<style>
|
||||
.login_button { position: relative; }
|
||||
.login_button.is-loading {
|
||||
color: transparent !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
.login_button.is-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin: -11px 0 0 -11px;
|
||||
border: 3px solid rgba(255,255,255,0.35);
|
||||
border-top-color: #FFFFFF;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.7s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login_panel">
|
||||
|
||||
<?php if (isset($_GET["error"])): ?>
|
||||
<?php
|
||||
$errorMessages = [
|
||||
1 => "E-Mail-Adresse nicht gefunden oder nicht registriert.",
|
||||
2 => "Keine Telefonnummer hinterlegt. Bitte wenden Sie sich an den Administrator.",
|
||||
3 => "Ungültiger oder abgelaufener Code.",
|
||||
4 => "SMS konnte nicht gesendet werden. Bitte versuchen Sie es erneut.",
|
||||
5 => "Passwort muss mindestens 8 Zeichen, einen Buchstaben und eine Zahl enthalten.",
|
||||
6 => "Passwörter stimmen nicht überein.",
|
||||
7 => "Sitzung abgelaufen. Bitte starten Sie den Vorgang erneut."
|
||||
];
|
||||
$errorNum = (int)$_GET["error"];
|
||||
$errorText = $errorMessages[$errorNum] ?? "Unbekannter Fehler.";
|
||||
?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" id="nakToastErr">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
|
||||
<span class="nak-toast__text"><?= htmlspecialchars($errorText) ?></span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastErr').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_GET["success"]) && $_GET["success"] == 1): ?>
|
||||
<div class="nak-toast nak-toast--success nak-toast--inline" id="nakToastOk">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg></div>
|
||||
<span class="nak-toast__text">Passwort erfolgreich geändert. Sie können sich jetzt anmelden.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastOk').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="login_content">
|
||||
<div class="nak-logo-link auth-logo">
|
||||
<img class="auth-logo__icon" src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK Logo">
|
||||
<div class="auth-logo__text">
|
||||
<div class="auth-logo__name">Neuapostolische Kirche</div>
|
||||
<div class="auth-logo__gemeinde">Berlin-Reinickendorf</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Passwort zurücksetzen</h2>
|
||||
|
||||
<?php if ($step === "email"): ?>
|
||||
<!-- SCHRITT 1: E-Mail eingeben -->
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Geben Sie Ihre E-Mail-Adresse ein. Ein Bestätigungscode wird an Ihre hinterlegte Telefonnummer und per Mail gesendet.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post" id="otpRequestForm">
|
||||
<input type="hidden" name="action" value="request_otp">
|
||||
<label for="email">E-Mailadresse</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="email" id="email" name="email" required>
|
||||
</div>
|
||||
<button class="login_button" type="submit" id="requestBtn">Code anfordern</button>
|
||||
</form>
|
||||
<script>
|
||||
document.getElementById('otpRequestForm').addEventListener('submit', function() {
|
||||
var btn = document.getElementById('requestBtn');
|
||||
btn.classList.add('is-loading');
|
||||
btn.disabled = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php elseif ($step === "verify"): ?>
|
||||
<!-- SCHRITT 2: Nur OTP-Code eingeben -->
|
||||
<?php $phone_masked = htmlspecialchars($_GET["phone"] ?? "***"); ?>
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Ein 6-stelliger Code wurde an die Nummer +49 <?= $phone_masked ?> und an Ihre E-Mail-Adresse gesendet.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post">
|
||||
<input type="hidden" name="action" value="verify_otp">
|
||||
<input type="hidden" name="user_id" value="<?= (int)($_GET["uid"] ?? 0) ?>">
|
||||
|
||||
<label for="otp_code">Bestätigungscode</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="text" id="otp_code" name="otp_code" maxlength="6" inputmode="numeric" pattern="[0-9]{6}" placeholder="000000" required autocomplete="one-time-code" style="text-align:center;font-size:1.4em;letter-spacing:8px;">
|
||||
</div>
|
||||
|
||||
<input class="login_button" type="submit" value="Code bestätigen">
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === "newpassword"): ?>
|
||||
<!-- SCHRITT 3: Neues Passwort setzen (nur nach verifiziertem OTP) -->
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Ihr Code wurde bestätigt. Geben Sie nun Ihr neues Passwort ein.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post">
|
||||
<input type="hidden" name="action" value="set_password">
|
||||
<input type="hidden" name="reset_token" value="<?= htmlspecialchars($_GET["token"] ?? '') ?>">
|
||||
|
||||
<label for="new_password">Neues Passwort</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="new_password" name="new_password" required>
|
||||
</div>
|
||||
|
||||
<label for="new_password_confirm">Neues Passwort wiederholen</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="new_password_confirm" name="new_password_confirm" required>
|
||||
</div>
|
||||
|
||||
<input class="login_button" type="submit" value="Passwort ändern">
|
||||
</form>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="small_text" align="center">
|
||||
<br>
|
||||
<a href="login.php">Zurück zur Anmeldung</a><br>
|
||||
<br>
|
||||
Probleme beim Zurücksetzen?<br>
|
||||
<a href="#" onclick="openContactModal(); return false;">Admin kontaktieren</a>
|
||||
</div>
|
||||
</div><!-- EOD: login_content -->
|
||||
</div><!-- EOD: login_panel -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/functions.php';
|
||||
require_once __DIR__ . '/util/authorization_helpers.php';
|
||||
|
||||
authorization_start_session();
|
||||
authorization_send_security_headers();
|
||||
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
authorization_redirect($g_httpHomePath, 302);
|
||||
}
|
||||
|
||||
$allowedSteps = ['email', 'verify', 'newpassword'];
|
||||
$step = (string) ($_GET['step'] ?? 'email');
|
||||
if (!in_array($step, $allowedSteps, true)) {
|
||||
$step = 'email';
|
||||
}
|
||||
|
||||
$error = null;
|
||||
$errorCode = (int) ($_GET['error'] ?? 0);
|
||||
$errorMessages = [
|
||||
1 => 'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
|
||||
3 => 'Ungültiger oder abgelaufener Bestätigungscode.',
|
||||
5 => 'Passwort muss mindestens 8 Zeichen, einen Buchstaben und eine Zahl enthalten.',
|
||||
6 => 'Passwörter stimmen nicht überein.',
|
||||
7 => 'Sitzung abgelaufen. Bitte starten Sie den Vorgang erneut.',
|
||||
];
|
||||
if (isset($errorMessages[$errorCode])) {
|
||||
$error = $errorMessages[$errorCode];
|
||||
}
|
||||
|
||||
if ($step === 'verify' && !authorization_reset_request_is_active()) {
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7', 302);
|
||||
}
|
||||
if ($step === 'newpassword' && !authorization_reset_is_authorized()) {
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7', 302);
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$action = (string) ($_POST['action'] ?? '');
|
||||
|
||||
if (!authorization_csrf_is_valid($_POST['csrf_token'] ?? null)) {
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7');
|
||||
}
|
||||
|
||||
$pdo = require $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/database.php';
|
||||
$pdo->exec("SET timezone = 'Europe/Berlin'");
|
||||
|
||||
if ($action === 'request_otp') {
|
||||
$email = trim((string) ($_POST['email'] ?? ''));
|
||||
if (strlen($email) > 254 || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
authorization_redirect('reset-password.php?error=1');
|
||||
}
|
||||
|
||||
authorization_clear_reset_state();
|
||||
$_SESSION['auth_reset_started_at'] = time();
|
||||
$_SESSION['auth_reset_attempts'] = 0;
|
||||
$_SESSION['auth_reset_user_id'] = 0;
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT ugi.user_id, ugi.phone, ugi.first_name, ugi.mail '
|
||||
. 'FROM user_general_information ugi '
|
||||
. 'INNER JOIN user_login ul ON ul.user_id = ugi.user_id '
|
||||
. 'WHERE LOWER(ugi.mail) = LOWER(?) LIMIT 1'
|
||||
);
|
||||
$stmt->execute([$email]);
|
||||
$resetUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (is_array($resetUser)) {
|
||||
$userId = (int) $resetUser['user_id'];
|
||||
$otp = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
|
||||
$expiresAt = date('Y-m-d H:i:s', time() + AUTH_RESET_TTL_SECONDS);
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$stmt = $pdo->prepare('UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0');
|
||||
$stmt->execute([$userId]);
|
||||
$stmt = $pdo->prepare('INSERT INTO password_reset_otp (user_id, otp_code, expires_at) VALUES (?, ?, ?)');
|
||||
$stmt->execute([$userId, $otp, $expiresAt]);
|
||||
$pdo->commit();
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
error_log('authorization reset OTP persistence failed: ' . $e->getMessage());
|
||||
authorization_redirect('reset-password.php?step=verify&sent=1');
|
||||
}
|
||||
|
||||
$mailSent = false;
|
||||
try {
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/send_mail.php';
|
||||
$greeting = !empty($resetUser['first_name']) ? 'Hallo ' . $resetUser['first_name'] : 'Hallo';
|
||||
$mailMessage = $greeting . ",\n\n"
|
||||
. "Sie haben das Zurücksetzen Ihres Passworts angefordert.\n\n"
|
||||
. "Ihr Bestätigungscode lautet: {$otp}\n\n"
|
||||
. "Der Code ist 10 Minuten gültig.\n\n"
|
||||
. 'Falls Sie diese Anfrage nicht gestellt haben, können Sie diese Nachricht ignorieren.';
|
||||
$mailSent = send_intranet_mail((string) $resetUser['mail'], 'Ihr Bestätigungscode', $mailMessage);
|
||||
} catch (Throwable $e) {
|
||||
error_log('authorization reset mail delivery failed: ' . $e->getMessage());
|
||||
}
|
||||
$smsSent = authorization_send_reset_sms(authorization_normalize_phone((string) ($resetUser['phone'] ?? '')), $otp);
|
||||
|
||||
if ($mailSent || $smsSent) {
|
||||
$_SESSION['auth_reset_user_id'] = $userId;
|
||||
} else {
|
||||
error_log('authorization reset delivery failed for user_id=' . $userId);
|
||||
$stmt = $pdo->prepare('UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0');
|
||||
$stmt->execute([$userId]);
|
||||
}
|
||||
}
|
||||
|
||||
// Immer dieselbe Antwort, damit aus dem Reset-Flow kein Kontostatus abgeleitet werden kann.
|
||||
authorization_redirect('reset-password.php?step=verify&sent=1');
|
||||
}
|
||||
|
||||
if ($action === 'verify_otp') {
|
||||
if (!authorization_reset_request_is_active()) {
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7');
|
||||
}
|
||||
|
||||
$otp = trim((string) ($_POST['otp_code'] ?? ''));
|
||||
$attempts = (int) ($_SESSION['auth_reset_attempts'] ?? 0) + 1;
|
||||
$_SESSION['auth_reset_attempts'] = $attempts;
|
||||
$userId = (int) ($_SESSION['auth_reset_user_id'] ?? 0);
|
||||
|
||||
if (!preg_match('/^[0-9]{6}$/', $otp) || $userId <= 0 || $attempts > AUTH_RESET_MAX_ATTEMPTS) {
|
||||
if ($attempts >= AUTH_RESET_MAX_ATTEMPTS && $userId > 0) {
|
||||
$stmt = $pdo->prepare('UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0');
|
||||
$stmt->execute([$userId]);
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7');
|
||||
}
|
||||
authorization_redirect('reset-password.php?step=verify&error=3');
|
||||
}
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT id FROM password_reset_otp '
|
||||
. 'WHERE user_id = ? AND otp_code = ? AND used = 0 AND expires_at > ? '
|
||||
. 'ORDER BY id DESC LIMIT 1 FOR UPDATE'
|
||||
);
|
||||
$stmt->execute([$userId, $otp, $now]);
|
||||
$otpId = (int) ($stmt->fetchColumn() ?: 0);
|
||||
|
||||
if ($otpId <= 0) {
|
||||
$pdo->rollBack();
|
||||
authorization_redirect('reset-password.php?step=verify&error=3');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE password_reset_otp SET used = 1 WHERE id = ?');
|
||||
$stmt->execute([$otpId]);
|
||||
$pdo->commit();
|
||||
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['auth_reset_user_id'] = $userId;
|
||||
$_SESSION['auth_reset_authorized_until'] = time() + AUTH_RESET_TTL_SECONDS;
|
||||
unset($_SESSION['auth_reset_attempts']);
|
||||
authorization_redirect('reset-password.php?step=newpassword');
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
error_log('authorization OTP verification failed: ' . $e->getMessage());
|
||||
authorization_redirect('reset-password.php?step=verify&error=3');
|
||||
}
|
||||
}
|
||||
|
||||
if ($action === 'set_password') {
|
||||
if (!authorization_reset_is_authorized()) {
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7');
|
||||
}
|
||||
|
||||
$newPassword = (string) ($_POST['new_password'] ?? '');
|
||||
$confirmation = (string) ($_POST['new_password_confirm'] ?? '');
|
||||
$passwordError = authorization_password_error($newPassword, $confirmation);
|
||||
if ($passwordError !== null) {
|
||||
$code = str_contains($passwordError, 'stimmen') ? 6 : 5;
|
||||
authorization_redirect('reset-password.php?step=newpassword&error=' . $code);
|
||||
}
|
||||
|
||||
$userId = (int) $_SESSION['auth_reset_user_id'];
|
||||
$passwordHash = password_hash($newPassword, PASSWORD_DEFAULT);
|
||||
$resetUser = null;
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$stmt = $pdo->prepare('UPDATE user_login SET password_hash = ? WHERE user_id = ?');
|
||||
$stmt->execute([$passwordHash, $userId]);
|
||||
if ($stmt->rowCount() !== 1) {
|
||||
throw new RuntimeException('Reset target login no longer exists.');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0');
|
||||
$stmt->execute([$userId]);
|
||||
|
||||
$stmt = $pdo->prepare('SELECT mail, first_name, last_name FROM user_general_information WHERE user_id = ?');
|
||||
$stmt->execute([$userId]);
|
||||
$resetUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_array($resetUser)) {
|
||||
throw new RuntimeException('Reset target user no longer exists.');
|
||||
}
|
||||
|
||||
$userName = trim(($resetUser['first_name'] ?? '') . ' ' . ($resetUser['last_name'] ?? ''));
|
||||
if ($userName === '') {
|
||||
$userName = (string) $resetUser['mail'];
|
||||
}
|
||||
$taskSubject = "Passwort selbst zurückgesetzt: {$userName}";
|
||||
$taskMessage = "{$userName} ({$resetUser['mail']}) hat das eigene Passwort erfolgreich zurückgesetzt.";
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) "
|
||||
. "VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())"
|
||||
);
|
||||
$stmt->execute([$userName, $resetUser['mail'], $taskSubject, $taskMessage]);
|
||||
|
||||
$pdo->commit();
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
error_log('authorization password reset failed: ' . $e->getMessage());
|
||||
authorization_clear_reset_state();
|
||||
authorization_redirect('reset-password.php?error=7');
|
||||
}
|
||||
|
||||
try {
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/send_mail.php';
|
||||
$loginUrl = authorization_public_url('/intranet_repo/projects/authorization/login.php');
|
||||
$greeting = !empty($resetUser['first_name']) ? 'Hallo ' . $resetUser['first_name'] : 'Hallo';
|
||||
$message = $greeting . ",\n\n"
|
||||
. "Ihr Passwort für das Intranet der NAK Reinickendorf wurde erfolgreich geändert.\n\n"
|
||||
. 'Sie können sich ab sofort mit Ihrem neuen Passwort anmelden.';
|
||||
send_intranet_mail((string) $resetUser['mail'], 'Passwort erfolgreich geändert', $message, null, 'intranet@nak-reinickendorf.de', 'Jetzt anmelden', $loginUrl);
|
||||
} catch (Throwable $e) {
|
||||
error_log('authorization password reset notification failed: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
authorization_clear_reset_state();
|
||||
session_regenerate_id(true);
|
||||
authorization_redirect('login.php?message=1');
|
||||
}
|
||||
|
||||
authorization_redirect('reset-password.php');
|
||||
}
|
||||
|
||||
$csrfToken = authorization_csrf_token();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<link rel="stylesheet" href="/intranet_repo/projects/_central/layouts/authorization.css">
|
||||
<script src="/intranet_repo/projects/_central/scripts/authorization.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login_panel">
|
||||
<?php if ($error !== null): ?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" data-auth-toast>
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
|
||||
<span class="nak-toast__text"><?= authorization_html($error) ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="login_content">
|
||||
<div class="nak-logo-link auth-logo">
|
||||
<img class="auth-logo__icon" src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK Logo">
|
||||
<div class="auth-logo__text">
|
||||
<div class="auth-logo__name">Neuapostolische Kirche</div>
|
||||
<div class="auth-logo__gemeinde">Berlin-Reinickendorf</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Passwort zurücksetzen</h2>
|
||||
|
||||
<?php if ($step === 'email'): ?>
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Geben Sie Ihre E-Mail-Adresse ein. Wenn ein passendes Konto vorhanden ist, senden wir einen Bestätigungscode an die hinterlegten Kontaktwege.</p>
|
||||
<form method="post" id="otpRequestForm">
|
||||
<input type="hidden" name="action" value="request_otp">
|
||||
<input type="hidden" name="csrf_token" value="<?= authorization_html($csrfToken) ?>">
|
||||
<label for="email">E-Mailadresse</label>
|
||||
<div class="item"><input class="login_field" type="email" id="email" name="email" maxlength="254" required autocomplete="email"></div>
|
||||
<button class="login_button" type="submit" id="requestBtn">Code anfordern</button>
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === 'verify'): ?>
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);"><?= authorization_html(authorization_masked_reset_message()) ?></p>
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="verify_otp">
|
||||
<input type="hidden" name="csrf_token" value="<?= authorization_html($csrfToken) ?>">
|
||||
<label for="otp_code">Bestätigungscode</label>
|
||||
<div class="item"><input class="login_field" type="text" id="otp_code" name="otp_code" maxlength="6" inputmode="numeric" pattern="[0-9]{6}" placeholder="000000" required autocomplete="one-time-code" style="text-align:center;font-size:1.4em;letter-spacing:8px;"></div>
|
||||
<input class="login_button" type="submit" value="Code bestätigen">
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === 'newpassword'): ?>
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Ihr Code wurde bestätigt. Geben Sie nun Ihr neues Passwort ein.</p>
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="set_password">
|
||||
<input type="hidden" name="csrf_token" value="<?= authorization_html($csrfToken) ?>">
|
||||
<label for="new_password">Neues Passwort</label>
|
||||
<div class="item"><input class="login_field" type="password" id="new_password" name="new_password" required autocomplete="new-password"></div>
|
||||
<label for="new_password_confirm">Neues Passwort wiederholen</label>
|
||||
<div class="item"><input class="login_field" type="password" id="new_password_confirm" name="new_password_confirm" required autocomplete="new-password"></div>
|
||||
<input class="login_button" type="submit" value="Passwort ändern">
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="small_text" align="center">
|
||||
<br><a href="login.php">Zurück zur Anmeldung</a><br><br>
|
||||
Probleme beim Zurücksetzen?<br>
|
||||
<a href="#" onclick="openContactModal(); return false;">Admin kontaktieren</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user