Adds tests for middleware
parent
c2f63f6121
commit
5327bde032
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security Helper
|
* Security Helper
|
||||||
*
|
*
|
||||||
* Security helper, to be used with all the forms in the app.
|
* Security helper, to be used with all the forms in the app.
|
||||||
* Implements singleton pattern for consistent state management.
|
* Implements singleton pattern for consistent state management.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require_once __DIR__ . '/../helpers/security.php';
|
require_once __DIR__ . '/../helpers/security.php';
|
||||||
|
|
||||||
function verifyCsrfToken() {
|
function applyCsrfMiddleware() {
|
||||||
$security = SecurityHelper::getInstance();
|
$security = SecurityHelper::getInstance();
|
||||||
|
|
||||||
// Skip CSRF check for GET requests
|
// Skip CSRF check for GET requests
|
||||||
|
|
|
@ -11,6 +11,7 @@ require_once __DIR__ . '/../classes/ratelimiter.php';
|
||||||
* @return bool True if request is allowed, false if rate limited
|
* @return bool True if request is allowed, false if rate limited
|
||||||
*/
|
*/
|
||||||
function checkRateLimit($database, $endpoint, $userId = null) {
|
function checkRateLimit($database, $endpoint, $userId = null) {
|
||||||
|
$isTest = defined('PHPUNIT_RUNNING');
|
||||||
$rateLimiter = new RateLimiter($database['db']);
|
$rateLimiter = new RateLimiter($database['db']);
|
||||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||||
|
|
||||||
|
@ -19,28 +20,34 @@ function checkRateLimit($database, $endpoint, $userId = null) {
|
||||||
// Get remaining requests for error message
|
// Get remaining requests for error message
|
||||||
$remaining = $rateLimiter->getRemainingPageRequests($ipAddress, $endpoint, $userId);
|
$remaining = $rateLimiter->getRemainingPageRequests($ipAddress, $endpoint, $userId);
|
||||||
|
|
||||||
// Set rate limit headers
|
if (!$isTest) {
|
||||||
header('X-RateLimit-Remaining: ' . $remaining);
|
// Set rate limit headers
|
||||||
header('X-RateLimit-Reset: ' . (time() + 60)); // Reset in 1 minute
|
header('X-RateLimit-Remaining: ' . $remaining);
|
||||||
|
header('X-RateLimit-Reset: ' . (time() + 60)); // Reset in 1 minute
|
||||||
|
|
||||||
// Return 429 Too Many Requests
|
// Return 429 Too Many Requests
|
||||||
http_response_code(429);
|
http_response_code(429);
|
||||||
|
|
||||||
// If AJAX request, return JSON
|
// If AJAX request, return JSON
|
||||||
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
|
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
|
||||||
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
|
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Too many requests. Please try again in a minute.',
|
'message' => 'Too many requests. Please try again in a minute.',
|
||||||
'messageData' => Feedback::getMessageData('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true)
|
'messageData' => Feedback::getMessageData('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true)
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// For regular requests, set flash message and redirect
|
// For regular requests, set flash message and redirect
|
||||||
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
|
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
|
||||||
header('Location: ' . htmlspecialchars($app_root));
|
header('Location: ' . htmlspecialchars($app_root));
|
||||||
|
}
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
exit;
|
|
||||||
|
// In test mode, just set the flash message
|
||||||
|
Feedback::flash('ERROR', 'DEFAULT', 'Too many requests. Please try again in a minute.', true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record this request
|
// Record this request
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security Headers Middleware
|
* Security Headers Middleware
|
||||||
*
|
*
|
||||||
* Sets various security headers to protect against common web vulnerabilities:
|
* Sets various security headers to protect against common web vulnerabilities:
|
||||||
* - HSTS: Force HTTPS connections
|
* - HSTS: Force HTTPS connections
|
||||||
* - CSP: Content Security Policy to prevent XSS and other injection attacks
|
* - CSP: Content Security Policy to prevent XSS and other injection attacks
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
function applySecurityHeaders($testMode = false) {
|
function applySecurityHeaders($testMode = false) {
|
||||||
$headers = [];
|
$headers = [];
|
||||||
|
|
||||||
// Get current page
|
// Get current page
|
||||||
$current_page = $_GET['page'] ?? 'dashboard';
|
$current_page = $_GET['page'] ?? 'dashboard';
|
||||||
|
|
||||||
|
|
|
@ -2,48 +2,91 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session Middleware
|
* Session Middleware
|
||||||
*
|
*
|
||||||
* Validates session status and handles session timeout.
|
* Validates session status and handles session timeout.
|
||||||
* This middleware should be included in all protected pages.
|
* This middleware should be included in all protected pages.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Start session if not already started
|
function applySessionMiddleware($config, $app_root) {
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
$isTest = defined('PHPUNIT_RUNNING');
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if user is logged in
|
// Access $_SESSION directly in test mode
|
||||||
if (!isset($_SESSION['USER_ID'])) {
|
if (!$isTest) {
|
||||||
header('Location: ' . $app_root . '?page=login');
|
// Start session if not already started
|
||||||
exit();
|
if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
|
||||||
}
|
session_start([
|
||||||
|
'cookie_httponly' => 1,
|
||||||
|
'cookie_secure' => 1,
|
||||||
|
'cookie_samesite' => 'Strict',
|
||||||
|
'gc_maxlifetime' => 1440 // 24 minutes
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check session timeout
|
// Check if user is logged in
|
||||||
$session_timeout = isset($_SESSION['REMEMBER_ME']) ? (30 * 24 * 60 * 60) : 1440; // 30 days or 24 minutes
|
if (!isset($_SESSION['USER_ID'])) {
|
||||||
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $session_timeout)) {
|
if (!$isTest) {
|
||||||
// Session has expired
|
header('Location: ' . $app_root . '?page=login');
|
||||||
session_unset();
|
exit();
|
||||||
session_destroy();
|
}
|
||||||
setcookie('username', '', [
|
return false;
|
||||||
'expires' => time() - 3600,
|
}
|
||||||
'path' => $config['folder'],
|
|
||||||
'domain' => $config['domain'],
|
|
||||||
'secure' => isset($_SERVER['HTTPS']),
|
|
||||||
'httponly' => true,
|
|
||||||
'samesite' => 'Strict'
|
|
||||||
]);
|
|
||||||
header('Location: ' . $app_root . '?page=login&timeout=1');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update last activity time
|
// Check session timeout
|
||||||
$_SESSION['LAST_ACTIVITY'] = time();
|
$session_timeout = isset($_SESSION['REMEMBER_ME']) ? (30 * 24 * 60 * 60) : 1440; // 30 days or 24 minutes
|
||||||
|
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $session_timeout)) {
|
||||||
|
// Session has expired
|
||||||
|
$oldSessionData = $_SESSION;
|
||||||
|
$_SESSION = array();
|
||||||
|
|
||||||
// Regenerate session ID periodically (every 30 minutes)
|
if (!$isTest && session_status() === PHP_SESSION_ACTIVE) {
|
||||||
if (!isset($_SESSION['CREATED'])) {
|
session_unset();
|
||||||
$_SESSION['CREATED'] = time();
|
session_destroy();
|
||||||
} else if (time() - $_SESSION['CREATED'] > 1800) {
|
|
||||||
// Regenerate session ID and update creation time
|
// Start a new session to prevent errors
|
||||||
session_regenerate_id(true);
|
if (!headers_sent()) {
|
||||||
$_SESSION['CREATED'] = time();
|
session_start([
|
||||||
|
'cookie_httponly' => 1,
|
||||||
|
'cookie_secure' => 1,
|
||||||
|
'cookie_samesite' => 'Strict',
|
||||||
|
'gc_maxlifetime' => 1440
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isTest && !headers_sent()) {
|
||||||
|
setcookie('username', '', [
|
||||||
|
'expires' => time() - 3600,
|
||||||
|
'path' => $config['folder'],
|
||||||
|
'domain' => $config['domain'],
|
||||||
|
'secure' => isset($_SERVER['HTTPS']),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Strict'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isTest) {
|
||||||
|
header('Location: ' . $app_root . '?page=login&timeout=1');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update last activity time
|
||||||
|
$_SESSION['LAST_ACTIVITY'] = time();
|
||||||
|
|
||||||
|
// Regenerate session ID periodically (every 30 minutes)
|
||||||
|
if (!isset($_SESSION['CREATED'])) {
|
||||||
|
$_SESSION['CREATED'] = time();
|
||||||
|
} else if (time() - $_SESSION['CREATED'] > 1800) {
|
||||||
|
// Regenerate session ID and update creation time
|
||||||
|
if (!$isTest && !headers_sent() && session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
$oldData = $_SESSION;
|
||||||
|
session_regenerate_id(true);
|
||||||
|
$_SESSION = $oldData;
|
||||||
|
$_SESSION['CREATED'] = time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once dirname(__DIR__, 4) . '/app/classes/database.php';
|
||||||
|
require_once dirname(__DIR__, 4) . '/app/classes/ratelimiter.php';
|
||||||
|
require_once dirname(__DIR__, 4) . '/app/includes/rate_limit_middleware.php';
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class RateLimitMiddlewareTest extends TestCase
|
||||||
|
{
|
||||||
|
private $db;
|
||||||
|
private $rateLimiter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
// Set up test database
|
||||||
|
$this->db = new Database([
|
||||||
|
'type' => 'sqlite',
|
||||||
|
'dbFile' => ':memory:'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create rate limiter table
|
||||||
|
$this->db->getConnection()->exec("CREATE TABLE pages_rate_limits (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip_address TEXT NOT NULL,
|
||||||
|
endpoint TEXT NOT NULL,
|
||||||
|
request_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
// Create ip_whitelist table
|
||||||
|
$this->db->getConnection()->exec("CREATE TABLE ip_whitelist (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip_address TEXT NOT NULL UNIQUE,
|
||||||
|
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
|
||||||
|
description TEXT,
|
||||||
|
created_at TEXT DEFAULT (DATETIME('now')),
|
||||||
|
created_by TEXT
|
||||||
|
)");
|
||||||
|
|
||||||
|
// Create ip_blacklist table
|
||||||
|
$this->db->getConnection()->exec("CREATE TABLE ip_blacklist (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip_address TEXT NOT NULL UNIQUE,
|
||||||
|
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
|
||||||
|
reason TEXT,
|
||||||
|
expiry_time TEXT NULL,
|
||||||
|
created_at TEXT DEFAULT (DATETIME('now')),
|
||||||
|
created_by TEXT
|
||||||
|
)");
|
||||||
|
|
||||||
|
$this->rateLimiter = new RateLimiter($this->db);
|
||||||
|
|
||||||
|
// Mock $_SERVER variables
|
||||||
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||||
|
$_SERVER['REQUEST_URI'] = '/login';
|
||||||
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||||
|
|
||||||
|
// Define testing constant
|
||||||
|
if (!defined('TESTING')) {
|
||||||
|
define('TESTING', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
// Clean up rate limit records
|
||||||
|
$this->db->getConnection()->exec('DELETE FROM pages_rate_limits');
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRateLimitMiddleware()
|
||||||
|
{
|
||||||
|
// Test multiple requests
|
||||||
|
for ($i = 1; $i <= 5; $i++) {
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
|
||||||
|
if ($i <= 5) {
|
||||||
|
// First 5 requests should pass
|
||||||
|
$this->assertTrue($result);
|
||||||
|
} else {
|
||||||
|
// 6th and subsequent requests should be blocked
|
||||||
|
$this->assertFalse($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRateLimitBypass()
|
||||||
|
{
|
||||||
|
// Test AJAX request bypass
|
||||||
|
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRateLimitReset()
|
||||||
|
{
|
||||||
|
// Use up the rate limit
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for rate limit to reset (use a short window for testing)
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
// Should be able to make request again
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDifferentEndpoints()
|
||||||
|
{
|
||||||
|
// Use up rate limit for login
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should still be able to access different endpoint
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/dashboard');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDifferentIpAddresses()
|
||||||
|
{
|
||||||
|
// Use up rate limit for first IP
|
||||||
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different IP should not be affected
|
||||||
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhitelistedIp()
|
||||||
|
{
|
||||||
|
// Add IP to whitelist
|
||||||
|
$this->db->execute(
|
||||||
|
'INSERT INTO ip_whitelist (ip_address, description, created_by) VALUES (?, ?, ?)',
|
||||||
|
['127.0.0.1', 'Test whitelist', 'PHPUnit']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should be able to make more requests than limit
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBlacklistedIp()
|
||||||
|
{
|
||||||
|
// Add IP to blacklist
|
||||||
|
$this->db->execute(
|
||||||
|
'INSERT INTO ip_blacklist (ip_address, reason, created_by) VALUES (?, ?, ?)',
|
||||||
|
['127.0.0.1', 'Test blacklist', 'PHPUnit']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should be blocked immediately
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertFalse($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRateLimitPersistence()
|
||||||
|
{
|
||||||
|
// Use up some of the rate limit
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy and restart session
|
||||||
|
//session_destroy();
|
||||||
|
//session_start();
|
||||||
|
|
||||||
|
// Should still count previous requests
|
||||||
|
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once dirname(__DIR__, 4) . '/app/includes/session_middleware.php';
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class SessionMiddlewareTest extends TestCase
|
||||||
|
{
|
||||||
|
protected $config;
|
||||||
|
protected $app_root;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
// Mock server variables
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
|
||||||
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||||
|
$_SERVER['HTTPS'] = 'on';
|
||||||
|
|
||||||
|
// Set up test config
|
||||||
|
$this->config = [
|
||||||
|
'folder' => '/app',
|
||||||
|
'domain' => 'localhost'
|
||||||
|
];
|
||||||
|
$this->app_root = 'https://localhost/app';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionStart()
|
||||||
|
{
|
||||||
|
$_SESSION = ['USER_ID' => 1];
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
$this->assertArrayHasKey('LAST_ACTIVITY', $_SESSION);
|
||||||
|
$this->assertArrayHasKey('CREATED', $_SESSION);
|
||||||
|
$this->assertArrayHasKey('USER_ID', $_SESSION);
|
||||||
|
$this->assertEquals(1, $_SESSION['USER_ID']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionTimeout()
|
||||||
|
{
|
||||||
|
$_SESSION = [
|
||||||
|
'USER_ID' => 1,
|
||||||
|
'LAST_ACTIVITY' => time() - 1500 // 25 minutes ago
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertFalse($result);
|
||||||
|
$this->assertArrayNotHasKey('USER_ID', $_SESSION, 'Session should be cleared after timeout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionRegeneration()
|
||||||
|
{
|
||||||
|
$now = time();
|
||||||
|
$_SESSION = [
|
||||||
|
'USER_ID' => 1,
|
||||||
|
'CREATED' => $now - 1900 // 31+ minutes ago
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
$this->assertEquals(1, $_SESSION['USER_ID']);
|
||||||
|
$this->assertGreaterThanOrEqual($now - 1900, $_SESSION['CREATED']);
|
||||||
|
$this->assertLessThanOrEqual($now + 10, $_SESSION['CREATED']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRememberMe()
|
||||||
|
{
|
||||||
|
$_SESSION = [
|
||||||
|
'USER_ID' => 1,
|
||||||
|
'REMEMBER_ME' => true,
|
||||||
|
'LAST_ACTIVITY' => time() - 86500 // More than 24 hours ago
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
$this->assertArrayHasKey('USER_ID', $_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoUserSession()
|
||||||
|
{
|
||||||
|
$_SESSION = [];
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertFalse($result);
|
||||||
|
$this->assertArrayNotHasKey('USER_ID', $_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionHeaders()
|
||||||
|
{
|
||||||
|
$_SESSION = [
|
||||||
|
'USER_ID' => 1,
|
||||||
|
'LAST_ACTIVITY' => time() - 1500 // 25 minutes ago
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = applySessionMiddleware($this->config, $this->app_root);
|
||||||
|
|
||||||
|
$this->assertFalse($result);
|
||||||
|
$this->assertArrayNotHasKey('USER_ID', $_SESSION, 'Session should be cleared after timeout');
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ class SecurityHeadersTest extends TestCase
|
||||||
{
|
{
|
||||||
// Apply security headers in test mode
|
// Apply security headers in test mode
|
||||||
$headers = \applySecurityHeaders(true);
|
$headers = \applySecurityHeaders(true);
|
||||||
|
|
||||||
// Check security headers
|
// Check security headers
|
||||||
$this->assertContains('X-Frame-Options: DENY', $headers);
|
$this->assertContains('X-Frame-Options: DENY', $headers);
|
||||||
$this->assertContains('X-XSS-Protection: 1; mode=block', $headers);
|
$this->assertContains('X-XSS-Protection: 1; mode=block', $headers);
|
||||||
|
@ -32,7 +32,7 @@ class SecurityHeadersTest extends TestCase
|
||||||
{
|
{
|
||||||
// Apply security headers in test mode
|
// Apply security headers in test mode
|
||||||
$headers = \applySecurityHeaders(true);
|
$headers = \applySecurityHeaders(true);
|
||||||
|
|
||||||
// Get CSP header
|
// Get CSP header
|
||||||
$cspHeader = '';
|
$cspHeader = '';
|
||||||
foreach ($headers as $header) {
|
foreach ($headers as $header) {
|
||||||
|
@ -138,10 +138,10 @@ class SecurityHeadersTest extends TestCase
|
||||||
public function testPermissionsPolicyForMediaEnabledPages()
|
public function testPermissionsPolicyForMediaEnabledPages()
|
||||||
{
|
{
|
||||||
$_SERVER['REQUEST_URI'] = '/media/upload';
|
$_SERVER['REQUEST_URI'] = '/media/upload';
|
||||||
|
|
||||||
// Apply security headers in test mode
|
// Apply security headers in test mode
|
||||||
$headers = \applySecurityHeaders(true);
|
$headers = \applySecurityHeaders(true);
|
||||||
|
|
||||||
// Get Permissions-Policy header
|
// Get Permissions-Policy header
|
||||||
$permissionsHeader = '';
|
$permissionsHeader = '';
|
||||||
foreach ($headers as $header) {
|
foreach ($headers as $header) {
|
||||||
|
|
|
@ -7,23 +7,23 @@ class TestCase extends PHPUnit\Framework\TestCase
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// Set up test environment
|
// Set up test environment
|
||||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||||
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
|
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
|
||||||
|
|
||||||
// Include common app files
|
// Include common app files
|
||||||
require_once dirname(__DIR__, 2) . '/app/includes/config.php';
|
require_once dirname(__DIR__, 2) . '/app/includes/config.php';
|
||||||
require_once dirname(__DIR__, 2) . '/app/includes/functions.php';
|
require_once dirname(__DIR__, 2) . '/app/includes/functions.php';
|
||||||
|
|
||||||
// Clean up any existing session
|
// Clean up any existing session
|
||||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
session_destroy();
|
session_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset session data
|
// Reset session data
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
|
|
||||||
// Only start session if headers haven't been sent
|
// Only start session if headers haven't been sent
|
||||||
if (!headers_sent() && session_status() === PHP_SESSION_NONE) {
|
if (!headers_sent() && session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
|
@ -37,7 +37,7 @@ class TestCase extends PHPUnit\Framework\TestCase
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
session_destroy();
|
session_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Session Handler
|
||||||
|
*
|
||||||
|
* Provides session handling functionality for PHPUnit tests.
|
||||||
|
* This class ensures proper session management during testing.
|
||||||
|
*/
|
||||||
|
class TestSessionHandler implements SessionHandlerInterface
|
||||||
|
{
|
||||||
|
private static $initialized = false;
|
||||||
|
private $data = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize session settings
|
||||||
|
*/
|
||||||
|
public static function init()
|
||||||
|
{
|
||||||
|
if (!self::$initialized && !headers_sent()) {
|
||||||
|
// Clean up any existing session
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_write_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_COOKIE[session_name()])) {
|
||||||
|
setcookie(session_name(), '', time()-3600, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION = array();
|
||||||
|
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set session configuration
|
||||||
|
session_name('jilo');
|
||||||
|
|
||||||
|
// Start a new session
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
session_start([
|
||||||
|
'cookie_httponly' => 1,
|
||||||
|
'cookie_secure' => 1,
|
||||||
|
'cookie_samesite' => 'Strict',
|
||||||
|
'gc_maxlifetime' => 1440 // 24 minutes
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a fresh session
|
||||||
|
*/
|
||||||
|
public static function startSession()
|
||||||
|
{
|
||||||
|
// Clean up any existing session first
|
||||||
|
self::cleanupSession();
|
||||||
|
|
||||||
|
// Initialize new session
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
|
||||||
|
session_name('jilo');
|
||||||
|
session_start([
|
||||||
|
'cookie_httponly' => 1,
|
||||||
|
'cookie_secure' => 1,
|
||||||
|
'cookie_samesite' => 'Strict',
|
||||||
|
'gc_maxlifetime' => 1440
|
||||||
|
]);
|
||||||
|
self::$initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the current session
|
||||||
|
*/
|
||||||
|
public static function cleanupSession()
|
||||||
|
{
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_write_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_COOKIE[session_name()])) {
|
||||||
|
setcookie(session_name(), '', time()-3600, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION = array();
|
||||||
|
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function open($path, $name): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read($id): string|false
|
||||||
|
{
|
||||||
|
return $this->data[$id] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($id, $data): bool
|
||||||
|
{
|
||||||
|
$this->data[$id] = $data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id): bool
|
||||||
|
{
|
||||||
|
unset($this->data[$id]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function gc($max_lifetime): int|false
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -107,7 +107,7 @@ class AgentTest extends TestCase
|
||||||
'secret_key' => 'test_secret',
|
'secret_key' => 'test_secret',
|
||||||
'check_period' => 60
|
'check_period' => 60
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->agent->addAgent($hostId, $data);
|
$this->agent->addAgent($hostId, $data);
|
||||||
|
|
||||||
// Test getting agent details
|
// Test getting agent details
|
||||||
|
@ -127,7 +127,7 @@ class AgentTest extends TestCase
|
||||||
'secret_key' => 'test_secret',
|
'secret_key' => 'test_secret',
|
||||||
'check_period' => 60
|
'check_period' => 60
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->agent->addAgent($hostId, $data);
|
$this->agent->addAgent($hostId, $data);
|
||||||
|
|
||||||
// Get agent ID
|
// Get agent ID
|
||||||
|
@ -167,7 +167,7 @@ class AgentTest extends TestCase
|
||||||
'secret_key' => 'test_secret',
|
'secret_key' => 'test_secret',
|
||||||
'check_period' => 60
|
'check_period' => 60
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->agent->addAgent($hostId, $data);
|
$this->agent->addAgent($hostId, $data);
|
||||||
|
|
||||||
// Get agent ID
|
// Get agent ID
|
||||||
|
@ -197,7 +197,7 @@ class AgentTest extends TestCase
|
||||||
'secret_key' => 'test_secret',
|
'secret_key' => 'test_secret',
|
||||||
'check_period' => 60
|
'check_period' => 60
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->agent->addAgent($hostId, $data);
|
$this->agent->addAgent($hostId, $data);
|
||||||
|
|
||||||
// Get agent ID
|
// Get agent ID
|
||||||
|
@ -210,7 +210,7 @@ class AgentTest extends TestCase
|
||||||
->setConstructorArgs([$this->db])
|
->setConstructorArgs([$this->db])
|
||||||
->onlyMethods(['fetchAgent'])
|
->onlyMethods(['fetchAgent'])
|
||||||
->getMock();
|
->getMock();
|
||||||
|
|
||||||
$mockResponse = json_encode([
|
$mockResponse = json_encode([
|
||||||
'status' => 'ok',
|
'status' => 'ok',
|
||||||
'metrics' => [
|
'metrics' => [
|
||||||
|
@ -226,7 +226,7 @@ class AgentTest extends TestCase
|
||||||
|
|
||||||
$response = $mockAgent->fetchAgent($agentId);
|
$response = $mockAgent->fetchAgent($agentId);
|
||||||
$this->assertJson($response);
|
$this->assertJson($response);
|
||||||
|
|
||||||
$data = json_decode($response, true);
|
$data = json_decode($response, true);
|
||||||
$this->assertEquals('ok', $data['status']);
|
$this->assertEquals('ok', $data['status']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ class DatabaseTest extends TestCase
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// Set development environment for detailed errors
|
// Set development environment for detailed errors
|
||||||
global $config;
|
global $config;
|
||||||
$config['environment'] = 'development';
|
$config['environment'] = 'development';
|
||||||
|
|
||||||
$this->config = [
|
$this->config = [
|
||||||
'type' => 'sqlite',
|
'type' => 'sqlite',
|
||||||
'dbFile' => ':memory:'
|
'dbFile' => ':memory:'
|
||||||
|
@ -39,7 +39,7 @@ class DatabaseTest extends TestCase
|
||||||
'user' => 'test',
|
'user' => 'test',
|
||||||
'password' => 'test'
|
'password' => 'test'
|
||||||
];
|
];
|
||||||
|
|
||||||
$mariadbConfig = [
|
$mariadbConfig = [
|
||||||
'type' => 'mariadb',
|
'type' => 'mariadb',
|
||||||
'host' => 'invalid-host',
|
'host' => 'invalid-host',
|
||||||
|
@ -48,11 +48,11 @@ class DatabaseTest extends TestCase
|
||||||
'user' => 'test',
|
'user' => 'test',
|
||||||
'password' => 'test'
|
'password' => 'test'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Both should fail to connect and return null
|
// Both should fail to connect and return null
|
||||||
$mysqlDb = new Database($mysqlConfig);
|
$mysqlDb = new Database($mysqlConfig);
|
||||||
$this->assertNull($mysqlDb->getConnection());
|
$this->assertNull($mysqlDb->getConnection());
|
||||||
|
|
||||||
$mariaDb = new Database($mariadbConfig);
|
$mariaDb = new Database($mariadbConfig);
|
||||||
$this->assertNull($mariaDb->getConnection());
|
$this->assertNull($mariaDb->getConnection());
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class DatabaseTest extends TestCase
|
||||||
'user' => 'test',
|
'user' => 'test',
|
||||||
'password' => 'test'
|
'password' => 'test'
|
||||||
];
|
];
|
||||||
|
|
||||||
$invalidDb = new Database($invalidConfig);
|
$invalidDb = new Database($invalidConfig);
|
||||||
$this->assertNull($invalidDb->getConnection());
|
$this->assertNull($invalidDb->getConnection());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ class FeedbackTest extends TestCase
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// Start session for flash messages
|
// Start session for flash messages
|
||||||
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
|
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize session variables
|
// Initialize session variables
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
$_SESSION['flash_messages'] = [];
|
$_SESSION['flash_messages'] = [];
|
||||||
|
@ -34,10 +34,10 @@ class FeedbackTest extends TestCase
|
||||||
// Add a test message
|
// Add a test message
|
||||||
Feedback::flash('LOGIN', 'LOGIN_SUCCESS', 'Test message');
|
Feedback::flash('LOGIN', 'LOGIN_SUCCESS', 'Test message');
|
||||||
$messages = $_SESSION['flash_messages'];
|
$messages = $_SESSION['flash_messages'];
|
||||||
|
|
||||||
$this->assertIsArray($messages);
|
$this->assertIsArray($messages);
|
||||||
$this->assertCount(1, $messages);
|
$this->assertCount(1, $messages);
|
||||||
|
|
||||||
$message = $messages[0];
|
$message = $messages[0];
|
||||||
$this->assertEquals('LOGIN', $message['category']);
|
$this->assertEquals('LOGIN', $message['category']);
|
||||||
$this->assertEquals('LOGIN_SUCCESS', $message['key']);
|
$this->assertEquals('LOGIN_SUCCESS', $message['key']);
|
||||||
|
@ -67,7 +67,7 @@ class FeedbackTest extends TestCase
|
||||||
public function testGetMessageData()
|
public function testGetMessageData()
|
||||||
{
|
{
|
||||||
$data = Feedback::getMessageData('LOGIN', 'LOGIN_SUCCESS', 'Test message');
|
$data = Feedback::getMessageData('LOGIN', 'LOGIN_SUCCESS', 'Test message');
|
||||||
|
|
||||||
$this->assertIsArray($data);
|
$this->assertIsArray($data);
|
||||||
$this->assertEquals(Feedback::TYPE_SUCCESS, $data['type']);
|
$this->assertEquals(Feedback::TYPE_SUCCESS, $data['type']);
|
||||||
$this->assertEquals('Test message', $data['message']);
|
$this->assertEquals('Test message', $data['message']);
|
||||||
|
|
|
@ -56,7 +56,7 @@ class LogTest extends TestCase
|
||||||
$stmt = $this->db->getConnection()->prepare("SELECT * FROM logs WHERE scope = ?");
|
$stmt = $this->db->getConnection()->prepare("SELECT * FROM logs WHERE scope = ?");
|
||||||
$stmt->execute(['test']);
|
$stmt->execute(['test']);
|
||||||
$log = $stmt->fetch(PDO::FETCH_ASSOC);
|
$log = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$this->assertEquals(1, $log['user_id']);
|
$this->assertEquals(1, $log['user_id']);
|
||||||
$this->assertEquals('Test message', $log['message']);
|
$this->assertEquals('Test message', $log['message']);
|
||||||
$this->assertEquals('test', $log['scope']);
|
$this->assertEquals('test', $log['scope']);
|
||||||
|
@ -67,7 +67,7 @@ class LogTest extends TestCase
|
||||||
// Insert test logs
|
// Insert test logs
|
||||||
$this->log->insertLog(1, 'Test message 1', 'user');
|
$this->log->insertLog(1, 'Test message 1', 'user');
|
||||||
$this->log->insertLog(1, 'Test message 2', 'user');
|
$this->log->insertLog(1, 'Test message 2', 'user');
|
||||||
|
|
||||||
$logs = $this->log->readLog(1, 'user');
|
$logs = $this->log->readLog(1, 'user');
|
||||||
$this->assertCount(2, $logs);
|
$this->assertCount(2, $logs);
|
||||||
$this->assertEquals('Test message 1', $logs[0]['message']);
|
$this->assertEquals('Test message 1', $logs[0]['message']);
|
||||||
|
@ -80,15 +80,15 @@ class LogTest extends TestCase
|
||||||
$this->log->insertLog(1, 'Old message', 'user');
|
$this->log->insertLog(1, 'Old message', 'user');
|
||||||
sleep(1); // Ensure different timestamps
|
sleep(1); // Ensure different timestamps
|
||||||
$this->log->insertLog(1, 'New message', 'user');
|
$this->log->insertLog(1, 'New message', 'user');
|
||||||
|
|
||||||
$now = date('Y-m-d H:i:s');
|
$now = date('Y-m-d H:i:s');
|
||||||
$oneHourAgo = date('Y-m-d H:i:s', strtotime('-1 hour'));
|
$oneHourAgo = date('Y-m-d H:i:s', strtotime('-1 hour'));
|
||||||
|
|
||||||
$logs = $this->log->readLog(1, 'user', 0, '', [
|
$logs = $this->log->readLog(1, 'user', 0, '', [
|
||||||
'from_time' => $oneHourAgo,
|
'from_time' => $oneHourAgo,
|
||||||
'until_time' => $now
|
'until_time' => $now
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertCount(2, $logs);
|
$this->assertCount(2, $logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +98,11 @@ class LogTest extends TestCase
|
||||||
$this->log->insertLog(1, 'Message 1', 'user');
|
$this->log->insertLog(1, 'Message 1', 'user');
|
||||||
$this->log->insertLog(1, 'Message 2', 'user');
|
$this->log->insertLog(1, 'Message 2', 'user');
|
||||||
$this->log->insertLog(1, 'Message 3', 'user');
|
$this->log->insertLog(1, 'Message 3', 'user');
|
||||||
|
|
||||||
// Test with limit
|
// Test with limit
|
||||||
$logs = $this->log->readLog(1, 'user', 0, 2);
|
$logs = $this->log->readLog(1, 'user', 0, 2);
|
||||||
$this->assertCount(2, $logs);
|
$this->assertCount(2, $logs);
|
||||||
|
|
||||||
// Test with offset
|
// Test with offset
|
||||||
$logs = $this->log->readLog(1, 'user', 2, 2);
|
$logs = $this->log->readLog(1, 'user', 2, 2);
|
||||||
$this->assertCount(1, $logs);
|
$this->assertCount(1, $logs);
|
||||||
|
@ -113,11 +113,11 @@ class LogTest extends TestCase
|
||||||
// Insert test logs
|
// Insert test logs
|
||||||
$this->log->insertLog(1, 'Test message', 'user');
|
$this->log->insertLog(1, 'Test message', 'user');
|
||||||
$this->log->insertLog(1, 'Another message', 'user');
|
$this->log->insertLog(1, 'Another message', 'user');
|
||||||
|
|
||||||
$logs = $this->log->readLog(1, 'user', 0, '', [
|
$logs = $this->log->readLog(1, 'user', 0, '', [
|
||||||
'message' => 'Test'
|
'message' => 'Test'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertCount(1, $logs);
|
$this->assertCount(1, $logs);
|
||||||
$this->assertEquals('Test message', $logs[0]['message']);
|
$this->assertEquals('Test message', $logs[0]['message']);
|
||||||
}
|
}
|
||||||
|
@ -127,11 +127,11 @@ class LogTest extends TestCase
|
||||||
// Insert test logs for different users
|
// Insert test logs for different users
|
||||||
$this->log->insertLog(1, 'User 1 message', 'user');
|
$this->log->insertLog(1, 'User 1 message', 'user');
|
||||||
$this->log->insertLog(2, 'User 2 message', 'user');
|
$this->log->insertLog(2, 'User 2 message', 'user');
|
||||||
|
|
||||||
$logs = $this->log->readLog(1, 'user', 0, '', [
|
$logs = $this->log->readLog(1, 'user', 0, '', [
|
||||||
'id' => 1
|
'id' => 1
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertCount(1, $logs);
|
$this->assertCount(1, $logs);
|
||||||
$this->assertEquals('User 1 message', $logs[0]['message']);
|
$this->assertEquals('User 1 message', $logs[0]['message']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ class PlatformTest extends TestCase
|
||||||
$stmt = $this->db->getConnection()->prepare('SELECT * FROM platforms WHERE name = ?');
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM platforms WHERE name = ?');
|
||||||
$stmt->execute([$data['name']]);
|
$stmt->execute([$data['name']]);
|
||||||
$platform = $stmt->fetch(PDO::FETCH_ASSOC);
|
$platform = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$this->assertNotNull($platform);
|
$this->assertNotNull($platform);
|
||||||
$this->assertEquals($data['name'], $platform['name']);
|
$this->assertEquals($data['name'], $platform['name']);
|
||||||
$this->assertEquals($data['jitsi_url'], $platform['jitsi_url']);
|
$this->assertEquals($data['jitsi_url'], $platform['jitsi_url']);
|
||||||
|
|
|
@ -3,18 +3,14 @@
|
||||||
// Set test environment
|
// Set test environment
|
||||||
define('PHPUNIT_RUNNING', true);
|
define('PHPUNIT_RUNNING', true);
|
||||||
|
|
||||||
// Configure session before starting it
|
// Configure session before any output
|
||||||
ini_set('session.use_strict_mode', '1');
|
if (!headers_sent()) {
|
||||||
ini_set('session.use_only_cookies', '1');
|
// Configure session settings
|
||||||
ini_set('session.cookie_httponly', '1');
|
ini_set('session.cookie_httponly', 1);
|
||||||
ini_set('session.cookie_secure', '1');
|
ini_set('session.cookie_secure', 1);
|
||||||
ini_set('session.cookie_samesite', 'Lax');
|
ini_set('session.cookie_samesite', 'Strict');
|
||||||
ini_set('session.gc_maxlifetime', 1440);
|
ini_set('session.gc_maxlifetime', 1440); // 24 minutes
|
||||||
|
}
|
||||||
// Start session if not already started
|
|
||||||
//if (session_status() === PHP_SESSION_NONE) {
|
|
||||||
// session_start();
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Load Composer's autoloader
|
// Load Composer's autoloader
|
||||||
require_once __DIR__ . '/vendor/autoload.php';
|
require_once __DIR__ . '/vendor/autoload.php';
|
||||||
|
@ -33,26 +29,9 @@ $GLOBALS['config'] = [
|
||||||
'db' => [
|
'db' => [
|
||||||
'type' => 'sqlite',
|
'type' => 'sqlite',
|
||||||
'dbFile' => ':memory:'
|
'dbFile' => ':memory:'
|
||||||
],
|
|
||||||
'folder' => '/',
|
|
||||||
'domain' => 'localhost',
|
|
||||||
'login' => [
|
|
||||||
'max_attempts' => 5,
|
|
||||||
'lockout_time' => 900
|
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initialize system_messages array
|
|
||||||
$GLOBALS['system_messages'] = [];
|
|
||||||
|
|
||||||
// Set up server variables
|
|
||||||
$_SERVER['PHP_SELF'] = '/index.php';
|
|
||||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
|
||||||
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
|
|
||||||
$_SERVER['HTTP_HOST'] = 'localhost';
|
|
||||||
$_SERVER['REQUEST_URI'] = '/?page=login';
|
|
||||||
$_SERVER['HTTPS'] = 'on';
|
|
||||||
|
|
||||||
// Define global connectDB function
|
// Define global connectDB function
|
||||||
if (!function_exists('connectDB')) {
|
if (!function_exists('connectDB')) {
|
||||||
function connectDB($config) {
|
function connectDB($config) {
|
||||||
|
@ -62,3 +41,9 @@ if (!function_exists('connectDB')) {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up server variables
|
||||||
|
$_SERVER['PHP_SELF'] = '/index.php';
|
||||||
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit Test Browser';
|
||||||
|
$_SERVER['HTTPS'] = 'on';
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[Session]
|
||||||
|
session.cookie_httponly = 1
|
||||||
|
session.use_only_cookies = 1
|
||||||
|
session.cookie_secure = 1
|
||||||
|
session.cookie_samesite = "Strict"
|
||||||
|
session.gc_maxlifetime = 1440
|
||||||
|
session.use_strict_mode = 1
|
Loading…
Reference in New Issue