smtp config
This commit is contained in:
parent
fa60b1d6db
commit
9b31c32aba
@ -4,9 +4,11 @@ require_once __DIR__ . "/../db/config.php";
|
||||
require_permission("settings_view");
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../includes/WablasService.php';
|
||||
require_once __DIR__ . '/../mail/MailService.php';
|
||||
|
||||
$pdo = db();
|
||||
$wablasTestResult = null;
|
||||
$smtpTestResult = null;
|
||||
$message = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
@ -61,6 +63,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SMTP
|
||||
if ($provider === 'smtp') {
|
||||
$keys = ['host', 'port', 'secure', 'username', 'password', 'from_email', 'from_name'];
|
||||
foreach ($keys as $k) {
|
||||
$val = $_POST[$k] ?? '';
|
||||
$stmt = $pdo->prepare("INSERT INTO integration_settings (provider, setting_key, setting_value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)");
|
||||
$stmt->execute(['smtp', $k, $val]);
|
||||
}
|
||||
|
||||
if ($action === 'save') {
|
||||
header("Location: integrations.php?msg=saved");
|
||||
exit;
|
||||
} elseif ($action === 'test') {
|
||||
$testEmail = $_POST['test_email'] ?? '';
|
||||
if (!empty($testEmail)) {
|
||||
// We need to use the new values immediately for testing
|
||||
// MailService usually loads from config, which we will update next
|
||||
// For now, let's just use the provided values if we can or wait until config is updated.
|
||||
// Actually, let's update config first then test.
|
||||
$smtpTestResult = MailService::sendMail($testEmail, "SMTP Test Message", "Your SMTP configuration is working correctly!", "Your SMTP configuration is working correctly!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch current settings
|
||||
@ -86,6 +112,15 @@ $wablasSecKey = getSetting($allSettings, 'wablas', 'secret_key');
|
||||
$wablasTemplate = getSetting($allSettings, 'wablas', 'order_template');
|
||||
$wablasEnabled = getSetting($allSettings, 'wablas', 'is_enabled');
|
||||
|
||||
// SMTP Settings
|
||||
$smtpHost = getSetting($allSettings, 'smtp', 'host');
|
||||
$smtpPort = getSetting($allSettings, 'smtp', 'port') ?: '587';
|
||||
$smtpSecure = getSetting($allSettings, 'smtp', 'secure') ?: 'tls';
|
||||
$smtpUser = getSetting($allSettings, 'smtp', 'username');
|
||||
$smtpPass = getSetting($allSettings, 'smtp', 'password');
|
||||
$smtpFromEmail = getSetting($allSettings, 'smtp', 'from_email');
|
||||
$smtpFromName = getSetting($allSettings, 'smtp', 'from_name');
|
||||
|
||||
// Default template if empty
|
||||
if (empty($wablasTemplate)) {
|
||||
$wablasTemplate = "Dear *{customer_name}*,
|
||||
@ -127,7 +162,76 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($smtpTestResult): ?>
|
||||
<div class="alert alert-<?= $smtpTestResult['success'] ? 'success' : 'danger' ?> alert-dismissible fade show" role="alert">
|
||||
<strong>SMTP Test Result:</strong> <?= $smtpTestResult['success'] ? 'Success! Test email sent.' : 'Error: ' . htmlspecialchars($smtpTestResult['error']) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- SMTP Settings -->
|
||||
<div class="col-md-12 mb-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 fw-bold text-primary">SMTP Configuration</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="provider" value="smtp">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">SMTP Host</label>
|
||||
<input type="text" class="form-control" name="host" placeholder="smtp.gmail.com" value="<?= htmlspecialchars($smtpHost) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<label class="form-label">SMTP Port</label>
|
||||
<input type="number" class="form-control" name="port" value="<?= htmlspecialchars($smtpPort) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<label class="form-label">Encryption</label>
|
||||
<select class="form-select" name="secure" <?= !has_permission('settings_add') ? 'disabled' : '' ?>>
|
||||
<option value="tls" <?= $smtpSecure == 'tls' ? 'selected' : '' ?>>TLS</option>
|
||||
<option value="ssl" <?= $smtpSecure == 'ssl' ? 'selected' : '' ?>>SSL</option>
|
||||
<option value="none" <?= $smtpSecure == 'none' ? 'selected' : '' ?>>None</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">SMTP Username</label>
|
||||
<input type="text" class="form-control" name="username" value="<?= htmlspecialchars($smtpUser) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">SMTP Password</label>
|
||||
<input type="password" class="form-control" name="password" value="<?= htmlspecialchars($smtpPass) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">From Email</label>
|
||||
<input type="email" class="form-control" name="from_email" placeholder="noreply@yourdomain.com" value="<?= htmlspecialchars($smtpFromEmail) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">From Name</label>
|
||||
<input type="text" class="form-control" name="from_name" placeholder="Business Name" value="<?= htmlspecialchars($smtpFromName) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (has_permission('settings_add')): ?>
|
||||
<div class="mb-3 border-top pt-3">
|
||||
<label class="form-label text-muted small">Test SMTP Connection</label>
|
||||
<div class="input-group">
|
||||
<input type="email" class="form-control" name="test_email" placeholder="receiver@example.com" value="<?= htmlspecialchars($_POST['test_email'] ?? '') ?>">
|
||||
<button type="submit" name="action" value="test" class="btn btn-info text-white">Save & Send Test Email</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="submit" name="action" value="save" class="btn btn-primary">Save SMTP Settings</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Thawani -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card shadow h-100">
|
||||
@ -174,7 +278,6 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<form method="POST" id="wablas_form">
|
||||
<input type="hidden" name="provider" value="wablas">
|
||||
|
||||
<!-- Also keep a hidden input to send '0' if checkbox is unchecked (handled in PHP POST block too) -->
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Domain</label>
|
||||
<input type="text" class="form-control" name="domain" placeholder="https://..." value="<?= htmlspecialchars($wablasDom) ?>" <?= !has_permission('settings_add') ? 'readonly' : '' ?>>
|
||||
@ -206,7 +309,6 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<input type="text" class="form-control" name="test_phone" placeholder="e.g. 62812345678" value="<?= htmlspecialchars($_POST['test_phone'] ?? '') ?>">
|
||||
<button type="submit" name="action" value="test" class="btn btn-info text-white">Test & Send Message</button>
|
||||
</div>
|
||||
<small class="text-muted">Enter a phone number to send a real test message.</small>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
@ -220,4 +322,4 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/header.php'; ?>
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
|
||||
@ -56,7 +56,7 @@ if (isset($_GET['delete'])) {
|
||||
}
|
||||
|
||||
// Fetch Outlets for Filter
|
||||
$outlets = $pdo->query("SELECT id, name FROM outlets ORDER BY name")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$outlets = $pdo->query("SELECT id, name FROM outlets WHERE is_deleted = 0 ORDER BY name")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Build Query with Filters
|
||||
$params = [];
|
||||
@ -78,11 +78,16 @@ if (!empty($_GET['end_date'])) {
|
||||
$params[':end_date'] = $_GET['end_date'];
|
||||
}
|
||||
|
||||
// Filter: Search (Order No)
|
||||
// Filter: Search (Order No / Customer Name)
|
||||
if (!empty($_GET['search'])) {
|
||||
if (is_numeric($_GET['search'])) {
|
||||
$where[] = "o.id = :search";
|
||||
$params[':search'] = $_GET['search'];
|
||||
$searchTerm = $_GET['search'];
|
||||
if (is_numeric($searchTerm)) {
|
||||
$where[] = "(o.id = :search_exact OR o.customer_name LIKE :search_like)";
|
||||
$params[':search_exact'] = $searchTerm;
|
||||
$params[':search_like'] = "%$searchTerm%";
|
||||
} else {
|
||||
$where[] = "o.customer_name LIKE :search";
|
||||
$params[':search'] = "%$searchTerm%";
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,7 +251,7 @@ include 'includes/header.php';
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small fw-bold text-muted">Search</label>
|
||||
<input type="text" name="search" class="form-control" placeholder="Order No (ID)" value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
|
||||
<input type="text" name="search" class="form-control" placeholder="Order No / Customer" value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="d-flex gap-2">
|
||||
|
||||
@ -16,7 +16,7 @@ ALTER TABLE `tables` ADD COLUMN IF NOT EXISTS `is_deleted` TINYINT(1) DEFAULT 0;
|
||||
-- But usually, if they have 'name', they need to move it to 'table_number'.
|
||||
|
||||
-- If name exists, this will work. If not, it will fail, which is okay for this specific fix.
|
||||
UPDATE `tables` SET `table_number` = `name` WHERE `table_number` IS NULL OR `table_number` = '';
|
||||
-- UPDATE `tables` SET `table_number` = `name` WHERE `table_number` IS NULL OR `table_number` = '';
|
||||
|
||||
-- Fix areas foreign key if it was wrong in their initial setup
|
||||
ALTER TABLE `areas` DROP FOREIGN KEY IF EXISTS `areas_ibfk_1`;
|
||||
|
||||
2
db/migrations/042_add_reset_token_to_users.sql
Normal file
2
db/migrations/042_add_reset_token_to_users.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE users ADD COLUMN reset_token VARCHAR(255) DEFAULT NULL;
|
||||
ALTER TABLE users ADD COLUMN reset_token_expiry DATETIME DEFAULT NULL;
|
||||
122
forgot_password.php
Normal file
122
forgot_password.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/functions.php';
|
||||
require_once __DIR__ . '/mail/MailService.php';
|
||||
|
||||
init_session();
|
||||
|
||||
$baseUrl = get_base_url();
|
||||
$settings = get_company_settings();
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$email = $_POST['email'] ?? '';
|
||||
|
||||
if (empty($email)) {
|
||||
$error = 'Please enter your email address.';
|
||||
} else {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id, username, full_name FROM users WHERE email = ? AND is_deleted = 0 LIMIT 1");
|
||||
$stmt->execute([$email]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($user) {
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$expiry = date('Y-m-d H:i:s', strtotime('+1 hour'));
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?");
|
||||
$stmt->execute([$token, $expiry, $user['id']]);
|
||||
|
||||
$resetLink = $baseUrl . "reset_password.php?token=" . $token;
|
||||
|
||||
$subject = "Password Reset Request - " . $settings['company_name'];
|
||||
$messageHtml = "
|
||||
<h2>Password Reset Request</h2>
|
||||
<p>Hello " . htmlspecialchars($user['full_name'] ?: $user['username']) . ",</p>
|
||||
<p>We received a request to reset your password. Click the button below to set a new password:</p>
|
||||
<p><a href='$resetLink' style='background: #0d6efd; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; display: inline-block;'>Reset Password</a></p>
|
||||
<p>If you did not request this, please ignore this email.</p>
|
||||
<p>This link will expire in 1 hour.</p>
|
||||
";
|
||||
$messageTxt = "Hello, click here to reset your password: $resetLink. This link will expire in 1 hour.";
|
||||
|
||||
$res = MailService::sendMail($email, $subject, $messageHtml, $messageTxt);
|
||||
|
||||
if (!empty($res['success'])) {
|
||||
$success = 'Password reset instructions have been sent to your email.';
|
||||
} else {
|
||||
$error = 'Failed to send reset email. Please contact administrator.';
|
||||
// error_log($res['error']);
|
||||
}
|
||||
} else {
|
||||
// We show success anyway for security reasons to prevent email enumeration
|
||||
$success = 'If that email exists in our system, you will receive reset instructions shortly.';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Forgot Password - <?= htmlspecialchars($settings['company_name']) ?></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="<?= $baseUrl ?>assets/css/custom.css">
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0 1rem 3rem rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="card login-card border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
<h3 class="fw-bold">Forgot Password</h3>
|
||||
<p class="text-muted small">Enter your email address to receive a reset link</p>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger small py-2"><?= $error ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success small py-2"><?= $success ?></div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="login.php" class="small text-decoration-none"><i class="bi bi-arrow-left"></i> Back to Login</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<form method="POST">
|
||||
<div class="mb-4">
|
||||
<label class="form-label small fw-medium">Email Address</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-0"><i class="bi bi-envelope"></i></span>
|
||||
<input type="email" name="email" class="form-control bg-light border-0" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-2 fw-bold mb-3">Send Reset Link</button>
|
||||
<div class="text-center">
|
||||
<a href="login.php" class="small text-decoration-none">Back to Login</a>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -82,6 +82,10 @@ $settings = get_company_settings();
|
||||
<div class="alert alert-danger small py-2"><?= $error ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_GET['reset']) && $_GET['reset'] == 'success'): ?>
|
||||
<div class="alert alert-success small py-2">Password reset successfully. You can now login.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-medium">Username</label>
|
||||
@ -90,13 +94,16 @@ $settings = get_company_settings();
|
||||
<input type="text" name="username" class="form-control bg-light border-0" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-medium">Password</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-0"><i class="bi bi-lock"></i></span>
|
||||
<input type="password" name="password" class="form-control bg-light border-0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 d-flex justify-content-end">
|
||||
<a href="forgot_password.php" class="small text-decoration-none">Forgot Password?</a>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-2 fw-bold">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
// Mail configuration sourced from environment variables.
|
||||
// No secrets are stored here; the file just maps env -> config array for MailService.
|
||||
// Mail configuration sourced from environment variables or Database.
|
||||
|
||||
function env_val(string $key, $default = null) {
|
||||
$v = getenv($key);
|
||||
@ -8,8 +7,6 @@ function env_val(string $key, $default = null) {
|
||||
}
|
||||
|
||||
// Fallback: if critical vars are missing from process env, try to parse executor/.env
|
||||
// This helps in web/Apache contexts where .env is not exported.
|
||||
// Supports simple KEY=VALUE lines; ignores quotes and comments.
|
||||
function load_dotenv_if_needed(array $keys): void {
|
||||
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
|
||||
if (empty($missing)) return;
|
||||
@ -22,9 +19,7 @@ function load_dotenv_if_needed(array $keys): void {
|
||||
if ($line[0] === '#' || trim($line) === '') continue;
|
||||
if (!str_contains($line, '=')) continue;
|
||||
[$k, $v] = array_map('trim', explode('=', $line, 2));
|
||||
// Strip potential surrounding quotes
|
||||
$v = trim($v, "\"' ");
|
||||
// Do not override existing env
|
||||
$v = trim($v, "'\" ");
|
||||
if ($k !== '' && (getenv($k) === false || getenv($k) === '')) {
|
||||
putenv("{$k}={$v}");
|
||||
}
|
||||
@ -35,42 +30,43 @@ function load_dotenv_if_needed(array $keys): void {
|
||||
|
||||
load_dotenv_if_needed([
|
||||
'MAIL_TRANSPORT','SMTP_HOST','SMTP_PORT','SMTP_SECURE','SMTP_USER','SMTP_PASS',
|
||||
'MAIL_FROM','MAIL_FROM_NAME','MAIL_REPLY_TO','MAIL_TO',
|
||||
'DKIM_DOMAIN','DKIM_SELECTOR','DKIM_PRIVATE_KEY_PATH'
|
||||
'MAIL_FROM','MAIL_FROM_NAME','MAIL_REPLY_TO','MAIL_TO'
|
||||
]);
|
||||
|
||||
$transport = env_val('MAIL_TRANSPORT', 'smtp');
|
||||
$smtp_host = env_val('SMTP_HOST');
|
||||
$smtp_port = (int) env_val('SMTP_PORT', 587);
|
||||
$smtp_secure = env_val('SMTP_SECURE', 'tls'); // tls | ssl | null
|
||||
$smtp_user = env_val('SMTP_USER');
|
||||
$smtp_pass = env_val('SMTP_PASS');
|
||||
// Try to load from Database
|
||||
$dbSettings = [];
|
||||
try {
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT setting_key, setting_value FROM integration_settings WHERE provider = 'smtp'");
|
||||
$stmt->execute();
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as $row) {
|
||||
$dbSettings[$row['setting_key']] = $row['setting_value'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Database might not be ready or table might not exist yet
|
||||
}
|
||||
|
||||
$from_email = env_val('MAIL_FROM', 'no-reply@localhost');
|
||||
$from_name = env_val('MAIL_FROM_NAME', 'App');
|
||||
$transport = $dbSettings['transport'] ?? env_val('MAIL_TRANSPORT', 'smtp');
|
||||
$smtp_host = $dbSettings['host'] ?? env_val('SMTP_HOST');
|
||||
$smtp_port = (int) ($dbSettings['port'] ?? env_val('SMTP_PORT', 587));
|
||||
$smtp_secure = $dbSettings['secure'] ?? env_val('SMTP_SECURE', 'tls');
|
||||
$smtp_user = $dbSettings['username'] ?? env_val('SMTP_USER');
|
||||
$smtp_pass = $dbSettings['password'] ?? env_val('SMTP_PASS');
|
||||
|
||||
$from_email = $dbSettings['from_email'] ?? env_val('MAIL_FROM', 'no-reply@localhost');
|
||||
$from_name = $dbSettings['from_name'] ?? env_val('MAIL_FROM_NAME', 'App');
|
||||
$reply_to = env_val('MAIL_REPLY_TO');
|
||||
|
||||
$dkim_domain = env_val('DKIM_DOMAIN');
|
||||
$dkim_selector = env_val('DKIM_SELECTOR');
|
||||
$dkim_private_key_path = env_val('DKIM_PRIVATE_KEY_PATH');
|
||||
|
||||
return [
|
||||
'transport' => $transport,
|
||||
|
||||
// SMTP
|
||||
'smtp_host' => $smtp_host,
|
||||
'smtp_port' => $smtp_port,
|
||||
'smtp_secure' => $smtp_secure,
|
||||
'smtp_user' => $smtp_user,
|
||||
'smtp_pass' => $smtp_pass,
|
||||
|
||||
// From / Reply-To
|
||||
'from_email' => $from_email,
|
||||
'from_name' => $from_name,
|
||||
'reply_to' => $reply_to,
|
||||
|
||||
// DKIM (optional)
|
||||
'dkim_domain' => $dkim_domain,
|
||||
'dkim_selector' => $dkim_selector,
|
||||
'dkim_private_key_path' => $dkim_private_key_path,
|
||||
];
|
||||
1112
qorder.php
1112
qorder.php
File diff suppressed because it is too large
Load Diff
110
reset_password.php
Normal file
110
reset_password.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/functions.php';
|
||||
|
||||
init_session();
|
||||
|
||||
$baseUrl = get_base_url();
|
||||
$settings = get_company_settings();
|
||||
|
||||
$error = '';
|
||||
$token = $_GET['token'] ?? '';
|
||||
$user = null;
|
||||
|
||||
if (empty($token)) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id, username, reset_token_expiry FROM users WHERE reset_token = ? AND is_deleted = 0 LIMIT 1");
|
||||
$stmt->execute([$token]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user || strtotime($user['reset_token_expiry']) < time()) {
|
||||
$error = "This password reset link is invalid or has expired.";
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !$error) {
|
||||
$password = $_POST['password'] ?? '';
|
||||
$confirmPassword = $_POST['confirm_password'] ?? '';
|
||||
|
||||
if (empty($password)) {
|
||||
$error = "Please enter a new password.";
|
||||
} elseif ($password !== $confirmPassword) {
|
||||
$error = "Passwords do not match.";
|
||||
} elseif (strlen($password) < 6) {
|
||||
$error = "Password must be at least 6 characters long.";
|
||||
} else {
|
||||
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE id = ?");
|
||||
$stmt->execute([$hashedPassword, $user['id']]);
|
||||
|
||||
header("Location: login.php?reset=success");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Reset Password - <?= htmlspecialchars($settings['company_name']) ?></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="<?= $baseUrl ?>assets/css/custom.css">
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0 1rem 3rem rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="card login-card border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
<h3 class="fw-bold">Set New Password</h3>
|
||||
<p class="text-muted small">Choose a secure password for your account</p>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger small py-2"><?= $error ?></div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="forgot_password.php" class="small text-decoration-none">Request a new reset link</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-medium">New Password</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-0"><i class="bi bi-lock"></i></span>
|
||||
<input type="password" name="password" class="form-control bg-light border-0" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label small fw-medium">Confirm New Password</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-0"><i class="bi bi-lock-fill"></i></span>
|
||||
<input type="password" name="confirm_password" class="form-control bg-light border-0" required>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-2 fw-bold">Reset Password</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user