Documentación de Laravel 10.x
Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.
Además de proporcionar servicios de autenticación integrados, Laravel también proporciona una forma sencilla de autorizar acciones de usuario contra un recurso específico. Por ejemplo, aunque un usuario esté autenticado, es posible que no esté autorizado para actualizar o eliminar ciertos modelos Eloquent o registros de la base de datos gestionados por tu aplicación. Las funciones de autorización de Laravel proporcionan una forma fácil y organizada de gestionar este tipo de comprobaciones de autorización.
Laravel proporciona dos formas principales de autorizar acciones: gates y policies. Piensa en gates y policies como rutas y controladores. Los gates proporcionan un enfoque simple basado en cierres para la autorización, mientras que las policies, al igual que los controladores, agrupan la lógica en torno a un modelo o recurso específico. En esta documentación, exploraremos primero los gates y luego examinaremos las policies.
No necesitas elegir entre usar exclusivamente gates o policies al construir una aplicación. La mayoría de las aplicaciones probablemente contendrán una mezcla de gates y policies, ¡y eso está perfectamente bien! Los gates son más aplicables a acciones que no están relacionadas con ningún modelo o recurso, como ver un panel de administrador. En cambio, las policies deben usarse cuando deseas autorizar una acción para un modelo o recurso específico.
Advertencia Los gates son una excelente manera de aprender los conceptos básicos de las características de autorización de Laravel; sin embargo, al construir aplicaciones robustas con Laravel, deberías considerar usar policies para organizar tus reglas de autorización.
Los gates son simplemente cierres que determinan si un usuario está autorizado para realizar una acción determinada. Normalmente, los gates se definen dentro del método boot
de la clase App\Providers\AuthServiceProvider
utilizando la fachada Gate
. Los gates siempre reciben una instancia de usuario como su primer argumento y opcionalmente pueden recibir argumentos adicionales, como un modelo Eloquent relevante.
En este ejemplo, definiremos un gate para determinar si un usuario puede actualizar un modelo App\Models\Post
dado. El gate logrará esto comparando el id
del usuario con el user_id
del usuario que creó la publicación:
use App\Models\Post;use App\Models\User;use Illuminate\Support\Facades\Gate; /** * Registra cualquier servicio de autenticación/autorización. */public function boot(): void{ Gate::define('update-post', function (User $user, Post $post) { return $user->id === $post->user_id; });}
Al igual que los controladores, los gates también se pueden definir mediante un array de devolución de llamada de clase:
use App\Policies\PostPolicy;use Illuminate\Support\Facades\Gate; /** * Registra cualquier servicio de autenticación/autorización. */public function boot(): void{ Gate::define('update-post', [PostPolicy::class, 'update']);}
Para autorizar una acción mediante gates, debes utilizar los métodos allows
o denies
proporcionados por la fachada Gate
. Ten en cuenta que no es necesario pasar el usuario actualmente autenticado a estos métodos. Laravel se encargará automáticamente de pasar el usuario al cierre del gate. Es típico llamar a los métodos de autorización del gate dentro de los controladores de tu aplicación antes de realizar una acción que requiera autorización:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\Support\Facades\Gate; class PostController extends Controller{ /** * Actualiza la publicación dada. */ public function update(Request $request, Post $post): RedirectResponse { if (! Gate::allows('update-post', $post)) { abort(403); } // Actualizar la publicación... return redirect('/posts'); }}
Si deseas determinar si un usuario que no es el usuario autenticado actualmente está autorizado para realizar una acción, puedes usar el método forUser
en la fachada Gate
:
if (Gate::forUser($user)->allows('update-post', $post)) { // El usuario puede actualizar la publicación...} if (Gate::forUser($user)->denies('update-post', $post)) { // El usuario no puede actualizar la publicación...}
Puedes autorizar múltiples acciones a la vez usando los métodos any
o none
:
if (Gate::any(['update-post', 'delete-post'], $post)) { // El usuario puede actualizar o eliminar la publicación...} if (Gate::none(['update-post', 'delete-post'], $post)) { // El usuario no puede actualizar o eliminar la publicación...}
Si deseas intentar autorizar una acción y lanzar automáticamente una excepción Illuminate\Auth\Access\AuthorizationException
si el usuario no tiene permitido realizar la acción dada, puedes usar el método authorize
de la fachada Gate
. Las instancias de AuthorizationException
se convierten automáticamente en una respuesta HTTP 403 por el manejador de excepciones de Laravel:
Gate::authorize('update-post', $post); // La acción está autorizada...
Los métodos de gate para autorizar habilidades (allows
, denies
, check
, any
, none
, authorize
, can
, cannot
) y las directivas de autorización Blade (@can
, @cannot
, @canany
) pueden recibir una matriz como segundo argumento. Estos elementos de la matriz se pasan como parámetros al cierre del gate y se pueden usar para obtener un contexto adicional al tomar decisiones de autorización:
use App\Models\Category;use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::define('create-post', function (User $user, Category $category, bool $pinned) { if (! $user->canPublishToGroup($category->group)) { return false; } elseif ($pinned && ! $user->canPinPosts()) { return false; } return true;}); if (Gate::check('create-post', [$category, $pinned])) { // El usuario puede crear la publicación...}
Hasta ahora, solo hemos examinado gates que devuelven valores booleanos simples. Sin embargo, a veces puedes desear devolver una respuesta más detallada, incluido un mensaje de error. Para hacerlo, puedes devolver una instancia de Illuminate\Auth\Access\Response
desde tu gate:
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::deny('Debes ser un administrador.');});
Incluso cuando devuelves una respuesta de autorización desde tu gate, el método Gate::allows
seguirá devolviendo un valor booleano simple; sin embargo, puedes usar el método Gate::inspect
para obtener la respuesta completa de autorización devuelta por el gate:
$response = Gate::inspect('edit-settings'); if ($response->allowed()) { // La acción está autorizada...} else { echo $response->message();}
Cuando usas el método Gate::authorize
, que lanza una excepción AuthorizationException
si la acción no está autorizada, el mensaje de error proporcionado por la respuesta de autorización se propagará a la respuesta HTTP:
Gate::authorize('edit-settings'); // La acción está autorizada...
Cuando se niega una acción a través de un Gate, se devuelve una respuesta HTTP 403
; sin embargo, a veces puede ser útil devolver un código de estado HTTP alternativo. Puedes personalizar el código de estado HTTP devuelto para una comprobación de autorización fallida utilizando el constructor estático denyWithStatus
en la clase Illuminate\Auth\Access\Response
:
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::denyWithStatus(404);});
Debido a que ocultar recursos mediante una respuesta 404
es un patrón tan común para aplicaciones web, se ofrece el método denyAsNotFound
para mayor comodidad:
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::denyAsNotFound();});
A veces, es posible que desees conceder todas las habilidades a un usuario específico. Puedes usar el método before
para definir un cierre que se ejecute antes de todas las demás comprobaciones de autorización:
use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::before(function (User $user, string $ability) { if ($user->isAdministrator()) { return true; }});
Si el cierre before
devuelve un resultado no nulo, ese resultado se considerará el resultado de la comprobación de autorización.
Puedes usar el método after
para definir un cierre que se ejecutará después de todas las demás comprobaciones de autorización:
use App\Models\User; Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) { if ($user->isAdministrator()) { return true; }});
Similar al método before
, si el cierre after
devuelve un resultado no nulo, ese resultado se considerará el resultado de la comprobación de autorización.
Ocasionalmente, es posible que desees determinar si el usuario autenticado actualmente está autorizado para realizar una acción determinada sin escribir un gate dedicado que corresponda a la acción. Laravel te permite realizar este tipo de comprobaciones de autorización "en línea" mediante los métodos Gate::allowIf
y Gate::denyIf
:
use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::allowIf(fn (User $user) => $user->isAdministrator()); Gate::denyIf(fn (User $user) => $user->banned());
Si la acción no está autorizada o si no hay un usuario autenticado actualmente, Laravel lanzará automáticamente una excepción Illuminate\Auth\Access\AuthorizationException
. Las instancias de AuthorizationException
se convierten automáticamente en una respuesta HTTP 403 por el manejador de excepciones de Laravel.
Las políticas son clases que organizan la lógica de autorización en torno a un modelo o recurso en particular. Por ejemplo, si tu aplicación es un blog, es posible que tengas un modelo App\Models\Post
y una política correspondiente App\Policies\PostPolicy
para autorizar acciones de usuario, como crear o actualizar publicaciones.
Puedes generar una política usando el comando Artisan make:policy
. La política generada se colocará en el directorio app/Policies
. Si este directorio no existe en tu aplicación, Laravel lo creará por ti:
php artisan make:policy PostPolicy
El comando make:policy
generará una clase de política vacía. Si deseas generar una clase con métodos de política de ejemplo relacionados con ver, crear, actualizar y eliminar el recurso, puedes proporcionar una opción --model
al ejecutar el comando:
php artisan make:policy PostPolicy --model=Post
Una vez que se haya creado la clase de política, necesita registrarse. El registro de políticas es la forma en que podemos informar a Laravel qué política usar al autorizar acciones contra un tipo de modelo dado.
El App\Providers\AuthServiceProvider
incluido en las aplicaciones Laravel nuevas contiene una propiedad policies
que asigna tus modelos Eloquent a sus respectivas políticas. Registrar una política instruirá a Laravel sobre qué política utilizar al autorizar acciones contra un modelo Eloquent dado:
<?php namespace App\Providers; use App\Models\Post;use App\Policies\PostPolicy;use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;use Illuminate\Support\Facades\Gate; class AuthServiceProvider extends ServiceProvider{ /** * Las asignaciones de políticas para la aplicación. * * @var array */ protected $policies = [ Post::class => PostPolicy::class, ]; /** * Registra cualquier servicio de autenticación/autorización de la aplicación. */ public function boot(): void { // ... }}
En lugar de registrar manualmente las políticas de modelo, Laravel puede descubrir automáticamente las políticas siempre que el modelo y la política sigan las convenciones de nomenclatura estándar de Laravel. Específicamente, las políticas deben estar en un directorio Policies
en o por encima del directorio que contiene tus modelos. Por ejemplo, los modelos pueden ubicarse en el directorio app/Models
, mientras que las políticas pueden ubicarse en el directorio app/Policies
. En esta situación, Laravel verificará las políticas en app/Models/Policies
y luego app/Policies
. Además, el nombre de la política debe coincidir con el nombre del modelo y tener un sufijo Policy
. Así, una clase User
del modelo correspondería a una clase de política UserPolicy
.
Si deseas definir tu propia lógica de descubrimiento de políticas, puedes registrar un callback de descubrimiento de políticas personalizado utilizando el método Gate::guessPolicyNamesUsing
. Por lo general, este método debe llamarse desde el método boot
del AuthServiceProvider
de tu aplicación:
use Illuminate\Support\Facades\Gate; Gate::guessPolicyNamesUsing(function (string $modelClass) { // Devuelve el nombre de la clase de política para el modelo dado...});
Advertencia Cualquier política que esté explícitamente asignada en tu
AuthServiceProvider
tomará precedencia sobre cualquier política que se descubra automáticamente.
Una vez que la clase de política haya sido registrada, puedes agregar métodos para cada acción que autoriza. Por ejemplo, definamos un método update
en nuestra PostPolicy
que determine si un App\Models\User
dado puede actualizar una instancia dada de App\Models\Post
.
El método update
recibirá como argumentos una instancia de User
y una de Post
, y debería devolver true
o false
indicando si el usuario está autorizado para actualizar la Post
dada. Entonces, en este ejemplo, verificaremos que el id
del usuario coincida con el user_id
en la publicación:
<?php namespace App\Policies; use App\Models\Post;use App\Models\User; class PostPolicy{ /** * Determina si el usuario dado puede actualizar la publicación. */ public function update(User $user, Post $post): bool { return $user->id === $post->user_id; }}
Puedes seguir definiendo métodos adicionales en la política según sea necesario para las diversas acciones que autoriza. Por ejemplo, podrías definir métodos view
o delete
para autorizar varias acciones relacionadas con Post
, pero recuerda que eres libre de darle a tus métodos de política el nombre que desees.
Si usaste la opción --model
al generar tu política a través de la consola Artisan, ya contendrá métodos para las acciones viewAny
, view
, create
, update
, delete
, restore
y forceDelete
.
Nota Todas las políticas se resuelven a través del contenedor de servicios de Laravel, lo que te permite sugerir dependencias necesarias en el constructor de la política para que se inyecten automáticamente.
Hasta ahora, solo hemos examinado métodos de política que devuelven valores booleanos simples. Sin embargo, a veces puedes desear devolver una respuesta más detallada, incluido un mensaje de error. Para hacerlo, puedes devolver una instancia de Illuminate\Auth\Access\Response
desde tu método de política:
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determina si el usuario dado puede actualizar la publicación. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::deny('No eres el propietario de esta publicación.');}
Cuando devuelves una respuesta de autorización desde tu política, el método Gate::allows
seguirá devolviendo un valor booleano simple; sin embargo, puedes usar el método Gate::inspect
para obtener la respuesta completa de autorización devuelta por el gate:
use Illuminate\Support\Facades\Gate; $response = Gate::inspect('update', $post); if ($response->allowed()) { // La acción está autorizada...} else { echo $response->message();}
Cuando usas el método Gate::authorize
, que lanza una excepción AuthorizationException
si la acción no está autorizada, el mensaje de error proporcionado por la respuesta de autorización se propagará a la respuesta HTTP:
Gate::authorize('update', $post); // La acción está autorizada...
Cuando se deniega una acción a través de un método de política, se devuelve una respuesta HTTP 403
; sin embargo, a veces puede ser útil devolver un código de estado HTTP alternativo. Puedes personalizar el código de estado HTTP devuelto para una comprobación de autorización fallida utilizando el constructor estático denyWithStatus
en la clase Illuminate\Auth\Access\Response
:
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determina si el usuario dado puede actualizar la publicación. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::denyWithStatus(404);}
Debido a que ocultar recursos mediante una respuesta 404
es un patrón tan común para aplicaciones web, se ofrece el método denyAsNotFound
para mayor comodidad:
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determina si el usuario dado puede actualizar la publicación. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::denyAsNotFound();}
Algunos métodos de política solo reciben una instancia del usuario actualmente autenticado. Esta situación es más común al autorizar acciones de create
. Por ejemplo, si estás creando un blog, es posible que desees determinar si un usuario está autorizado para crear cualquier publicación en absoluto. En estas situaciones, tu método de política debería esperar recibir solo una instancia de usuario:
/** * Determina si el usuario dado puede crear publicaciones. */public function create(User $user): bool{ return $user->role == 'writer';}
De forma predeterminada, todos los gates y las políticas devuelven automáticamente false
si la solicitud HTTP entrante no fue iniciada por un usuario autenticado. Sin embargo, puedes permitir que estas comprobaciones de autorización pasen a través de tus gates y políticas declarando un tipo de declaración "opcional" o proporcionando un valor predeterminado null
para la definición del argumento de usuario:
<?php namespace App\Policies; use App\Models\Post;use App\Models\User; class PostPolicy{ /** * Determina si el usuario dado puede actualizar la publicación. */ public function update(?User $user, Post $post): bool { return $user?->id === $post->user_id; }}
Para ciertos usuarios, es posible que desees autorizar todas las acciones dentro de una política dada. Para lograr esto, define un método before
en la política. El método before
se ejecutará antes que cualquier otro método en la política, dándote la oportunidad de autorizar la acción antes de que se llame al método de política previsto. Esta función se utiliza comúnmente para autorizar a los administradores de la aplicación para realizar cualquier acción:
use App\Models\User; /** * Realiza comprobaciones de preautorización. */public function before(User $user, string $ability): bool|null{ if ($user->isAdministrator()) { return true; } return null;}
Si deseas denegar todas las comprobaciones de autorización para un tipo de usuario en particular, puedes devolver false
desde el método before
. Si se devuelve null
, la comprobación de autorización pasará al método de política.
Advertencia El método
before
de una clase de política no se llamará si la clase no contiene un método con un nombre que coincida con el nombre de la capacidad que se está comprobando.
El modelo App\Models\User
que se incluye en tu aplicación Laravel incluye dos métodos útiles para autorizar acciones: can
y cannot
. Los métodos can
y cannot
reciben el nombre de la acción que deseas autorizar y el modelo relevante. Por ejemplo, determinemos si un usuario está autorizado para actualizar un modelo App\Models\Post
. Por lo general, esto se hará dentro de un método del controlador:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class PostController extends Controller{ /** * Actualiza la publicación dada. */ public function update(Request $request, Post $post): RedirectResponse { if ($request->user()->cannot('update', $post)) { abort(403); } // Actualizar la publicación... return redirect('/posts'); }}
Si se registra una política para el modelo dado, el método can
llamará automáticamente a la política adecuada y devolverá el resultado booleano. Si no se registra ninguna política para el modelo, el método can
intentará llamar al gate basado en cierres que coincida con el nombre de la acción dado.
Recuerda, algunas acciones pueden corresponder a métodos de política como create
que no requieren una instancia de modelo. En estas situaciones, puedes pasar un nombre de clase al método can
. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class PostController extends Controller{ /** * Crea una publicación. */ public function store(Request $request): RedirectResponse { if ($request->user()->cannot('create', Post::class)) { abort(403); } // Crear la publicación... return redirect('/posts'); }}
Además de los métodos útiles proporcionados al modelo App\Models\User
, Laravel proporciona un útil método authorize
a cualquiera de tus controladores que extiendan la clase base App\Http\Controllers\Controller
.
Al igual que el método can
, este método acepta el nombre de la acción que deseas autorizar y el modelo relevante. Si la acción no está autorizada, el método authorize
lanzará una excepción Illuminate\Auth\Access\AuthorizationException
que el gestor de excepciones de Laravel convertirá automáticamente en una respuesta HTTP con un código de estado 403:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class PostController extends Controller{ /** * Actualiza la publicación de blog dada. * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(Request $request, Post $post): RedirectResponse { $this->authorize('update', $post); // El usuario actual puede actualizar la publicación del blog... return redirect('/posts'); }}
Como se discutió anteriormente, algunos métodos de política como create
no requieren una instancia de modelo. En estas situaciones, debes pasar un nombre de clase al método authorize
. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:
use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; /** * Crea una nueva publicación de blog. * * @throws \Illuminate\Auth\Access\AuthorizationException */public function create(Request $request): RedirectResponse{ $this->authorize('create', Post::class); // El usuario actual puede crear publicaciones de blog... return redirect('/posts');}
Si estás utilizando controladores de recursos, puedes hacer uso del método authorizeResource
en el constructor de tu controlador. Este método adjuntará las definiciones de middleware can
apropiadas a los métodos del controlador de recursos.
El método authorizeResource
acepta el nombre de clase del modelo como su primer argumento y el nombre del parámetro de ruta / solicitud que contendrá el ID del modelo como su segundo argumento. Debes asegurarte de que tu controlador de recursos se cree utilizando la bandera --model
para que tenga las firmas de método y las sugerencias de tipo requeridas:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post; class PostController extends Controller{ /** * Crea una instancia del controlador. */ public function __construct() { $this->authorizeResource(Post::class, 'post'); }}
Los siguientes métodos del controlador se asignarán a su método de política correspondiente. Cuando las solicitudes se dirijan al método del controlador dado, el método de política correspondiente se invocará automáticamente antes de que se ejecute el método del controlador:
Método del Controlador | Método de la Política |
---|---|
index | viewAny |
show | view |
create | create |
store | create |
edit | update |
update | update |
destroy | delete |
Nota Puedes usar el comando
make:policy
con la opción--model
para generar rápidamente una clase de política para un modelo dado:php artisan make:policy PostPolicy --model=Post
.
Laravel incluye un middleware que puede autorizar acciones antes de que la solicitud entrante llegue a tus rutas o controladores. De forma predeterminada, el middleware Illuminate\Auth\Middleware\Authorize
se asigna a la clave can
en tu clase App\Http\Kernel
. Veamos un ejemplo de cómo usar el middleware can
para autorizar que un usuario puede actualizar una publicación:
use App\Models\Post; Route::put('/post/{post}', function (Post $post) { // El usuario actual puede actualizar la publicación...})->middleware('can:update,post');
En este ejemplo, estamos pasando al middleware can
dos argumentos. El primero es el nombre de la acción que deseamos autorizar y el segundo es el parámetro de ruta que deseamos pasar al método de la política. En este caso, dado que estamos utilizando enlace implícito de modelos, se pasará un modelo App\Models\Post
al método de la política. Si el usuario no está autorizado para realizar la acción dada, el middleware devolverá una respuesta HTTP con un código de estado 403.
Para mayor comodidad, también puedes adjuntar el middleware can
a tu ruta utilizando el método can
:
use App\Models\Post; Route::put('/post/{post}', function (Post $post) { // El usuario actual puede actualizar la publicación...})->can('update', 'post');
Nuevamente, algunos métodos de política como create
no requieren una instancia de modelo. En estas situaciones, puedes pasar un nombre de clase al middleware. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:
Route::post('/post', function () { // El usuario actual puede crear publicaciones...})->middleware('can:create,App\Models\Post');
Especificar el nombre completo de la clase dentro de una definición de middleware de cadena puede volverse engorroso. Por esa razón, puedes optar por adjuntar el middleware can
a tu ruta utilizando el método can
:
use App\Models\Post; Route::post('/post', function () { // El usuario actual puede crear publicaciones...})->can('create', Post::class);
Al escribir plantillas Blade, es posible que desees mostrar una parte de la página solo si el usuario está autorizado para realizar una acción determinada. Por ejemplo, es posible que desees mostrar un formulario de actualización para una publicación de blog solo si el usuario realmente puede actualizar la publicación. En esta situación, puedes usar las directivas @can
y @cannot
:
@can('update', $post) <!-- El usuario actual puede actualizar la publicación... -->@elsecan('create', App\Models\Post::class) <!-- El usuario actual puede crear nuevas publicaciones... -->@else <!-- ... -->@endcan @cannot('update', $post) <!-- El usuario actual no puede actualizar la publicación... -->@elsecannot('create', App\Models\Post::class) <!-- El usuario actual no puede crear nuevas publicaciones... -->@endcannot
Estas directivas son accesos directos convenientes para escribir declaraciones @if
y @unless
. Las declaraciones @can
y @cannot
anteriores son equivalentes a las siguientes declaraciones:
@if (Auth::user()->can('update', $post)) <!-- El usuario actual puede actualizar la publicación... -->@endif @unless (Auth::user()->can('update', $post)) <!-- El usuario actual no puede actualizar la publicación... -->@endunless
También puedes determinar si un usuario está autorizado para realizar cualquier acción desde una matriz de acciones dada. Para lograr esto, utiliza la directiva @canany
:
@canany(['update', 'view', 'delete'], $post) <!-- El usuario actual puede actualizar, ver o eliminar la publicación... -->@elsecanany(['create'], \App\Models\Post::class) <!-- El usuario actual puede crear una publicación... -->@endcanany
Al igual que con la mayoría de los otros métodos de autorización, puedes pasar un nombre de clase a las directivas @can
y @cannot
si la acción no requiere una instancia de modelo:
@can('create', App\Models\Post::class) <!-- El usuario actual puede crear publicaciones... -->@endcan @cannot('create', App\Models\Post::class) <!-- El usuario actual no puede crear publicaciones... -->@endcannot
Al autorizar acciones mediante políticas, puedes pasar una matriz como segundo argumento a las diversas funciones y ayudantes de autorización. El primer elemento en la matriz se utilizará para determinar qué política se debe invocar, mientras que el resto de los elementos de la matriz se pasan como parámetros al método de la política y se pueden utilizar para obtener contexto adicional al tomar decisiones de autorización. Por ejemplo, considera el siguiente método de definición de la política PostPolicy
que contiene un parámetro adicional $category
:
/** * Determina si el usuario dado puede actualizar la publicación. */public function update(User $user, Post $post, int $category): bool{ return $user->id === $post->user_id && $user->canUpdateCategory($category);}
Cuando intentas determinar si el usuario autenticado puede actualizar una publicación dada, puedes invocar este método de política de la siguiente manera:
/** * Actualiza la publicación de blog dada. * * @throws \Illuminate\Auth\Access\AuthorizationException */public function update(Request $request, Post $post): RedirectResponse{ $this->authorize('update', [$post, $request->category]); // El usuario actual puede actualizar la publicación del blog... return redirect('/posts');}