Implement multi-tenancy support with OAuth2 authentication for tenant admins, Stripe integration for event purchases and credits ledger, new Filament resources for event purchases, updated API routes and middleware for tenant isolation and token guarding, added factories/seeders/migrations for new models (Tenant, EventPurchase, OAuth entities, etc.), enhanced tests, and documentation updates. Removed outdated DemoAchievementsSeeder.

This commit is contained in:
2025-09-17 19:56:54 +02:00
parent 5fbb9cb240
commit 42d6e98dff
84 changed files with 6125 additions and 155 deletions

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class TenantIsolation
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next)
{
$tenantId = $request->attributes->get('tenant_id');
if (!$tenantId) {
return response()->json(['error' => 'Tenant ID not found in token'], 401);
}
// Get the tenant from request (query param, route param, or header)
$requestTenantId = $this->getTenantIdFromRequest($request);
if ($requestTenantId && $requestTenantId != $tenantId) {
return response()->json(['error' => 'Tenant isolation violation'], 403);
}
// Set tenant context for query scoping
DB::statement("SET @tenant_id = ?", [$tenantId]);
// Add tenant context to request for easy access in controllers
$request->attributes->set('current_tenant_id', $tenantId);
return $next($request);
}
/**
* Extract tenant ID from request
*/
private function getTenantIdFromRequest(Request $request): ?int
{
// 1. Route parameter (e.g., /api/v1/tenant/123/events)
if ($request->route('tenant')) {
return (int) $request->route('tenant');
}
// 2. Query parameter (e.g., ?tenant_id=123)
if ($request->query('tenant_id')) {
return (int) $request->query('tenant_id');
}
// 3. Header (X-Tenant-ID)
if ($request->header('X-Tenant-ID')) {
return (int) $request->header('X-Tenant-ID');
}
// 4. For tenant-specific resources, use token tenant_id
return null;
}
}