Files
michaelschiemer/tests/debug/test-action-authorization.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

206 lines
7.7 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\DateTime\SystemClock;
use App\Framework\Http\Session\Session;
use App\Framework\Http\Session\SessionId;
use App\Framework\LiveComponents\Attributes\RequiresPermission;
use App\Framework\LiveComponents\ComponentEventDispatcher;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
use App\Framework\LiveComponents\Exceptions\UnauthorizedActionException;
use App\Framework\LiveComponents\LiveComponentHandler;
use App\Framework\LiveComponents\Security\SessionBasedAuthorizationChecker;
use App\Framework\LiveComponents\ValueObjects\ActionParameters;
use App\Framework\LiveComponents\ValueObjects\ComponentData;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentRenderData;
use App\Framework\Random\SecureRandomGenerator;
use App\Framework\Security\CsrfTokenGenerator;
echo "=== Action Authorization Test ===\n\n";
// Setup Session
$sessionId = SessionId::fromString(bin2hex(random_bytes(16)));
$clock = new SystemClock();
$randomGenerator = new SecureRandomGenerator();
$csrfGenerator = new CsrfTokenGenerator($randomGenerator);
$session = Session::fromArray($sessionId, $clock, $csrfGenerator, []);
// Setup Handler
$eventDispatcher = new ComponentEventDispatcher();
$authChecker = new SessionBasedAuthorizationChecker($session);
$handler = new LiveComponentHandler($eventDispatcher, $session, $authChecker);
// Test Component with protected action
$componentId = ComponentId::fromString('posts:manager');
$component = new class ($componentId) implements LiveComponentContract {
public function __construct(private ComponentId $id)
{
}
public function getId(): ComponentId
{
return $this->id;
}
public function getData(): ComponentData
{
return ComponentData::fromArray(['posts' => []]);
}
public function getRenderData(): ComponentRenderData
{
return new ComponentRenderData('posts-manager', ['posts' => []]);
}
// Public action - no permission required
public function viewPosts(): ComponentData
{
return ComponentData::fromArray(['posts' => ['Post 1', 'Post 2']]);
}
// Protected action - requires permission
#[RequiresPermission('posts.delete')]
public function deletePost(string $postId): ComponentData
{
return ComponentData::fromArray([
'deleted' => true,
'postId' => $postId,
]);
}
// Multiple permissions (OR logic)
#[RequiresPermission('posts.edit', 'posts.admin')]
public function editPost(string $postId): ComponentData
{
return ComponentData::fromArray([
'edited' => true,
'postId' => $postId,
]);
}
};
// Generate CSRF token
$formId = 'livecomponent:' . $componentId->toString();
$csrfToken = $session->csrf->generateToken($formId);
// Test 1: Public action without authentication
echo "Test 1: Public action without authentication\n";
echo "--------------------------------------------\n";
try {
$params = ActionParameters::fromArray([], $csrfToken);
$result = $handler->handle($component, 'viewPosts', $params);
echo "✓ Public action executed successfully\n";
echo " Posts: " . json_encode($result->state->data['posts']) . "\n";
} catch (\Exception $e) {
echo "✗ Failed: " . $e->getMessage() . "\n";
exit(1);
}
// Test 2: Protected action without authentication
echo "\nTest 2: Protected action without authentication\n";
echo "------------------------------------------------\n";
try {
$params = ActionParameters::fromArray(['postId' => '123'], $csrfToken);
$handler->handle($component, 'deletePost', $params);
echo "✗ Should have thrown UnauthorizedActionException!\n";
exit(1);
} catch (UnauthorizedActionException $e) {
echo "✓ Correctly rejected unauthenticated user\n";
echo " Error: " . $e->getUserMessage() . "\n";
echo " Is authentication issue: " . ($e->isAuthenticationIssue() ? 'yes' : 'no') . "\n";
}
// Test 3: Protected action with authentication but missing permission
echo "\nTest 3: Protected action with permission check (missing permission)\n";
echo "--------------------------------------------------------------------\n";
$session->set('user', [
'id' => 123,
'permissions' => ['posts.view', 'posts.edit'], // No 'posts.delete'
]);
try {
$params = ActionParameters::fromArray(['postId' => '456'], $csrfToken);
$handler->handle($component, 'deletePost', $params);
echo "✗ Should have thrown UnauthorizedActionException!\n";
exit(1);
} catch (UnauthorizedActionException $e) {
echo "✓ Correctly rejected user without permission\n";
echo " Error: " . $e->getUserMessage() . "\n";
echo " Missing permissions: " . json_encode($e->getMissingPermissions()) . "\n";
}
// Test 4: Protected action with correct permission
echo "\nTest 4: Protected action with correct permission\n";
echo "------------------------------------------------\n";
$session->set('user', [
'id' => 123,
'permissions' => ['posts.view', 'posts.edit', 'posts.delete'],
]);
try {
$params = ActionParameters::fromArray(['postId' => '789'], $csrfToken);
$result = $handler->handle($component, 'deletePost', $params);
echo "✓ Action executed successfully with permission\n";
echo " Result: " . json_encode($result->state->data) . "\n";
} catch (\Exception $e) {
echo "✗ Failed: " . $e->getMessage() . "\n";
exit(1);
}
// Test 5: Multiple permissions (OR logic)
echo "\nTest 5: Multiple permissions with OR logic\n";
echo "-------------------------------------------\n";
$session->set('user', [
'id' => 123,
'permissions' => ['posts.admin'], // Has 'posts.admin', not 'posts.edit'
]);
try {
$params = ActionParameters::fromArray(['postId' => '999'], $csrfToken);
$result = $handler->handle($component, 'editPost', $params);
echo "✓ Action executed with alternative permission\n";
echo " User has 'posts.admin' instead of 'posts.edit'\n";
echo " Result: " . json_encode($result->state->data) . "\n";
} catch (\Exception $e) {
echo "✗ Failed: " . $e->getMessage() . "\n";
exit(1);
}
// Test 6: RequiresPermission attribute validation
echo "\nTest 6: RequiresPermission attribute behavior\n";
echo "----------------------------------------------\n";
$attr1 = new RequiresPermission('posts.edit');
echo "Single permission attribute:\n";
echo " Permissions: " . json_encode($attr1->getPermissions()) . "\n";
echo " Primary: " . $attr1->getPrimaryPermission() . "\n";
echo " Has multiple: " . ($attr1->hasMultiplePermissions() ? 'yes' : 'no') . "\n";
$attr2 = new RequiresPermission('posts.edit', 'posts.admin');
echo "\nMultiple permissions attribute:\n";
echo " Permissions: " . json_encode($attr2->getPermissions()) . "\n";
echo " Primary: " . $attr2->getPrimaryPermission() . "\n";
echo " Has multiple: " . ($attr2->hasMultiplePermissions() ? 'yes' : 'no') . "\n";
echo "\nPermission checking:\n";
echo " User with ['posts.edit']: " . ($attr2->isAuthorized(['posts.edit']) ? 'authorized' : 'denied') . "\n";
echo " User with ['posts.admin']: " . ($attr2->isAuthorized(['posts.admin']) ? 'authorized' : 'denied') . "\n";
echo " User with ['posts.view']: " . ($attr2->isAuthorized(['posts.view']) ? 'authorized' : 'denied') . "\n";
echo "\n=== All Tests Passed! ===\n";
echo "\nSummary:\n";
echo " ✓ Public actions work without authentication\n";
echo " ✓ Protected actions require authentication\n";
echo " ✓ Permission checks work correctly\n";
echo " ✓ Missing permissions are rejected\n";
echo " ✓ Multiple permissions support OR logic\n";
echo " ✓ RequiresPermission attribute works as expected\n";
echo "\nAction Guards Implementation: COMPLETE\n";