function log_activity($action, $meta=''){ global $pdo; try{ $uid = $_SESSION['admin_id'] ?? null; $ip = $_SERVER['REMOTE_ADDR'] ?? ''; $ua = $_SERVER['HTTP_USER_AGENT'] ?? ''; $stmt = $pdo->prepare("INSERT INTO activity_log (user_id, action, meta, ip, user_agent) VALUES (?,?,?,?,?)"); $stmt->execute([$uid, $action, $meta, $ip, $ua]); } catch(Exception $e){} } function has_role($role){ global $pdo; $uid = $_SESSION['admin_id'] ?? 0; if(!$uid) return false; $stmt = $pdo->prepare("SELECT r.name FROM roles r JOIN user_roles ur ON ur.role_id=r.id WHERE ur.user_id=?"); $stmt->execute([$uid]); $roles = array_map(fn($x)=>$x['name'], $stmt->fetchAll()); return in_array($role, $roles, true); } function require_role($roles){ if(!is_array($roles)) $roles = [$roles]; foreach($roles as $r){ if(has_role($r)) return; } http_response_code(403); echo "
403 Forbidden
"; exit; } /* -------------------------------------------------------------------------- | CSRF Protection |-------------------------------------------------------------------------- */ function csrf_token() { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } function csrf_field() { echo ''; } function csrf_verify() { $sent = $_POST['csrf_token'] ?? ''; $sess = $_SESSION['csrf_token'] ?? ''; if (!$sent || !$sess || !hash_equals($sess, $sent)) { http_response_code(403); echo '403 Forbidden (CSRF)'; exit; } } /* -------------------------------------------------------------------------- | Simple Page Cache (optional) |-------------------------------------------------------------------------- */ function cache_page($key, $ttl_seconds = 60) { $dir = __DIR__ . '/../storage/cache_pages'; if (!is_dir($dir)) @mkdir($dir, 0755, true); $file = $dir . '/' . preg_replace('~[^a-zA-Z0-9_\-]~','_', $key) . '.html'; if (file_exists($file) && (time() - filemtime($file)) < $ttl_seconds) { readfile($file); exit; } ob_start(); register_shutdown_function(function() use ($file) { $out = ob_get_contents(); if ($out !== false) @file_put_contents($file, $out); ob_end_flush(); }); } /* -------------------------------------------------------------------------- | Brute-force protection helpers |-------------------------------------------------------------------------- */ function login_attempts_bootstrap() { global $pdo; try { $pdo->exec("CREATE TABLE IF NOT EXISTS login_attempts ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(190) NULL, ip VARCHAR(64) NULL, success TINYINT(1) NOT NULL DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY idx_user_ip_time (username, ip, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); } catch (Throwable $e) {} } function login_is_blocked($username, $ip) { global $pdo; login_attempts_bootstrap(); $max = defined('LOGIN_MAX_ATTEMPTS') ? (int)LOGIN_MAX_ATTEMPTS : 5; $mins = defined('LOGIN_BLOCK_MINUTES') ? (int)LOGIN_BLOCK_MINUTES : 15; try { $stmt = $pdo->prepare("SELECT COUNT(*) FROM login_attempts WHERE success=0 AND created_at >= (NOW() - INTERVAL ? MINUTE) AND (ip=? OR (username IS NOT NULL AND username=?))"); $stmt->execute([$mins, $ip, $username]); return ((int)$stmt->fetchColumn()) >= $max; } catch (Throwable $e) { return false; } } function login_record_attempt($username, $ip, $success) { global $pdo; login_attempts_bootstrap(); try { $stmt = $pdo->prepare("INSERT INTO login_attempts (username, ip, success) VALUES (?,?,?)"); $stmt->execute([$username ?: null, $ip ?: null, $success ? 1 : 0]); } catch (Throwable $e) {} } function require_any_role($roles) { if (!is_array($roles)) $roles = [$roles]; foreach ($roles as $r) if (has_role($r)) return; http_response_code(403); echo "403 Forbidden"; exit; } /* -------------------------------------------------------------------------- | Settings (DB key/value) |-------------------------------------------------------------------------- */ function settings_bootstrap() { global $pdo; try { $pdo->exec("CREATE TABLE IF NOT EXISTS settings ( `key` VARCHAR(190) PRIMARY KEY, `value` TEXT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); } catch (Throwable $e) {} } function setting($key, $default = '') { global $pdo; settings_bootstrap(); try { $stmt = $pdo->prepare("SELECT value FROM settings WHERE `key`=? LIMIT 1"); $stmt->execute([$key]); $v = $stmt->fetchColumn(); if ($v === false || $v === null || $v === '') return $default; return $v; } catch (Throwable $e) { return $default; } } function set_setting($key, $value) { global $pdo; settings_bootstrap(); try { $stmt = $pdo->prepare("INSERT INTO settings (`key`,`value`) VALUES (?,?) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)"); $stmt->execute([$key, $value]); return true; } catch (Throwable $e) { return false; } } روابي
روابي
حلول أمان متكاملة بمعايير احترافية
Rawabi

Client Registration

Client registration will be enabled once the portal is approved.

For now, request a quote and we will contact you shortly.
Request a Quote Login