Skip to content

Seguridad y autorización ​

Arrel decide el acceso en el servidor, en cada endpoint. El frontend oculta los botones que no puedes usar, pero eso es comodidad: la protección real es que la API los rechaza.

Capas de una petición ​

Una petición a la API de un Resource pasa, en este orden, por:

  1. El middleware de config('arrel.middleware') (por ejemplo, identificar el tenant).
  2. La sesión de Sanctum (auth:sanctum).
  3. La verificación del correo y el segundo factor, si están activados (véase Autenticación).
  4. El middleware de config('arrel.authenticated_middleware').
  5. La autorización del Resource, de la página o de la acción.

Resources ​

Los cinco métodos canViewAny(), canView(), canCreate(), canEdit() y canDelete() delegan en la Policy del modelo, o se pueden sobrescribir (véase Resources).

Un Resource para el que canViewAny() es falso queda cerrado en todos los endpoints: el listado, pero también el esquema, la creación, la edición, el borrado, las acciones, las opciones de los campos y las relaciones responden 403. Sin esta regla, un modelo sin Policy dejaría canCreate() o canEdit() abiertos de manera independiente.

Esto quiere decir que, para un modelo sin Policy, todo queda permitido para cualquier usuario autenticado. Si el Resource debe ser restringido, define una Policy o sobrescribe canViewAny().

Acciones ​

  • Una acción con authorize() usa esa closure, con los mismos argumentos que handle().
  • Una acción sin authorize() exige canEdit() sobre el registro, o canCreate() si es standalone(). Declara authorize() en las acciones que deben quedar abiertas a más usuarios.
  • Las acciones incluidas siguen su habilidad: ViewAction pide canView(), EditAction y RestoreAction piden canEdit(), DeleteAction y ForceDeleteAction piden canDelete().
  • Las opciones que una acción ofrece a sus campos de relación solo se sirven a los usuarios que pueden ejecutarla.

Relaciones ​

Si un campo Relation declara query(), el alcance también se aplica al guardar: un registro que el alcance oculta del desplegable es rechazado con un error de validación, aunque alguien envíe su identificador a mano. Pasa igual en los formularios de un Resource, de un Relation manager y de una acción.

php
Relation::make('author_id')
    ->related(User::class)
    ->query(fn (Builder $query): Builder => $query->where('team_id', auth()->user()->team_id))

En la closure de query() de un campo de un Relation manager o de una acción, el registro padre llega como tercer argumento.

Subidas de archivos ​

  • Las subidas están limitadas a 60 por minuto y usuario.
  • Al guardar un registro, solo se mueven los archivos que realmente se han subido al directorio temporal (arrel-temp). Un valor que no corresponde a una subida real no se mueve.
  • El contenido de los campos RichEditor se sanitiza en el servidor en cada guardado.

Límites de intentos ​

QuéLímite
Inicio de sesión5 intentos fallidos por correo y dirección IP
Segundo factor de un inicio de sesión pendiente5 códigos incorrectos, y caduca a los 5 minutos
Envío del correo de verificación3 por minuto
Confirmar o desactivar el segundo factor10 por minuto
Subidas de archivos60 por minuto y usuario

Páginas ​

Page::canView() decide si una página es visible y accesible. Una página que no se puede ver sale de la navegación y responde 403 en la API. Para una CustomPage, visible() controla la entrada de navegación; la autorización de los datos que la página carga debes hacerla en los endpoints de tu aplicación, que son código tuyo.

Lista de comprobación ​

  • Cada modelo expuesto tiene una Policy, o el Resource sobrescribe los can...().
  • Las acciones que no deben ser solo para editores declaran authorize().
  • Los campos Relation que muestran registros ajenos tienen query().
  • sanctum.stateful contiene solo los dominios de tu panel.
  • El segundo factor es obligatorio (isRequiredFor()) para los roles con más privilegios.