# Permisos

Zeus Backoffice incorpora un sistema de permisos basado en las Policies de Laravel.

# Visión general

Un archivo Policy va relacionado con una sección a través de su nombre.
Por ejemplo, una sección cuya clase sea Posts.php tendrá asociada su Policy PostsPolicy.php.

Al igual que las secciones residen en la carpeta Sections, sus policies asociadas residen en la carpeta Policies.

En un archivo Policy se puede especificar si se permite o no realizar acciones como mostrar una sección, crear, actualizar, eliminar, realizar acciones personalizadas y mostrar elementos y campos.

# Crear Policy

Las Policies se pueden crear fácilmente mediante un comando.

El nombre que hay que especificar al crearla corresponde con el nombre de la sección asociada:

php artisan backoffice:Policy NombreSeccion

Con esto se creará un archivo en la carpeta Policies junto a la carpeta Sections, con los métodos index, create, update y delete retornando true:

namespace App\Backoffice\Policies;

use App\Models\User;

class PostsPolicy
{
    public function index(User $user): bool
    {
        return true;
    }

    public function create(User $user): bool
    {
        return false;
    }

    public function update(User $user): bool
    {
        return true;
    }

    public function delete(User $user): bool
    {
        return true;
    }
}

# Métodos genéricos

index
Sirve para restringir el acceso al listado de datos.
Esto también hará que se muestre o no la sección en la Sidebar.

create
Restringe el visualizar la vista de creación, el crear un registro nuevo y el mostrar el botón de acción CreateAction.

update
Restringe el visualizar la vista de edición, el actualizar un registro y mostrar el botón de acción de item EditItemAction.

delete
Restringe el eliminar un registro y mostrar el botón de acción de item DeleteItemAction.

# Recibir registro actual

Los métodos update, create y delete pueden recibir el registro actual como segundo parámetro para realizar comprobaciones sobre el propio item.
Por ejemplo, si queremos restringir la actualización de un registro sólo si el usuario logueado es el propietario del registro:

public function update(User $user, Post $post)
{
    return $post->user_id == $user->id;
}

# Métodos custom

Los métodos custom sirven para restringir acciones como CustomAction, CustomItemAction, restringir la visualización de elementos como DataTable, DataForm o Card y campos en un formulario.

Se basan en el uso de la función can que puede ser usadas en dichos elementos.

Por ejemplo, si tenemos un botón de acción custom y queremos aplicarle una regla de permiso llamada export:

// app/Backoffice/Sections/Users.php

protected function actions(): array
{
    return [
        CustomAction::make('Exportar', function () {
            // Código para exportar
        })->can('export')
    ];
}

En su archivo de policies tendremos que crear una función llamada export:

// app/Backoffice/Policies/UsersPolicy.php

class UsersPolicy
{
    ...

    public function export(User $user): bool
    {
        return $user->can_export == 1;
    }
}

# Aplicar a acciones de item custom

En un DataTable, puedes aplicar condiciones a los botones de acción custom de cada item.
Al estar relacionado con un item, junto con el usuario se recibirá también el item:

protected function itemActions(): array
{
    return [
        EditItemAction::make(),
        DeleteItemAction::make(),
        CustomItemAction::make('Exportar')
            ->execute(function (Model $item) {
                // Código para exportar
            })
            ->can('exportItem')
    ];
}
class PostsPolicy
{
    ...

    public function exportItem(User $user, Post $post): bool
    {
        return $post->user_id == $post->id;
    }
}

EditItemAction y DeleteItemAction

Por defecto, al botón de acción EditItemAction se aplica la condición update y al DeleteItemAction la condición delete.
Ambas reciben junto con el usuario el registro actual.

# Aplicar a campos

Los campos y sus elementos agrupadores como GroupFields y StackFields también son susceptibles de recibir una policy mediante la función can:






 




 




protected function fields(): array
{
    return [
        GroupFields::make('Datos generales', [
            TextField::make('Nombre', 'name')->required(),
            EmailField::make('Email', 'email')->required()->can('changeEmail')
        ]),
        StackFields::make('Datos de pago', [
            TextField::make('Tarjeta', 'card_number'),
            TextField::make('Caducidad', 'expire_in'),
        ])->can('billingData'),
        ImageField::make('Avatar', 'avatar')
    ];
}

# Aplicar a elementos

Los elementos como DataTable, DataForm y Card puede recibir una policy para que se muestren o no:









 



protected function extraElements(): array
{
    return [
         DataTable::make('Listado de paises', [
            TextField::make('Nombre', 'name'),
            TextField::make('ISO Code', 'iso_code')
        ])
        ->fromQuery(Country::query())
        ->can('showCountries')
    ];
}

# Múltiples condiciones

La función can puede recibir un string o un array para establecer múltiples condiciones:

CustomAction::make('Exportar', function () {
    // Código para exportar
})->can(['exportPDF', 'exportExcel'])
class UsersPolicy
{
    ...

    public function exportPDF(User $user): bool
    {
        return in_array('pdf', $user->can_export_in);
    }

    public function exportExcel(User $user): bool
    {
        return in_array('excel', $user->can_export_in);
    }
}