Better route model binding

This commit is contained in:
Lance Pioch 2024-03-22 21:32:12 -04:00
parent 0c5b449c4e
commit 0d2e63f590
5 changed files with 16 additions and 40 deletions

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api\Client\Servers; namespace App\Http\Controllers\Api\Client\Servers;
use App\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Server; use App\Models\Server;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@ -42,7 +43,7 @@ class SubuserController extends ClientApiController
/** /**
* Returns a single subuser associated with this server instance. * Returns a single subuser associated with this server instance.
*/ */
public function view(GetSubuserRequest $request): array public function view(GetSubuserRequest $request, Server $server, User $user): array
{ {
$subuser = $request->attributes->get('subuser'); $subuser = $request->attributes->get('subuser');
@ -82,7 +83,7 @@ class SubuserController extends ClientApiController
* *
* @throws \App\Exceptions\Model\DataValidationException * @throws \App\Exceptions\Model\DataValidationException
*/ */
public function update(UpdateSubuserRequest $request, Server $server): array public function update(UpdateSubuserRequest $request, Server $server, User $user): array
{ {
/** @var \App\Models\Subuser $subuser */ /** @var \App\Models\Subuser $subuser */
$subuser = $request->attributes->get('subuser'); $subuser = $request->attributes->get('subuser');
@ -130,7 +131,7 @@ class SubuserController extends ClientApiController
/** /**
* Removes a subusers from a server's assignment. * Removes a subusers from a server's assignment.
*/ */
public function delete(DeleteSubuserRequest $request, Server $server): JsonResponse public function delete(DeleteSubuserRequest $request, Server $server, User $user): JsonResponse
{ {
/** @var \App\Models\Subuser $subuser */ /** @var \App\Models\Subuser $subuser */
$subuser = $request->attributes->get('subuser'); $subuser = $request->attributes->get('subuser');

View File

@ -1,33 +0,0 @@
<?php
namespace App\Http\Middleware\Api\Client;
use App\Models\Server;
use Closure;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Routing\Middleware\SubstituteBindings;
class SubstituteClientBindings extends SubstituteBindings
{
public function __construct(Registrar $router, private Server $server)
{
parent::__construct($router);
}
public function handle($request, Closure $next): mixed
{
// Override default behavior of the model binding to use a specific table column rather than the default 'id'.
$this->router->bind('user', function ($value, $route) {
/** @var \App\Models\Subuser $match */
$match = $route->parameter('server')
->subusers()
->whereRelation('user', 'uuid', '=', $value)
->firstOrFail();
return $match->user;
});
return parent::handle($request, $next);
}
}

View File

@ -331,6 +331,14 @@ class Server extends Model
}; };
} }
public function resolveChildRouteBinding($childType, $value, $field)
{
return match ($childType) {
'user' => $this->subusers()->whereRelation('user', 'uuid', $value)->firstOrFail()->user,
default => parent::resolveChildRouteBinding($childType, $value, $field),
};
}
/** /**
* Checks if the server is currently in a user-accessible state. If not, an * Checks if the server is currently in a user-accessible state. If not, an
* exception is raised. This should be called whenever something needs to make * exception is raised. This should be called whenever something needs to make

View File

@ -35,7 +35,7 @@ return Application::configure(basePath: dirname(__DIR__))
]); ]);
$middleware->group('client-api', [ $middleware->group('client-api', [
\App\Http\Middleware\Api\Client\SubstituteClientBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\Api\Client\RequireClientApiKey::class, \App\Http\Middleware\Api\Client\RequireClientApiKey::class,
]); ]);

View File

@ -107,9 +107,9 @@ Route::prefix('/servers/{server:uuid}')->middleware([ServerSubject::class, Authe
Route::prefix('/users')->group(function () { Route::prefix('/users')->group(function () {
Route::get('/', [Client\Servers\SubuserController::class, 'index']); Route::get('/', [Client\Servers\SubuserController::class, 'index']);
Route::post('/', [Client\Servers\SubuserController::class, 'store']); Route::post('/', [Client\Servers\SubuserController::class, 'store']);
Route::get('/{user}', [Client\Servers\SubuserController::class, 'view']); Route::get('/{user:uuid}', [Client\Servers\SubuserController::class, 'view']);
Route::post('/{user}', [Client\Servers\SubuserController::class, 'update']); Route::post('/{user:uuid}', [Client\Servers\SubuserController::class, 'update']);
Route::delete('/{user}', [Client\Servers\SubuserController::class, 'delete']); Route::delete('/{user:uuid}', [Client\Servers\SubuserController::class, 'delete']);
}); });
Route::prefix('/backups')->group(function () { Route::prefix('/backups')->group(function () {