Files
do-server-config/sites/worktracking.orbishosting.com/public_html/includes/auth.php
T

63 lines
2.2 KiB
PHP

<?php
require_once __DIR__ . '/functions.php';
class AdminAuth {
private const MAX_ATTEMPTS = 5;
private const LOCKOUT_MINUTES = 15;
public static function attempt(string $password): bool {
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
if (self::isLockedOut($ip)) {
return false;
}
if (password_verify($password, ADMIN_PASSWORD_HASH)) {
db()->query("DELETE FROM login_attempts WHERE ip_address = :ip", ['ip' => $ip]);
$_SESSION['wt_admin'] = true;
session_regenerate_id(true);
return true;
}
self::recordFailure($ip);
return false;
}
public static function isLockedOut(string $ip): bool {
$row = db()->fetch("SELECT * FROM login_attempts WHERE ip_address = :ip", ['ip' => $ip]);
if (!$row || (int) $row['attempts'] < self::MAX_ATTEMPTS) {
return false;
}
$lockoutUntil = strtotime($row['last_attempt']) + self::LOCKOUT_MINUTES * 60;
return time() < $lockoutUntil;
}
private static function recordFailure(string $ip): void {
$row = db()->fetch("SELECT * FROM login_attempts WHERE ip_address = :ip", ['ip' => $ip]);
if ($row) {
$lockoutUntil = strtotime($row['last_attempt']) + self::LOCKOUT_MINUTES * 60;
// Reset the counter once the previous lockout window has fully expired.
$attempts = (time() < $lockoutUntil) ? (int) $row['attempts'] + 1 : 1;
db()->update('login_attempts', ['attempts' => $attempts, 'last_attempt' => date('Y-m-d H:i:s')], 'ip_address = :ip', ['ip' => $ip]);
} else {
db()->insert('login_attempts', ['ip_address' => $ip, 'attempts' => 1, 'last_attempt' => date('Y-m-d H:i:s')]);
}
}
public static function isLoggedIn(): bool {
return !empty($_SESSION['wt_admin']);
}
public static function require(): void {
if (!self::isLoggedIn()) {
header('Location: /admin/login.php');
exit;
}
}
public static function logout(): void {
unset($_SESSION['wt_admin']);
session_regenerate_id(true);
}
}