291 lines
15 KiB
PHP
291 lines
15 KiB
PHP
<?php
|
|
include "../utils/security.php";
|
|
secure_session_start();
|
|
require_same_origin_request();
|
|
require_csrf_token();
|
|
header('Content-Type: application/json');
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
|
|
exit;
|
|
}
|
|
include "../../config/config.php";
|
|
include "../utils/get_location.php";
|
|
$username=$_SESSION["username"] ?? "";
|
|
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
|
check_rate_limit($conn, 'send_reset_link', 3, 60 * 60, $username);
|
|
if ($username === "") {
|
|
echo json_encode(['success' => false, 'message' => 'Missing username.']);
|
|
exit;
|
|
}
|
|
$sql="SELECT id, email, telegram_id FROM users WHERE username = ?;";
|
|
$mail="";
|
|
$id="";
|
|
$telegram_id="";
|
|
$stmt = mysqli_prepare($conn, $sql);
|
|
mysqli_stmt_bind_param($stmt, 's', $username);
|
|
mysqli_stmt_execute($stmt);
|
|
mysqli_stmt_store_result($stmt);
|
|
mysqli_stmt_bind_result($stmt,$id, $mail,$telegram_id);
|
|
mysqli_stmt_fetch($stmt);
|
|
$user_found = mysqli_stmt_num_rows($stmt) === 1;
|
|
mysqli_stmt_close($stmt);
|
|
if (!$user_found) {
|
|
echo json_encode(['success' => true, 'message' => 'If the account has reset methods configured, a reset link has been sent.']);
|
|
exit;
|
|
}
|
|
//send telegram message
|
|
$device = $_SERVER['HTTP_USER_AGENT'] ?? "";
|
|
$forwarded_for = $_SERVER["HTTP_X_FORWARDED_FOR"] ?? $_SERVER["REMOTE_ADDR"] ?? "";
|
|
$ip=trim(explode(",",$forwarded_for)[0]);
|
|
$location=get_location_from_ip($ip);
|
|
$date=date('Y-m-d H:i:s');
|
|
$token=bin2hex(random_bytes(128));
|
|
$token_hash=auth_token_hash($token);
|
|
$link="https://auth.jakach.ch/login/reset_pw.php?token=$token";
|
|
|
|
$tg_device = str_replace(['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'], ['\\_', '\\*', '\\[', '\\]', '\\(', '\\)', '\\~', '\\`', '\\>', '\\#', '\\+', '\\-', '\\=', '\\|', '\\{', '\\}', '\\.', '\\!'], $device);
|
|
$tg_username = str_replace(['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'], ['\\_', '\\*', '\\[', '\\]', '\\(', '\\)', '\\~', '\\`', '\\>', '\\#', '\\+', '\\-', '\\=', '\\|', '\\{', '\\}', '\\.', '\\!'], $_SESSION["username"]);
|
|
$tg_ip = str_replace(['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'], ['\\_', '\\*', '\\[', '\\]', '\\(', '\\)', '\\~', '\\`', '\\>', '\\#', '\\+', '\\-', '\\=', '\\|', '\\{', '\\}', '\\.', '\\!'], $ip);
|
|
$tg_location = str_replace(['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'], ['\\_', '\\*', '\\[', '\\]', '\\(', '\\)', '\\~', '\\`', '\\>', '\\#', '\\+', '\\-', '\\=', '\\|', '\\{', '\\}', '\\.', '\\!'], ($location["country"] ?? "").", ".($location["state"] ?? "").", ".($location["city"] ?? ""));
|
|
|
|
$message = "*Password reset token*\n\n"
|
|
. "You have requested the reset of your password here is your reset link.\n\n"
|
|
. "*Link*: [click here]($link)\n\n"
|
|
. "*Details of this request:*\n"
|
|
. "• *Date&Time*: $date\n"
|
|
. "• *Device&Browser*: $tg_device\n"
|
|
. "*Location*: $tg_location\n"
|
|
. "• *Account*: $tg_username\n"
|
|
. "• *IP*: $tg_ip\n\n"
|
|
."If this was you, you can reset your password. If this was not you somebody else tried to reset your password!\n"
|
|
. "*Thank you for using Jakach login!*";
|
|
|
|
// Telegram API URL
|
|
$url = "https://api.telegram.org/$TELEGRAM_BOT_API/sendMessage";
|
|
|
|
$message_data = [
|
|
'chat_id' => $telegram_id,
|
|
'text' => $message,
|
|
'parse_mode' => 'Markdown', // Use Markdown for formatting
|
|
];
|
|
|
|
// Use cURL to send the request
|
|
$ch = curl_init();
|
|
|
|
// Construct the GET request URL
|
|
$query_string = http_build_query($message_data); // Converts the array to URL-encoded query string
|
|
$get_url = $url . '?' . $query_string; // Append query string to the base URL
|
|
curl_setopt($ch, CURLOPT_URL, $get_url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Still retrieve the response if needed
|
|
curl_exec($ch);
|
|
curl_close($ch);
|
|
//send mail
|
|
if(!empty($mail)){
|
|
$loc=$location["country"].", ".$location["state"].", ".$location["city"];
|
|
$html_username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
|
|
$html_device = htmlspecialchars($device, ENT_QUOTES, 'UTF-8');
|
|
$html_ip = htmlspecialchars($ip, ENT_QUOTES, 'UTF-8');
|
|
$html_loc = htmlspecialchars($loc, ENT_QUOTES, 'UTF-8');
|
|
$html_mail = htmlspecialchars($mail, ENT_QUOTES, 'UTF-8');
|
|
$html_link = htmlspecialchars($link, ENT_QUOTES, 'UTF-8');
|
|
$content = '
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="x-apple-disable-message-reformatting" />
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<meta name="color-scheme" content="light dark" />
|
|
<meta name="supported-color-schemes" content="light dark" />
|
|
<title></title>
|
|
<style type="text/css" rel="stylesheet" media="all">
|
|
@import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700&display=swap");
|
|
body { width:100% !important; height:100%; margin:0; -webkit-text-size-adjust:none; }
|
|
a { color:#3869D4; }
|
|
a img { border:none; }
|
|
td { word-break:break-word; }
|
|
.preheader { display:none !important; visibility:hidden; mso-hide:all; font-size:1px; line-height:1px; max-height:0; max-width:0; opacity:0; overflow:hidden; }
|
|
body, td, th { font-family:"Nunito Sans",Helvetica,Arial,sans-serif; }
|
|
h1 { margin-top:0; color:#333333; font-size:22px; font-weight:bold; text-align:left; }
|
|
h2 { margin-top:0; color:#333333; font-size:16px; font-weight:bold; text-align:left; }
|
|
h3 { margin-top:0; color:#333333; font-size:14px; font-weight:bold; text-align:left; }
|
|
td, th { font-size:16px; }
|
|
p, ul, ol, blockquote { margin:.4em 0 1.1875em; font-size:16px; line-height:1.625; }
|
|
p.sub { font-size:13px; }
|
|
.align-right { text-align:right; }
|
|
.align-left { text-align:left; }
|
|
.align-center { text-align:center; }
|
|
.u-margin-bottom-none { margin-bottom:0; }
|
|
.button { background-color:#3869D4; border-top:10px solid #3869D4; border-right:18px solid #3869D4; border-bottom:10px solid #3869D4; border-left:18px solid #3869D4; display:inline-block; color:#FFF; text-decoration:none; border-radius:3px; box-shadow:0 2px 3px rgba(0,0,0,0.16); -webkit-text-size-adjust:none; box-sizing:border-box; }
|
|
.button--green { background-color:#22BC66; border-top:10px solid #22BC66; border-right:18px solid #22BC66; border-bottom:10px solid #22BC66; border-left:18px solid #22BC66; }
|
|
.button--red { background-color:#FF6136; border-top:10px solid #FF6136; border-right:18px solid #FF6136; border-bottom:10px solid #FF6136; border-left:18px solid #FF6136; }
|
|
@media only screen and (max-width:500px) { .button { width:100% !important; text-align:center !important; } }
|
|
.attributes { margin:0 0 21px; }
|
|
.attributes_content { background-color:#F4F4F7; padding:16px; }
|
|
.attributes_item { padding:0; }
|
|
.related { width:100%; margin:0; padding:25px 0 0 0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; }
|
|
.related_item { padding:10px 0; color:#CBCCCF; font-size:15px; line-height:18px; }
|
|
.related_item-title { display:block; margin:.5em 0 0; }
|
|
.related_item-thumb { display:block; padding-bottom:10px; }
|
|
.related_heading { border-top:1px solid #CBCCCF; text-align:center; padding:25px 0 10px; }
|
|
.discount { width:100%; margin:0; padding:24px; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; background-color:#F4F4F7; border:2px dashed #CBCCCF; }
|
|
.discount_heading { text-align:center; }
|
|
.discount_body { text-align:center; font-size:15px; }
|
|
.social { width:auto; }
|
|
.social td { padding:0; width:auto; }
|
|
.social_icon { height:20px; margin:0 8px 10px 8px; padding:0; }
|
|
.purchase { width:100%; margin:0; padding:35px 0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; }
|
|
.purchase_content { width:100%; margin:0; padding:25px 0 0 0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; }
|
|
.purchase_item { padding:10px 0; color:#51545E; font-size:15px; line-height:18px; }
|
|
.purchase_heading { padding-bottom:8px; border-bottom:1px solid #EAEAEC; }
|
|
.purchase_heading p { margin:0; color:#85878E; font-size:12px; }
|
|
.purchase_footer { padding-top:15px; border-top:1px solid #EAEAEC; }
|
|
.purchase_total { margin:0; text-align:right; font-weight:bold; color:#333333; }
|
|
.purchase_total--label { padding:0 15px 0 0; }
|
|
body { background-color:#F2F4F6; color:#51545E; }
|
|
p { color:#51545E; }
|
|
.email-wrapper { width:100%; margin:0; padding:0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; background-color:#F2F4F6; }
|
|
.email-content { width:100%; margin:0; padding:0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; }
|
|
.email-masthead { padding:25px 0; text-align:center; }
|
|
.email-masthead_logo { width:94px; }
|
|
.email-masthead_name { font-size:16px; font-weight:bold; color:#A8AAAF; text-decoration:none; text-shadow:0 1px 0 white; }
|
|
.email-body { width:100%; margin:0; padding:0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; }
|
|
.email-body_inner { width:570px; margin:0 auto; padding:0; -premailer-width:570px; -premailer-cellpadding:0; -premailer-cellspacing:0; background-color:#FFFFFF; }
|
|
.email-footer { width:570px; margin:0 auto; padding:0; -premailer-width:570px; -premailer-cellpadding:0; -premailer-cellspacing:0; text-align:center; }
|
|
.email-footer p { color:#A8AAAF; }
|
|
.body-action { width:100%; margin:30px auto; padding:0; -premailer-width:100%; -premailer-cellpadding:0; -premailer-cellspacing:0; text-align:center; }
|
|
.body-sub { margin-top:25px; padding-top:25px; border-top:1px solid #EAEAEC; }
|
|
.content-cell { padding:45px; }
|
|
@media only screen and (max-width:600px) { .email-body_inner, .email-footer { width:100% !important; } }
|
|
@media (prefers-color-scheme:dark) { body,.email-body,.email-body_inner,.email-content,.email-wrapper,.email-masthead,.email-footer { background-color:#333333 !important; color:#FFF !important; } p,ul,ol,blockquote,h1,h2,h3,span,.purchase_item { color:#FFF !important; } .attributes_content,.discount { background-color:#222 !important; } .email-masthead_name { text-shadow:none !important; } }
|
|
:root { color-scheme:light dark; supported-color-schemes:light dark; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<span class="preheader">Use this link to reset your password. The link is only valid for 12 hours.</span>
|
|
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
<tr>
|
|
<td align="center">
|
|
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
<tr>
|
|
<td class="email-masthead">
|
|
<a href="https://auth.jakach.ch" class="f-fallback email-masthead_name">Jakach Login</a>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="email-body" width="570" cellpadding="0" cellspacing="0">
|
|
<table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
|
<tr>
|
|
<td class="content-cell">
|
|
<div class="f-fallback">
|
|
<h1>Hi '.$html_username.',</h1>
|
|
<p>You recently requested to reset your password for your Jakach login account. Use the button below to reset it. <strong>This password reset is only valid for the next 12 hours.</strong></p>
|
|
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
<tr>
|
|
<td align="center">
|
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
|
|
<tr>
|
|
<td align="center">
|
|
<a href="'.$html_link.'" class="f-fallback button button--green" target="_blank">Reset your password</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><strong>Request Details:</strong></p>
|
|
<ul>
|
|
<li><strong>Date & Time:</strong> '.$date.'</li>
|
|
<li><strong>Device & Browser:</strong> '.$html_device.'</li>
|
|
<li><strong>Account:</strong> '.$html_mail.'</li>
|
|
<li><strong>IP Address:</strong> '.$html_ip.'</li>
|
|
<li><strong>Location:</strong> '.$html_loc.'</li>
|
|
</ul>
|
|
<p>Thanks,<br>The Jakach login team</p>
|
|
<table class="body-sub" role="presentation">
|
|
<tr>
|
|
<td>
|
|
<p class="f-fallback sub">If you are having trouble with the button above, copy and paste the URL below into your web browser.</p>
|
|
<p class="f-fallback sub">'.$html_link.'</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
|
<tr>
|
|
<td class="content-cell" align="center">
|
|
<p class="f-fallback sub align-center">Jakach.ch<br>CH-Switzerland.</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
';
|
|
|
|
|
|
$message = [
|
|
"personalizations" => [
|
|
[
|
|
"to" => [
|
|
[
|
|
"email" => $mail
|
|
]
|
|
]
|
|
]
|
|
],
|
|
"from" => [
|
|
"email" => $SENDGRID_MAIL
|
|
],
|
|
"subject" => "Jakach login password reset",
|
|
"content" => [
|
|
[
|
|
"type" => "text/html",
|
|
"value" => $content
|
|
]
|
|
]
|
|
];
|
|
|
|
$url = "https://api.sendgrid.com/v3/mail/send";
|
|
|
|
// Initialize cURL
|
|
$ch = curl_init($url);
|
|
|
|
// Set cURL options
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
"Authorization: Bearer $SENDGRID_KEY",
|
|
"Content-Type: application/json"
|
|
]);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));
|
|
|
|
// Execute the cURL request
|
|
curl_exec($ch);
|
|
curl_close($ch);
|
|
}
|
|
|
|
|
|
//insert the token into our db
|
|
$valid_until=time()+(12 * 60 * 60);
|
|
$sql="INSERT INTO reset_tokens (auth_token, user_id,valid_until) VALUES (?,?,?);";
|
|
$stmt = mysqli_prepare($conn, $sql);
|
|
mysqli_stmt_bind_param($stmt, 'sii', $token_hash,$id,$valid_until);
|
|
mysqli_stmt_execute($stmt);
|
|
mysqli_stmt_close($stmt);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'If the account has reset methods configured, a reset link has been sent.']);
|
|
?>
|