Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Concerns/Authorizable.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ public function authorizeTo($ability, $model)
* @param string $ability
* @param Model|string $model
*
* @return bool
* @return Response
*/
public function authorizedTo($ability, $model)
{
if ($this->isAuthorizingEnabled()) {
$resolver = function () use ($ability, $model) {
return Gate::check($ability, $model);
return Gate::inspect($ability, $model);
};

if ($this->isAuthorizationCacheEnabled()) {
Expand Down
24 changes: 17 additions & 7 deletions src/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,18 @@ public function resource(Resource $resource)

protected function buildGatesForModel(Model $model, Resource $resource, array $gates)
{
$authorizedToView = $resource->authorizedTo('view', $model);
$authorizedToUpdate = $resource->authorizedTo('update', $model);
$authorizedToDelete = $resource->authorizedTo('delete', $model);
$authorizedToRestore = $resource->authorizedTo('restore', $model);
$authorizedToForceDelete = $resource->authorizedTo('forceDelete', $model);

return array_merge(
in_array('view', $gates) ? [config('rest.gates.names.authorized_to_view') => $resource->authorizedTo('view', $model)] : [],
in_array('update', $gates) ? [config('rest.gates.names.authorized_to_update') => $resource->authorizedTo('update', $model)] : [],
in_array('delete', $gates) ? [config('rest.gates.names.authorized_to_delete') => $resource->authorizedTo('delete', $model)] : [],
in_array('restore', $gates) ? [config('rest.gates.names.authorized_to_restore') => $resource->authorizedTo('restore', $model)] : [],
in_array('forceDelete', $gates) ? [config('rest.gates.names.authorized_to_force_delete') => $resource->authorizedTo('forceDelete', $model)] : [],
in_array('view', $gates) ? [config('rest.gates.names.authorized_to_view') => $authorizedToView->message() ?? $authorizedToView->allowed()] : [],
in_array('update', $gates) ? [config('rest.gates.names.authorized_to_update') => $authorizedToUpdate->message() ?? $authorizedToUpdate->allowed()] : [],
in_array('delete', $gates) ? [config('rest.gates.names.authorized_to_delete') => $authorizedToDelete->message() ?? $authorizedToDelete->allowed()] : [],
in_array('restore', $gates) ? [config('rest.gates.names.authorized_to_restore') => $authorizedToRestore->message() ?? $authorizedToRestore->allowed()] : [],
in_array('forceDelete', $gates) ? [config('rest.gates.names.authorized_to_force_delete') => $authorizedToForceDelete->message() ?? $authorizedToForceDelete->allowed()] : [],
);
}

Expand Down Expand Up @@ -126,15 +132,19 @@ public function modelToResponse(Model $model, Resource $resource, array $request
public function toResponse($request)
{
if ($this->responsable instanceof LengthAwarePaginator) {
if ($this->resource->isGatingEnabled() && in_array('create', $request->input('search.gates', []))) {
$authorizedToCreate = $this->resource->authorizedTo('create', $this->resource::newModel()::class);
}

$restLengthAwarePaginator = new \Lomkit\Rest\Pagination\LengthAwarePaginator(
$this->responsable->items(),
$this->responsable->total(),
$this->responsable->perPage(),
$this->responsable->currentPage(),
$this->responsable->getOptions(),
$this->resource->isGatingEnabled() && in_array('create', $request->input('search.gates', [])) ? [
isset($authorizedToCreate) ? [
config('rest.gates.key') => [
config('rest.gates.names.authorized_to_create') => $this->resource->authorizedTo('create', $this->resource::newModel()::class),
config('rest.gates.names.authorized_to_create') => $authorizedToCreate->message() ?? $authorizedToCreate->allowed(),
],
] : []
);
Expand Down
39 changes: 39 additions & 0 deletions tests/Feature/Controllers/AutomaticGatingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Lomkit\Rest\Tests\Support\Policies\DeletePolicy;
use Lomkit\Rest\Tests\Support\Policies\ForceDeletePolicy;
use Lomkit\Rest\Tests\Support\Policies\GreenPolicy;
use Lomkit\Rest\Tests\Support\Policies\RedPolicyWithMessage;
use Lomkit\Rest\Tests\Support\Policies\RestorePolicy;
use Lomkit\Rest\Tests\Support\Policies\UpdatePolicy;
use Lomkit\Rest\Tests\Support\Policies\ViewPolicy;
Expand Down Expand Up @@ -62,6 +63,44 @@ public function test_searching_automatic_gated_resource(): void
);
}

public function test_searching_automatic_gated_resource_and_custom_message(): void
{
$model = ModelFactory::new()
->create();

Gate::policy(Model::class, RedPolicyWithMessage::class);

$response = $this->post(
'/api/automatic-gating/search',
[
'search' => [
'gates' => ['create', 'view', 'update', 'delete', 'forceDelete', 'restore'],
],
],
['Accept' => 'application/json']
);

$this->assertResourcePaginated(
$response,
[$model],
new AutomaticGatingResource(),
[
[
'gates' => [
'authorized_to_view' => 'You don\'t have permission to view user',
'authorized_to_update' => 'You don\'t have permission to update user',
'authorized_to_delete' => 'You don\'t have permission to delete user',
'authorized_to_restore' => 'You don\'t have permission to restore user',
'authorized_to_force_delete' => 'You don\'t have permission to force delete user',
],
],
]
);
$response->assertJson(
['meta' => ['gates' => ['authorized_to_create' => true]]]
);
}

public function test_searching_automatic_gated_resource_with_global_config_disabled(): void
{
$model = ModelFactory::new()
Expand Down
87 changes: 87 additions & 0 deletions tests/Support/Policies/RedPolicyWithMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Lomkit\Rest\Tests\Support\Policies;

use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Auth\Access\Response;
use Illuminate\Database\Eloquent\Model;

class RedPolicyWithMessage
{
use HandlesAuthorization;

/**
* Determine whether the user can view the list of models.
*
* @param $user
*/
public function viewAny($user)
{
return true;
}

/**
* Determine whether the user can view the model.
*
* @param $user
* @param Model $model
*/
public function view($user, Model $model)
{
return Response::deny('You don\'t have permission to view user');
}

/**
* Determine whether the user can create models.
*
* @param $user
*/
public function create($user)
{
return Response::deny('You don\'t have permission to create user');
}

/**
* Determine whether the user can update the model.
*
* @param $user
* @param Model $model
*/
public function update($user, Model $model)
{
return Response::deny('You don\'t have permission to update user');
}

/**
* Determine whether the user can delete the model.
*
* @param $user
* @param Model $model
*/
public function delete($user, Model $model)
{
return Response::deny('You don\'t have permission to delete user');
}

/**
* Determine whether the user can restore the model.
*
* @param $user
* @param Model $model
*/
public function restore($user, Model $model)
{
return Response::deny('You don\'t have permission to restore user');
}

/**
* Determine whether the user can permanently delete the model.
*
* @param $user
* @param Model $model
*/
public function forceDelete($user, Model $model)
{
return Response::deny('You don\'t have permission to force delete user');
}
}