120 lines
4.0 KiB
PHP
120 lines
4.0 KiB
PHP
<?php
|
|
include __DIR__ . '/../../config/koneksi.php';
|
|
include __DIR__ . '/mail_helper.php';
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
// Support JSON and form-encoded
|
|
$data = null;
|
|
if($_SERVER['REQUEST_METHOD'] === 'POST'){
|
|
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
|
if(strpos($contentType, 'application/json') !== false){
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
} else {
|
|
$data = $_POST;
|
|
}
|
|
}
|
|
|
|
$email = isset($data['email']) ? strtolower(trim($data['email'])) : null;
|
|
|
|
if(!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)){
|
|
http_response_code(400);
|
|
echo json_encode(['success'=>false,'error'=>'invalid_email']);
|
|
exit;
|
|
}
|
|
|
|
// Rate limiting table creation and validation
|
|
try {
|
|
$conn->query("CREATE TABLE IF NOT EXISTS verification_attempts (
|
|
email VARCHAR(255) PRIMARY KEY,
|
|
attempts INT NOT NULL DEFAULT 0,
|
|
last_attempt_at DATETIME NOT NULL,
|
|
locked_until DATETIME NULL,
|
|
code_hash VARCHAR(128) NULL,
|
|
expires_at DATETIME NULL
|
|
)");
|
|
} catch (Exception $e) {}
|
|
|
|
$nowStr = date('Y-m-d H:i:s');
|
|
$nowTime = time();
|
|
|
|
$stmt = $conn->prepare("SELECT attempts, last_attempt_at, locked_until FROM verification_attempts WHERE email = ?");
|
|
$stmt->bind_param('s', $email);
|
|
$stmt->execute();
|
|
$res = $stmt->get_result();
|
|
$row = $res ? $res->fetch_assoc() : null;
|
|
$stmt->close();
|
|
|
|
if($row){
|
|
$attempts = intval($row['attempts']);
|
|
$lastAttempt = strtotime($row['last_attempt_at']);
|
|
$lockedUntil = $row['locked_until'] ? strtotime($row['locked_until']) : null;
|
|
|
|
if($lockedUntil && $nowTime < $lockedUntil){
|
|
$diff = $lockedUntil - $nowTime;
|
|
$hours = floor($diff / 3600);
|
|
$mins = ceil(($diff % 3600) / 60);
|
|
http_response_code(429);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'locked_24h',
|
|
'message' => "Batas pengiriman kode tercapai. Anda harus menunggu {$hours} jam {$mins} menit.",
|
|
'locked_until' => $lockedUntil * 1000
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
if($nowTime - $lastAttempt < 30){
|
|
$remaining = 30 - ($nowTime - $lastAttempt);
|
|
http_response_code(429);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'cooldown_active',
|
|
'message' => "Silakan tunggu {$remaining} detik sebelum mengirim kembali.",
|
|
'remaining' => $remaining
|
|
]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Generate 6-digit code
|
|
$verificationCode = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
|
|
$codeHash = hash('sha256', $verificationCode);
|
|
$expiresAt = date('Y-m-d H:i:s', $nowTime + 15 * 60); // 15 minutes expiry
|
|
|
|
$mailSuccess = false;
|
|
try{
|
|
$subject = 'Kode Verifikasi Email - WebGIS';
|
|
$message = "Kode verifikasi Anda adalah:\n\n" . $verificationCode . "\n\nKode ini berlaku selama 15 menit. Jangan bagikan kode ini kepada siapapun.\n\nJika Anda tidak melakukan pendaftaran ini, abaikan email ini.";
|
|
$mailSuccess = send_mail_notify($email, $subject, $message, false);
|
|
}catch(Exception $e){
|
|
error_log('Mailing exception: ' . $e->getMessage());
|
|
}
|
|
|
|
// Update/Insert attempts on database
|
|
if($row){
|
|
$newAttempts = $row['attempts'];
|
|
if($mailSuccess){
|
|
$newAttempts = ($row['locked_until'] && $nowTime >= strtotime($row['locked_until'])) ? 1 : ($row['attempts'] + 1);
|
|
}
|
|
$newLockedUntil = ($newAttempts >= 3) ? date('Y-m-d H:i:s', $nowTime + 24 * 3600) : $row['locked_until'];
|
|
|
|
$up = $conn->prepare("UPDATE verification_attempts SET attempts = ?, last_attempt_at = ?, locked_until = ?, code_hash = ?, expires_at = ? WHERE email = ?");
|
|
$up->bind_param('isssss', $newAttempts, $nowStr, $newLockedUntil, $codeHash, $expiresAt, $email);
|
|
$up->execute();
|
|
$up->close();
|
|
} else {
|
|
$attemptsVal = $mailSuccess ? 1 : 0;
|
|
$nullVal = null;
|
|
$ins = $conn->prepare("INSERT INTO verification_attempts (email, attempts, last_attempt_at, locked_until, code_hash, expires_at) VALUES (?, ?, ?, ?, ?, ?)");
|
|
$ins->bind_param('sissss', $email, $attemptsVal, $nowStr, $nullVal, $codeHash, $expiresAt);
|
|
$ins->execute();
|
|
$ins->close();
|
|
}
|
|
|
|
$response = ['success'=>true,'email'=>$email,'message'=>'code_sent'];
|
|
if(getenv('DEBUG_MODE') === '1' || $_SERVER['REMOTE_ADDR'] === '127.0.0.1' || !$mailSuccess){
|
|
$response['debug_code'] = $verificationCode;
|
|
}
|
|
echo json_encode($response);
|
|
?>
|