Add comprehensive unit tests for Security, UserModel, and Validation utilities
- Implemented SecurityTest to validate token generation, CSRF protection, input sanitization, and rate limiting. - Created UserModelTest to ensure correct database operations for user management, including creation, updating, banning, and fetching active users. - Developed ValidationTest to verify input validation and sanitization for user IDs, nicknames, messages, and API requests. - Introduced Security and Validation utility classes with methods for secure token generation, input sanitization, and comprehensive validation rules.
This commit is contained in:
parent
5692874b10
commit
41cd7a4fd8
32 changed files with 5796 additions and 368 deletions
178
includes/Config.php
Normal file
178
includes/Config.php
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
/**
|
||||
* Configuration Management Class
|
||||
* Loads and manages application configuration from .env files
|
||||
*/
|
||||
|
||||
class Config
|
||||
{
|
||||
private static $config = [];
|
||||
private static $loaded = false;
|
||||
|
||||
/**
|
||||
* Load configuration from environment and .env files
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
if (self::$loaded) {
|
||||
return self::$config;
|
||||
}
|
||||
|
||||
// Load environment variables
|
||||
self::loadEnvironment();
|
||||
|
||||
// Load .env file if it exists
|
||||
self::loadDotEnv();
|
||||
|
||||
self::$loaded = true;
|
||||
return self::$config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configuration value
|
||||
*/
|
||||
public static function get($key, $default = null)
|
||||
{
|
||||
$config = self::load();
|
||||
|
||||
// Support dot notation (e.g., 'database.host')
|
||||
$keys = explode('.', $key);
|
||||
$value = $config;
|
||||
|
||||
foreach ($keys as $k) {
|
||||
if (!isset($value[$k])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$k];
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a configuration value (runtime only)
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
$keys = explode('.', $key);
|
||||
$config = &self::$config;
|
||||
|
||||
foreach ($keys as $i => $k) {
|
||||
if ($i === count($keys) - 1) {
|
||||
$config[$k] = $value;
|
||||
} else {
|
||||
if (!isset($config[$k]) || !is_array($config[$k])) {
|
||||
$config[$k] = [];
|
||||
}
|
||||
$config = &$config[$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load system environment variables
|
||||
*/
|
||||
private static function loadEnvironment()
|
||||
{
|
||||
// System environment variables get precedence
|
||||
foreach ($_ENV as $key => $value) {
|
||||
self::setFromEnv($key, $value);
|
||||
}
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (strpos($key, 'APP_') === 0 || strpos($key, 'DB_') === 0 ||
|
||||
strpos($key, 'STREAM_') === 0 || strpos($key, 'ADMIN_') === 0) {
|
||||
self::setFromEnv($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load .env file
|
||||
*/
|
||||
private static function loadDotEnv()
|
||||
{
|
||||
$envFile = __DIR__ . '/../.env';
|
||||
|
||||
if (!file_exists($envFile)) {
|
||||
error_log("Warning: .env file not found. Using default configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
|
||||
// Skip comments
|
||||
if (strpos($line, '#') === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse key=value pairs
|
||||
if (strpos($line, '=') !== false) {
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
|
||||
// Remove quotes if present
|
||||
if ((strpos($value, '"') === 0 && strrpos($value, '"') === strlen($value) - 1) ||
|
||||
(strpos($value, "'") === 0 && strrpos($value, "'") === strlen($value) - 1)) {
|
||||
$value = substr($value, 1, -1);
|
||||
}
|
||||
|
||||
self::setFromEnv($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set configuration value from environment variable
|
||||
*/
|
||||
private static function setFromEnv($key, $value)
|
||||
{
|
||||
// Convert environment naming to configuration naming
|
||||
$configKey = strtolower(str_replace('_', '.', $key));
|
||||
|
||||
// Type coercion for boolean values
|
||||
if (in_array($value, ['true', 'false'])) {
|
||||
$value = $value === 'true';
|
||||
}
|
||||
|
||||
// Type coercion for numeric values
|
||||
if (is_numeric($value) && !is_string($value)) {
|
||||
$value = strpos($value, '.') !== false ? (float)$value : (int)$value;
|
||||
}
|
||||
|
||||
// Handle arrays (comma-separated)
|
||||
if (strpos($value, ',') !== false) {
|
||||
$value = array_map('trim', explode(',', $value));
|
||||
}
|
||||
|
||||
self::set($configKey, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all configuration as a flattened array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
return self::load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are in a specific environment
|
||||
*/
|
||||
public static function isEnvironment($env)
|
||||
{
|
||||
return self::get('app.env') === $env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if debug mode is enabled
|
||||
*/
|
||||
public static function isDebug()
|
||||
{
|
||||
return self::get('app.debug', false);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue