prepare intranet for first Dokploy deployment
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
<?php /* Name: reset-password-process.php
|
||||
Beschreibung: Verarbeitung des Passwort-Resets (3 Schritte)
|
||||
- Schritt 1: OTP generieren und per SMS + Mail senden
|
||||
- Schritt 2: OTP verifizieren → Reset-Token erzeugen
|
||||
- Schritt 3: Neues Passwort setzen mit Reset-Token */
|
||||
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/send_mail.php';
|
||||
|
||||
// PostgreSQL-Zeitzone auf PHP-Zeitzone setzen
|
||||
$pdo->exec("SET timezone = 'Europe/Berlin'");
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
header("Location: reset-password.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $_POST["action"] ?? '';
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 1: OTP anfordern
|
||||
// =============================================
|
||||
if ($action === "request_otp") {
|
||||
$email = trim($_POST["email"] ?? '');
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
header("Location: reset-password.php?error=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Nutzer suchen (muss registriert sein = user_login existiert)
|
||||
$stmt = $pdo->prepare("SELECT ugi.user_id, ugi.phone, ugi.first_name FROM user_general_information ugi INNER JOIN user_login ul ON ugi.user_id = ul.user_id WHERE ugi.mail = ?");
|
||||
$stmt->execute([$email]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user) {
|
||||
header("Location: reset-password.php?error=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($user['phone'])) {
|
||||
header("Location: reset-password.php?error=2");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP generieren (6-stellig)
|
||||
$otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
|
||||
|
||||
// Ablaufzeit als UNIX-Timestamp speichern (vermeidet Timezone-Probleme)
|
||||
$expires_timestamp = time() + 600; // 10 Minuten
|
||||
$expires_at = date('Y-m-d H:i:s', $expires_timestamp);
|
||||
|
||||
// Alte OTPs für diesen Nutzer invalidieren
|
||||
$stmt = $pdo->prepare("UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0");
|
||||
$stmt->execute([$user['user_id']]);
|
||||
|
||||
// Neues OTP speichern
|
||||
$stmt = $pdo->prepare("INSERT INTO password_reset_otp (user_id, otp_code, expires_at) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$user['user_id'], $otp, $expires_at]);
|
||||
|
||||
// SMS senden (wie im Seelsorgeplaner)
|
||||
$phone_full = "+49" . $user['phone'];
|
||||
$messageText = "Intranet NAK Reinickendorf\n\nIhr Bestaetigungscode: {$otp}\n\nDer Code ist 10 Minuten gueltig.";
|
||||
|
||||
$smsData = array(
|
||||
"phone" => $phone_full,
|
||||
"message" => $messageText
|
||||
);
|
||||
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-Type: application/json; charset=utf-8",
|
||||
'method' => 'POST',
|
||||
'content' => json_encode($smsData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'timeout' => 10,
|
||||
),
|
||||
);
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$smsResult = @file_get_contents(rtrim(intranet_env('SMS_GATEWAY_URL'), '/') . '/send_sms', false, $context);
|
||||
|
||||
if ($smsResult === FALSE) {
|
||||
header("Location: reset-password.php?error=4");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP zusätzlich per Mail senden
|
||||
$greeting = !empty($user['first_name']) ? "Hallo {$user['first_name']}" : "Hallo";
|
||||
$mailBetreff = "Ihr Bestätigungscode";
|
||||
$mailNachricht = "{$greeting},\n\n";
|
||||
$mailNachricht .= "Sie haben das Zurücksetzen Ihres Passworts angefordert.\n\n";
|
||||
$mailNachricht .= "Ihr Bestätigungscode lautet: {$otp}\n\n";
|
||||
$mailNachricht .= "Der Code ist 10 Minuten gültig.\n\n";
|
||||
$mailNachricht .= "Falls Sie diese Anfrage nicht gestellt haben, können Sie diese Nachricht ignorieren.";
|
||||
|
||||
send_intranet_mail($email, $mailBetreff, $mailNachricht);
|
||||
|
||||
// Telefonnummer maskieren für Anzeige (nur letzte 3 Ziffern zeigen)
|
||||
$phone_masked = str_repeat('*', max(0, strlen($user['phone']) - 3)) . substr($user['phone'], -3);
|
||||
|
||||
header("Location: reset-password.php?step=verify&uid={$user['user_id']}&phone=" . urlencode($phone_masked));
|
||||
exit;
|
||||
}
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 2: OTP verifizieren → Reset-Token erzeugen
|
||||
// =============================================
|
||||
if ($action === "verify_otp") {
|
||||
$user_id = (int)($_POST["user_id"] ?? 0);
|
||||
$otp_code = trim($_POST["otp_code"] ?? '');
|
||||
|
||||
if ($user_id === 0 || strlen($otp_code) !== 6) {
|
||||
header("Location: reset-password.php?error=3");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP prüfen – Vergleich mit PHP-Zeit statt DB NOW()
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$stmt = $pdo->prepare("SELECT id FROM password_reset_otp WHERE user_id = ? AND otp_code = ? AND used = 0 AND expires_at > ?");
|
||||
$stmt->execute([$user_id, $otp_code, $now]);
|
||||
$otpRecord = $stmt->fetch();
|
||||
|
||||
if (!$otpRecord) {
|
||||
header("Location: reset-password.php?step=verify&uid={$user_id}&error=3");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP als verwendet markieren
|
||||
$stmt = $pdo->prepare("UPDATE password_reset_otp SET used = 1 WHERE id = ?");
|
||||
$stmt->execute([$otpRecord['id']]);
|
||||
|
||||
// Einmal-Token für Passwort-Änderung generieren (in Session speichern)
|
||||
$reset_token = bin2hex(random_bytes(32));
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
$_SESSION['reset_token'] = $reset_token;
|
||||
$_SESSION['reset_user_id'] = $user_id;
|
||||
$_SESSION['reset_token_expires'] = time() + 600; // 10 Minuten
|
||||
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token));
|
||||
exit;
|
||||
}
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 3: Neues Passwort setzen (nach OTP-Verifizierung)
|
||||
// =============================================
|
||||
if ($action === "set_password") {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$reset_token = $_POST["reset_token"] ?? '';
|
||||
$new_password = $_POST["new_password"] ?? '';
|
||||
$new_password_confirm = $_POST["new_password_confirm"] ?? '';
|
||||
|
||||
// Token validieren
|
||||
if (empty($reset_token)
|
||||
|| !isset($_SESSION['reset_token'])
|
||||
|| $reset_token !== $_SESSION['reset_token']
|
||||
|| !isset($_SESSION['reset_token_expires'])
|
||||
|| $_SESSION['reset_token_expires'] < time()) {
|
||||
// Session-Daten aufräumen
|
||||
unset($_SESSION['reset_token'], $_SESSION['reset_user_id'], $_SESSION['reset_token_expires']);
|
||||
header("Location: reset-password.php?error=7");
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = (int)$_SESSION['reset_user_id'];
|
||||
|
||||
// Passwort-Validierung
|
||||
if (strlen($new_password) < 8 || !preg_match("/[a-z]/i", $new_password) || !preg_match("/[0-9]/", $new_password)) {
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token) . "&error=5");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($new_password !== $new_password_confirm) {
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token) . "&error=6");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Neues Passwort setzen
|
||||
$password_hash = password_hash($new_password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE user_login SET password_hash = ? WHERE user_id = ?");
|
||||
$stmt->execute([$password_hash, $user_id]);
|
||||
|
||||
// User-Daten laden für Mail und Vermerk
|
||||
$stmt = $pdo->prepare("SELECT mail, first_name, last_name FROM user_general_information WHERE user_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$resetUserData = $stmt->fetch();
|
||||
|
||||
if ($resetUserData) {
|
||||
$loginUrl = "https://" . ($_SERVER['HTTP_HOST'] ?? intranet_env('INTRANET_FQDN')) . "/intranet_repo/projects/authorization/login.php";
|
||||
$greeting = !empty($resetUserData['first_name']) ? "Hallo {$resetUserData['first_name']}" : "Hallo";
|
||||
|
||||
$mailBetreff = "Passwort erfolgreich geändert";
|
||||
$mailNachricht = "{$greeting},\n\n";
|
||||
$mailNachricht .= "Ihr Passwort für das Intranet der NAK Reinickendorf wurde erfolgreich geändert.\n\n";
|
||||
$mailNachricht .= "Sie können sich ab sofort mit Ihrem neuen Passwort anmelden.";
|
||||
|
||||
send_intranet_mail($resetUserData['mail'], $mailBetreff, $mailNachricht, null, "intranet@nak-reinickendorf.de", "Jetzt anmelden", $loginUrl);
|
||||
|
||||
// Vermerk in erledigte Tasks
|
||||
$userName = trim(($resetUserData['first_name'] ?? '') . ' ' . ($resetUserData['last_name'] ?? ''));
|
||||
if (empty($userName)) $userName = $resetUserData['mail'];
|
||||
|
||||
$taskSubject = "Passwort selbst zurückgesetzt: {$userName}";
|
||||
$taskMessage = "{$userName} ({$resetUserData['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, $resetUserData['mail'], $taskSubject, $taskMessage]);
|
||||
}
|
||||
|
||||
// Session-Daten aufräumen
|
||||
unset($_SESSION['reset_token'], $_SESSION['reset_user_id'], $_SESSION['reset_token_expires']);
|
||||
|
||||
header("Location: login.php?message=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
header("Location: reset-password.php");
|
||||
exit;
|
||||
?>
|
||||
Reference in New Issue
Block a user