File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/scratch/test_security_validation_suite.php
Back
<?php /** * Comprehensive Functional Test Suite for Security, Validation & Error Handling Standard (Prompt 16) */ require_once __DIR__ . '/../database/Database.php'; require_once __DIR__ . '/../app/Helpers/Security.php'; require_once __DIR__ . '/../app/Helpers/Logger.php'; require_once __DIR__ . '/../app/Helpers/Validator.php'; require_once __DIR__ . '/../app/Helpers/Auth.php'; require_once __DIR__ . '/../app/Helpers/AuthGuard.php'; require_once __DIR__ . '/../app/Helpers/DB.php'; require_once __DIR__ . '/../app/Core/ErrorHandler.php'; require_once __DIR__ . '/../app/Services/Security/RateLimiter.php'; require_once __DIR__ . '/../app/Services/Security/SecureUploadService.php'; echo "=== CARGOO SECURITY, VALIDATION & ERROR HANDLING TEST SUITE ===" . PHP_EOL . PHP_EOL; // ── 1. INPUT VALIDATION ENGINE ────────────────────────────────────── echo "[1] Testing Validation Engine & Rules..." . PHP_EOL; // 1.1 Thai ID Checksum Algorithm $validThaiId = '1100400874943'; // Sum=195, 195%11=8, (11-8)%10=3 $invalidThaiId = '1100400874940'; $vThaiPass = Validator::make(['id_card' => $validThaiId], ['id_card' => 'thai_id']); assert($vThaiPass->validate() === true, "Valid Thai ID must pass checksum"); echo " ✓ Thai National ID Checksum (Valid ID): PASS" . PHP_EOL; $vThaiFail = Validator::make(['id_card' => $invalidThaiId], ['id_card' => 'thai_id']); assert($vThaiFail->validate() === false, "Invalid Thai ID must fail checksum"); echo " ✓ Thai National ID Checksum (Invalid ID): PASS (Blocked: '{$vThaiFail->firstError()}')" . PHP_EOL; // 1.2 Phone, Email, Username, Range, Whitelist $testData = [ 'username' => 'safe_user99', 'email' => 'user@cargoo.local', 'phone' => '0812345678', 'status' => 'active', 'quantity' => 5, 'price' => 199.50 ]; $testRules = [ 'username' => 'required|username', 'email' => 'required|email', 'phone' => 'required|phone', 'status' => 'required|in:active,inactive,pending', 'quantity' => 'required|integer|between:1,100', 'price' => 'required|numeric|gt:0' ]; $vAll = Validator::make($testData, $testRules); assert($vAll->validate() === true, "Standard inputs must pass validation"); echo " ✓ General Data Type & Format Rules: PASS" . PHP_EOL; // 1.3 validateOrFail() with ValidationException $failed = false; try { Validator::validateOrFail(['email' => 'not-an-email'], ['email' => 'required|email']); } catch (ValidationException $e) { $failed = true; assert($e->getStatusCode() === 422, "ValidationException must have status 422"); assert(!empty($e->getErrors()['email']), "Must contain email error"); } assert($failed === true, "validateOrFail must throw ValidationException"); echo " ✓ Validator::validateOrFail() Exception Throwing: PASS (HTTP 422)" . PHP_EOL; // 1.4 Sanitization $rawInput = ['name' => ' <script>alert("xss")</script> สมชาย ', 'password' => 'secret123', 'extra' => 'discard']; $sanitized = Validator::sanitize($rawInput, ['name', 'password']); assert($sanitized['name'] === 'alert("xss") สมชาย', "XSS tags must be stripped"); assert(!isset($sanitized['extra']), "Disallowed fields must be excluded"); echo " ✓ Validator::sanitize() Input Cleaning: PASS" . PHP_EOL; // ── 2. 5-LAYER AUTHORIZATION & OWNERSHIP GUARD ────────────────────── echo PHP_EOL . "[2] Testing 5-Layer Authorization & Ownership Guard..." . PHP_EOL; // Mock session user $_SESSION['user_id'] = 10; $_SESSION['user_roles'] = ['customer', 'seller']; // 2.1 Authenticated check $authedId = AuthGuard::requireAuth(); assert($authedId === 10, "Authenticated user ID must match"); echo " ✓ AuthGuard::requireAuth(): PASS" . PHP_EOL; // 2.2 Role check AuthGuard::requireRole(['seller', 'admin']); echo " ✓ AuthGuard::requireRole(['seller']): PASS" . PHP_EOL; // 2.3 Ownership Guard (Allow owner ID: 10, Block ID: 99) AuthGuard::requireOwnership(10); $blocked = false; try { AuthGuard::requireOwnership(99); } catch (AuthorizationException $e) { $blocked = true; assert($e->getStatusCode() === 403, "Must be 403 Forbidden"); } assert($blocked === true, "Must block horizontal IDOR access"); echo " ✓ AuthGuard::requireOwnership() IDOR Protection: PASS (HTTP 403 Forbidden)" . PHP_EOL; // ── 3. DATABASE TRANSACTION & CONCURRENCY HELPER ──────────────────── echo PHP_EOL . "[3] Testing Database Transaction & Atomic Helpers..." . PHP_EOL; $db = Database::getInstance(); // 3.1 Transaction Commit on success $transResult = DB::transaction(function($pdo) { $pdo->exec("INSERT INTO rate_limits (rate_key, hits, expires_at) VALUES ('test_trans_1', 1, " . (time() + 100) . ")"); return "SUCCESS"; }); assert($transResult === "SUCCESS", "Transaction callback return value must match"); $check1 = $db->query("SELECT hits FROM rate_limits WHERE rate_key = 'test_trans_1'")->fetch(); assert($check1 !== false, "Committed record must exist in DB"); echo " ✓ DB::transaction() Commit: PASS" . PHP_EOL; // 3.2 Transaction Rollback on Exception $rolledBack = false; try { DB::transaction(function($pdo) { $pdo->exec("INSERT INTO rate_limits (rate_key, hits, expires_at) VALUES ('test_trans_rollback', 1, " . (time() + 100) . ")"); throw new Exception("Force transaction error"); }); } catch (Exception $e) { $rolledBack = true; } assert($rolledBack === true, "Exception must be caught"); $checkRollback = $db->query("SELECT hits FROM rate_limits WHERE rate_key = 'test_trans_rollback'")->fetch(); assert($checkRollback === false, "Rolled back record must NOT exist in DB"); echo " ✓ DB::transaction() Automatic Rollback on Error: PASS" . PHP_EOL; // Clean test records $db->exec("DELETE FROM rate_limits WHERE rate_key LIKE 'test_trans_%'"); // ── 4. RATE LIMITING & ABUSE PROTECTION ───────────────────────────── echo PHP_EOL . "[4] Testing RateLimiter Service..." . PHP_EOL; $rateKey = 'test_login_user_' . time(); RateLimiter::clear($rateKey); assert(RateLimiter::tooManyAttempts($rateKey, 3) === false, "New key must not exceed limit"); RateLimiter::hit($rateKey, 60); RateLimiter::hit($rateKey, 60); assert(RateLimiter::retriesLeft($rateKey, 3) === 1, "Retries left must be 1"); RateLimiter::hit($rateKey, 60); // 3rd hit assert(RateLimiter::tooManyAttempts($rateKey, 3) === true, "Key must exceed limit after 3 hits"); $secondsLeft = RateLimiter::availableIn($rateKey); assert($secondsLeft > 0 && $secondsLeft <= 60, "Available in must be between 1-60s"); echo " ✓ RateLimiter Triggered after max attempts: PASS (Available in {$secondsLeft}s)" . PHP_EOL; RateLimiter::clear($rateKey); assert(RateLimiter::tooManyAttempts($rateKey, 3) === false, "Key must be clear after reset"); echo " ✓ RateLimiter Reset & Clear: PASS" . PHP_EOL; // ── 5. SENSITIVE DATA LOG SCRUBBING ───────────────────────────────── echo PHP_EOL . "[5] Testing Sensitive Data Logger & Scrubbing..." . PHP_EOL; $dirtyContext = [ 'username' => 'john_doe', 'password' => 'superSecretPass123', 'confirm_password'=> 'superSecretPass123', 'token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI...', 'bank_account_no' => '123-4-56789-0', 'user_id' => 15 ]; $scrubbed = Logger::scrubSensitiveData($dirtyContext); assert($scrubbed['username'] === 'john_doe', "Username must remain intact"); assert($scrubbed['password'] === '********', "Password must be scrubbed"); assert($scrubbed['confirm_password'] === '********', "Confirm password must be scrubbed"); assert($scrubbed['token'] === '********', "Token must be scrubbed"); assert($scrubbed['bank_account_no'] === '********', "Bank account must be scrubbed"); assert($scrubbed['user_id'] === 15, "User ID must remain intact"); echo " ✓ Logger Sensitive Data Scrubbing: PASS (All credentials masked to '********')" . PHP_EOL; // ── 6. SECURE FILE UPLOAD VALIDATION ──────────────────────────────── echo PHP_EOL . "[6] Testing File Upload Security Protections..." . PHP_EOL; // 6.1 Disallowed extension rejection (e.g. php file) $phpFile = [ 'name' => 'malicious.php', 'type' => 'application/x-php', 'tmp_name' => __DIR__ . '/test_temp.php', 'error' => UPLOAD_ERR_OK, 'size' => 1024 ]; file_put_contents($phpFile['tmp_name'], '<?php echo "evil"; ?>'); $uploadBlocked = false; try { SecureUploadService::processImageUpload($phpFile, 'profiles', 'test', 2 * 1024 * 1024); } catch (ValidationException $e) { $uploadBlocked = true; } @unlink($phpFile['tmp_name']); assert($uploadBlocked === true, "PHP script upload must be blocked by SecureUploadService"); echo " ✓ Executable Script & Disallowed Extension Upload Block: PASS" . PHP_EOL; // Clean mock session unset($_SESSION['user_id'], $_SESSION['user_roles']); echo PHP_EOL . "🎉 ALL 6 SECURITY, VALIDATION & ERROR HANDLING TEST SUITES PASSED! 🎉" . PHP_EOL;
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.24 |
proxy
|
phpinfo
|
Settings