togethere.cloud/private_html/account/settings/change_password_verify.php

518 lines
19 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/session_bootstrap.php';
if (empty($_SESSION['logged_in'])) {
header('Location: /login/');
exit();
}
$host = "localhost";
$db = "togethere_cloud";
$user = "root";
$pass = "HasloDoSQL";
try {
$pdo->exec("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci");
} catch (PDOException $e) {
die("Błąd połączenia z bazą danych: " . $e->getMessage());
}
$user_id = $_SESSION['user_id'];
$error = '';
$success = '';
$link_expired = false;
$code_verified = false;
// Pobranie danych użytkownika
try {
$stmt = $pdo->prepare("SELECT email, password, password_reset_code, password_reset_expires FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$userData = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$userData) {
die("Nie znaleziono użytkownika");
}
} catch (PDOException $e) {
die("Błąd bazy danych: " . $e->getMessage() . "<br><br>Czy dodałeś kolumny password_reset_code i password_reset_expires do tabeli users?<br><br>Wykonaj w phpMyAdmin:<br><pre>ALTER TABLE users\nADD COLUMN password_reset_code VARCHAR(6) NULL AFTER newsletter_enabled,\nADD COLUMN password_reset_expires DATETIME NULL AFTER password_reset_code;</pre>");
}
// Jeśli użytkownik nie ma kodu, przekieruj do żądania
if (empty($userData['password_reset_code'])) {
header('Location: /account/settings/?error=' . urlencode('Link do zmiany hasła jest nieważny lub został już użyty.'));
exit();
}
// Sprawdzenie czy kod wygasł
if (!empty($userData['password_reset_expires'])) {
if (strtotime($userData['password_reset_expires']) < time()) {
$link_expired = true;
}
}
// Obsługa resend
if (isset($_GET['resend']) && $_GET['resend'] == '1') {
$reset_code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
$reset_expires = date('Y-m-d H:i:s', strtotime('+15 minutes'));
$update = $pdo->prepare("UPDATE users SET password_reset_code = ?, password_reset_expires = ? WHERE id = ?");
$update->execute([$reset_code, $reset_expires, $user_id]);
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/smtp_helper.php';
$subject = "Nowy kod zmiany hasła - Wspólnie";
$message = "
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<style>
body { font-family: 'Lato', Arial, sans-serif; background: #f0f8ff; padding: 20px; }
.container { max-width: 600px; margin: 0 auto; background: white; padding: 40px; border-radius: 15px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
h1 { color: #ff9800; text-align: center; }
.code { font-size: 32px; font-weight: bold; color: #ff9800; text-align: center; letter-spacing: 5px; margin: 30px 0; padding: 20px; background: #fff3e0; border-radius: 10px; }
p { color: #2c3e50; line-height: 1.6; }
.footer { margin-top: 30px; padding-top: 20px; border-top: 2px solid #fff3e0; text-align: center; color: #7f8c8d; font-size: 14px; }
</style>
</head>
<body>
<div class='container'>
<h1>🔒 Nowy kod zmiany hasła</h1>
<p>Twój nowy kod weryfikacyjny to:</p>
<div class='code'>$reset_code</div>
<p>Kod jest ważny przez <strong>15 minut</strong>.</p>
<div class='footer'>
<p>&copy; 2026 Wspólnie. Wszelkie prawa zastrzeżone.</p>
</div>
</div>
</body>
</html>
";
sendEmailSMTP($userData['email'], $subject, $message);
$success = "Nowy kod został wysłany na Twój email!";
$link_expired = false;
}
// Weryfikacja kodu
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['action']) && $_POST['action'] === 'verify_code' && !$link_expired) {
$code = trim($_POST["code"] ?? "");
if (empty($code)) {
$error = "Kod weryfikacyjny jest wymagany.";
} else {
if (strtotime($userData['password_reset_expires']) < time()) {
$error = "Kod weryfikacyjny wygasł.";
$link_expired = true;
} elseif ($userData['password_reset_code'] != $code) {
$error = "Nieprawidłowy kod weryfikacyjny.";
} else {
$code_verified = true;
}
}
}
// Walidacja i zmiana hasła
function validatePassword($password) {
$errors = [];
if (strlen($password) < 8) {
$errors[] = "Hasło musi mieć minimum 8 znaków";
}
if (!preg_match('/[A-Z]/', $password)) {
$errors[] = "Hasło musi zawierać wielką literę";
}
if (!preg_match('/[a-z]/', $password)) {
$errors[] = "Hasło musi zawierać małą literę";
}
if (!preg_match('/[0-9]/', $password)) {
$errors[] = "Hasło musi zawierać cyfrę";
}
return $errors;
}
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['action']) && $_POST['action'] === 'change_password') {
$code = trim($_POST["code"] ?? "");
$new_password = $_POST["new_password"] ?? "";
$confirm_password = $_POST["confirm_password"] ?? "";
// Pobierz aktualne hasło użytkownika
$stmt = $pdo->prepare("SELECT password, password_reset_code, password_reset_expires FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (strtotime($user['password_reset_expires']) < time()) {
$error = "Kod weryfikacyjny wygasł.";
$link_expired = true;
} elseif ($user['password_reset_code'] != $code) {
$error = "Nieprawidłowy kod weryfikacyjny.";
} elseif (empty($new_password) || empty($confirm_password)) {
$error = "Wszystkie pola są wymagane.";
$code_verified = true;
} elseif ($new_password !== $confirm_password) {
$error = "Hasła nie są identyczne.";
$code_verified = true;
} else {
// Walidacja siły hasła
$validation_errors = validatePassword($new_password);
if (!empty($validation_errors)) {
$error = implode(", ", $validation_errors);
$code_verified = true;
} elseif (password_verify($new_password, $user['password'])) {
$error = "Nowe hasło nie może być takie samo jak obecne hasło.";
$code_verified = true;
} else {
// Wszystko OK - zmień hasło
$new_hash = password_hash($new_password, PASSWORD_DEFAULT);
$update = $pdo->prepare("UPDATE users SET password = ?, password_reset_code = NULL, password_reset_expires = NULL WHERE id = ?");
$update->execute([$new_hash, $user_id]);
header('Location: /account/settings/?success=password_changed');
exit();
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Zmiana hasła | Wspólnie</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<link rel="stylesheet" href="/css/header.css" type="text/css" media="all"/>
<link rel="stylesheet" href="/css/footer.css" type="text/css" media="all"/>
<link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css" media="all">
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all">
<link href="//fonts.googleapis.com/css?family=Lato:400,500,600,700,800,900" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #e3f2fd 0%, #ffffff 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
}
.verify-container {
max-width: 500px;
margin: 80px auto;
padding: 40px;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(100, 181, 246, 0.2);
flex: 1;
}
.verify-container * {
box-sizing: border-box !important;
}
form {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
width: 100% !important;
}
h1 {
color: #1976d2;
font-size: 2em;
margin-bottom: 10px;
text-align: center;
}
.subtitle {
text-align: center;
color: #7f8c8d;
margin-bottom: 30px;
font-size: 0.95em;
}
.form-group {
margin-bottom: 25px !important;
text-align: center !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
width: 100% !important;
}
input[type="text"],
input[type="password"] {
width: 300px !important;
max-width: 300px !important;
padding: 15px !important;
border: 2px solid #e3f2fd !important;
border-radius: 8px !important;
font-size: 18px !important;
text-align: center !important;
transition: all 0.3s ease !important;
margin: 0 auto !important;
box-sizing: border-box !important;
font-family: 'Lato', Arial, sans-serif !important;
}
input[type="text"] {
font-size: 24px !important;
letter-spacing: 8px !important;
font-weight: bold !important;
color: #007BFF !important;
}
input:focus {
outline: none !important;
border-color: #007BFF !important;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1) !important;
}
button {
width: 100% !important;
max-width: 300px !important;
padding: 15px !important;
background: linear-gradient(135deg, #007BFF 0%, #0056b3 100%) !important;
color: white !important;
border: none !important;
border-radius: 8px !important;
font-size: 1.1em !important;
font-weight: 600 !important;
cursor: pointer !important;
transition: all 0.3s ease !important;
display: block !important;
margin: 0 auto !important;
font-family: 'Lato', Arial, sans-serif !important;
}
button:hover {
transform: translateY(-2px) !important;
box-shadow: 0 5px 15px rgba(0, 123, 255, 0.3) !important;
background: linear-gradient(135deg, #0056b3 0%, #004085 100%) !important;
}
.btn-secondary {
background: linear-gradient(135deg, #6c757d 0%, #5a6268 100%) !important;
margin-top: 0 !important;
}
.btn-secondary:hover {
background: linear-gradient(135deg, #5a6268 0%, #3d4349 100%) !important;
}
.success {
background: #d4edda !important;
color: #155724 !important;
padding: 15px !important;
border-radius: 8px !important;
margin-bottom: 20px !important;
text-align: center !important;
border-left: 4px solid #28a745 !important;
}
.error {
background: #ffebee !important;
color: #c62828 !important;
padding: 15px !important;
border-radius: 8px !important;
margin-bottom: 20px !important;
text-align: center !important;
border-left: 4px solid #c62828 !important;
}
.info-box {
background: #e3f2fd !important;
border-left: 4px solid #42a5f5 !important;
padding: 15px !important;
margin-bottom: 25px !important;
border-radius: 5px !important;
font-size: 0.95em !important;
color: #2c3e50 !important;
}
label {
display: block !important;
text-align: left !important;
width: 300px !important;
margin: 0 auto 10px !important;
font-weight: 600 !important;
color: #2c3e50 !important;
font-family: 'Lato', Arial, sans-serif !important;
}
a {
color: #007BFF !important;
text-decoration: none !important;
font-weight: 600 !important;
}
a:hover {
text-decoration: underline !important;
}
.button-container {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 15px !important;
margin-top: 20px !important;
width: 100% !important;
}
.btn-secondary {
background: linear-gradient(135deg, #6c757d 0%, #5a6268 100%) !important;
margin-top: 0 !important;
}
</style>
<script>
// Delay 60s na przycisk resend
document.addEventListener('DOMContentLoaded', function() {
const resendBtn = document.getElementById('resend-btn');
if (!resendBtn) return;
const lastResend = localStorage.getItem('lastResendTime_password');
if (lastResend) {
const elapsed = Math.floor((Date.now() - parseInt(lastResend)) / 1000);
if (elapsed < 60) {
startCountdown(60 - elapsed);
}
}
resendBtn.addEventListener('click', function(e) {
if (resendBtn.disabled) {
e.preventDefault();
return;
}
localStorage.setItem('lastResendTime_password', Date.now());
});
function startCountdown(seconds) {
resendBtn.disabled = true;
resendBtn.style.opacity = '0.5';
resendBtn.style.cursor = 'not-allowed';
const originalText = resendBtn.textContent;
const interval = setInterval(function() {
resendBtn.textContent = `Wysyłanie ponownie za ${seconds}s`;
seconds--;
if (seconds < 0) {
clearInterval(interval);
resendBtn.disabled = false;
resendBtn.style.opacity = '1';
resendBtn.style.cursor = 'pointer';
resendBtn.textContent = originalText;
localStorage.removeItem('lastResendTime_password');
}
}, 1000);
}
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('resend') === '1') {
startCountdown(60);
}
});
</script>
</head>
<body>
<?php
if (!empty($_SESSION['logged_in'])) {
include $_SERVER['DOCUMENT_ROOT'].'/global/navLogined.php';
} else {
include $_SERVER['DOCUMENT_ROOT'].'/global/navNoLogined.php';
}
?>
<div class="verify-container">
<h1>🔒 Zmiana hasła</h1>
<p class="subtitle">Wpisz 6-cyfrowy kod wysłany na Twój email</p>
<?php if ($error): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success"><?= htmlspecialchars($success) ?></div>
<?php endif; ?>
<?php if ($link_expired): ?>
<div class="error">
<strong>⏰ Kod wygasł!</strong><br>
Twój kod weryfikacyjny stracił ważność po 15 minutach.<br>
Kliknij przycisk poniżej aby otrzymać nowy kod.
</div>
<?php endif; ?>
<div class="info-box">
<strong>📧 Email:</strong> <?= htmlspecialchars($userData['email']) ?><br>
<strong>⏱️ Kod ważny:</strong> 15 minut od wysłania
</div>
<?php if (!$link_expired && !$code_verified): ?>
<form method="POST">
<input type="hidden" name="action" value="verify_code">
<div class="form-group">
<input type="text" name="code" maxlength="6" pattern="[0-9]{6}"
placeholder="000000" required autofocus>
</div>
<div class="button-container">
<button type="submit">Weryfikuj kod</button>
</div>
</form>
<?php elseif ($code_verified): ?>
<div class="info-box">
Hasło musi zawierać co najmniej 8 znaków, w tym wielką literę, małą literę i cyfrę.
</div>
<form method="POST">
<input type="hidden" name="action" value="change_password">
<input type="hidden" name="code" value="<?= htmlspecialchars($_POST['code'] ?? '') ?>">
<div class="form-group">
<label for="new_password">Nowe hasło</label>
<input type="password" id="new_password" name="new_password" placeholder="Nowe hasło" required>
</div>
<div class="form-group">
<label for="confirm_password">Potwierdź hasło</label>
<input type="password" id="confirm_password" name="confirm_password" placeholder="Powtórz hasło" required>
</div>
<div class="button-container">
<button type="submit">Zmień hasło</button>
</div>
</form>
<?php else: ?>
<p style="text-align: center; color: #7f8c8d; margin: 20px 0;">
Formularz jest zablokowany. Kliknij "Wyślij kod ponownie" aby otrzymać nowy kod.
</p>
<?php endif; ?>
<div class="button-container">
<button type="button" id="resend-btn" class="btn-secondary"
onclick="if(!this.disabled) window.location.href='?resend=1'">
Wyślij kod ponownie
</button>
</div>
<div style="text-align: center; margin-top: 20px;">
<a href="/account/settings/" style="color: #007BFF; text-decoration: none; font-weight: 600;">
← Powrót do ustawień
</a>
</div>
</div>
<?php
if (!empty($_SESSION['logged_in'])) {
include $_SERVER['DOCUMENT_ROOT'].'/global/footerLogined.php';
} else {
include $_SERVER['DOCUMENT_ROOT'].'/global/footerNoLogined.php';
}
?>
</body>
</html>