2021-01-19 21:19:17 -08:00
< ? php
2024-03-12 22:39:16 -04:00
namespace App\Http\Middleware\Api\Client\Server ;
2021-01-19 21:19:17 -08:00
2025-09-24 13:34:19 +02:00
use App\Models\Allocation ;
2024-03-12 22:39:16 -04:00
use App\Models\Backup ;
use App\Models\Database ;
use App\Models\Schedule ;
2025-09-24 13:34:19 +02:00
use App\Models\Server ;
use App\Models\Subuser ;
use App\Models\Task ;
use App\Models\User ;
use Closure ;
2021-01-19 21:19:17 -08:00
use Illuminate\Database\Eloquent\Model ;
2025-09-24 13:34:19 +02:00
use Illuminate\Http\Request ;
use InvalidArgumentException ;
2021-01-19 21:19:17 -08:00
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException ;
class ResourceBelongsToServer
{
/**
* Looks at the request parameters to determine if the given resource belongs
* to the requested server . If not , a 404 error will be returned to the caller .
*
* This is critical to ensuring that all subsequent logic is using exactly the
* server that is expected , and that we ' re not accessing a resource completely
* unrelated to the server provided in the request .
*/
2025-09-08 13:12:33 -04:00
public function handle ( Request $request , Closure $next ) : mixed
2021-01-19 21:19:17 -08:00
{
$params = $request -> route () -> parameters ();
2024-03-17 13:16:39 -04:00
$server = $params [ 'server' ] ? ? null ;
2026-07-09 09:55:11 -04:00
throw_unless ( $server instanceof Server , new InvalidArgumentException ( 'This middleware cannot be used in a context that is missing a server in the parameters.' ));
2021-01-19 21:19:17 -08:00
2025-09-08 13:12:33 -04:00
/** @var Server $server */
2021-01-19 21:19:17 -08:00
$server = $request -> route () -> parameter ( 'server' );
$exception = new NotFoundHttpException ( 'The requested resource was not found for this server.' );
foreach ( $params as $key => $model ) {
2025-03-03 14:41:19 -05:00
// Specifically skip the server, we're just trying to see if all the
2021-01-19 21:19:17 -08:00
// other resources are assigned to this server. Also skip anything that
// is not currently a Model instance since those will just end up being
// a 404 down the road.
2021-01-23 12:33:34 -08:00
if ( $key === 'server' || ! $model instanceof Model ) {
2021-01-19 21:19:17 -08:00
continue ;
}
switch ( get_class ( $model )) {
2025-03-03 14:41:19 -05:00
// all these models use "server_id" as the field key for the server
2021-01-19 21:19:17 -08:00
// they are assigned to, so the logic is identical for them all.
case Allocation :: class :
case Backup :: class :
case Database :: class :
case Schedule :: class :
case Subuser :: class :
2026-07-09 09:55:11 -04:00
throw_if ( $model -> server_id !== $server -> id , $exception );
2021-01-19 21:19:17 -08:00
break ;
2022-10-14 10:59:20 -06:00
// Regular users are a special case here as we need to make sure they're
// currently assigned as a subuser on the server.
2021-01-19 21:19:17 -08:00
case User :: class :
$subuser = $server -> subusers () -> where ( 'user_id' , $model -> id ) -> first ();
2026-07-09 09:55:11 -04:00
throw_if ( is_null ( $subuser ), $exception );
2021-01-19 21:19:17 -08:00
// This is a special case to avoid an additional query being triggered
// in the underlying logic.
$request -> attributes -> set ( 'subuser' , $subuser );
break ;
2022-10-14 10:59:20 -06:00
// Tasks are special since they're (currently) the only item in the API
// that requires something in addition to the server in order to be accessed.
2021-01-19 21:19:17 -08:00
case Task :: class :
2024-03-17 12:52:22 -04:00
/** @var Schedule $schedule */
2021-01-19 21:19:17 -08:00
$schedule = $request -> route () -> parameter ( 'schedule' );
2026-07-09 09:55:11 -04:00
throw_if ( $model -> schedule_id !== $schedule -> id || $schedule -> server_id !== $server -> id , $exception );
2021-01-19 21:19:17 -08:00
break ;
default :
// Don't return a 404 here since we want to make sure no one relies
// on this middleware in a context in which it will not work. Fail safe.
2025-09-08 13:12:33 -04:00
throw new InvalidArgumentException ( 'There is no handler configured for a resource of this type: ' . get_class ( $model ));
2021-01-19 21:19:17 -08:00
}
}
return $next ( $request );
}
}