Files
omsorg/mitarbeiter-app/lib/auth.php
T
2026-06-13 20:03:22 +02:00

112 lines
3.0 KiB
PHP

<?php
require_once __DIR__ . '/db.php';
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| (($_SERVER['SERVER_PORT'] ?? null) == 443);
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'httponly' => true,
'secure' => $secure,
'samesite' => 'Lax',
]);
session_name('OMSORG_FELIX_APP');
session_start();
function is_logged_in(): bool {
if (empty($_SESSION['felix_logged_in']) || empty($_SESSION['felix_username'])) {
return false;
}
$stmt = db()->prepare('SELECT active FROM users WHERE username = ?');
$stmt->execute([$_SESSION['felix_username']]);
$row = $stmt->fetch();
return $row && (int)$row['active'] === 1;
}
function require_login(): void {
if (!is_logged_in()) {
header('Location: ../index.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST)) {
verify_csrf();
}
}
function csrf_token(): string {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function csrf_field(): string {
return '<input type="hidden" name="csrf_token" value="' . csrf_token() . '">';
}
function verify_csrf(): void {
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals(csrf_token(), $token)) {
http_response_code(403);
exit('Ungültige Anfrage.');
}
}
function require_admin(): void {
require_login();
if (!is_admin()) {
header('Location: ../pages/dashboard.php');
exit;
}
}
function is_admin(): bool {
return isset($_SESSION['felix_role']) && $_SESSION['felix_role'] === 'admin';
}
function current_user(): array|false {
static $cache = null;
static $cachedFor = null;
$username = $_SESSION['felix_username'] ?? '';
if ($username === '') return false;
if ($cache !== null && $cachedFor === $username) return $cache;
$stmt = db()->prepare('SELECT * FROM users WHERE username = ?');
$stmt->execute([$username]);
$cache = $stmt->fetch();
$cachedFor = $username;
return $cache;
}
function current_username(): string {
return $_SESSION['felix_username'] ?? '';
}
function current_name(): string {
return $_SESSION['felix_name'] ?? '';
}
function e(string $s): string {
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
// --- Login rate limiting (IP-based, persisted in DB) ---
function login_recent_fails(string $ip, int $windowSec = 600): int {
$cutoff = date('c', time() - $windowSec);
$stmt = db()->prepare(
'SELECT COUNT(*) FROM login_attempts WHERE ip = ? AND attempted_at >= ?'
);
$stmt->execute([$ip, $cutoff]);
return (int) $stmt->fetchColumn();
}
function login_record_fail(string $ip, string $username): void {
db()->prepare(
'INSERT INTO login_attempts (ip, username, attempted_at) VALUES (?, ?, ?)'
)->execute([$ip, $username, date('c')]);
}
function login_clear_fails(string $ip): void {
db()->prepare('DELETE FROM login_attempts WHERE ip = ?')->execute([$ip]);
}