Cargando…

Esto está tardando más de lo esperado.

Construye un CRUD acotado al equipo

La clase base de recurso que mantiene un CRUD de Laravel Front dentro del equipo, y cómo registrar su ruta y sus permisos.

Weblabor Base construye sus pantallas de administración con Laravel Front: una clase de recurso declara los campos y el kit renderiza la lista, los formularios y la página de detalle. Ve El panel de administración en el sitio de la base. Dentro de un equipo la misma herramienta funciona, con una clase base que mantiene cada registro y cada verificación de permisos dentro del equipo. Esta guía la muestra.

La clase base

app/Front/Resources/Team/Resource.php:

namespace App\Front\Resources\Team;

use App\Front\Resources\Resource as Base;
use Illuminate\Database\Eloquent\Model;

class Resource extends Base
{
    public $guards = ['team'];
    public $layout = 'layouts.teams';
    public $section = 'team';

    public function indexQuery($query)
    {
        return $query->where('team_id', team()->id)->latest();
    }

    public function processDataBeforeSaving($data)
    {
        $data['team_id'] = team()->id;
        return $data;
    }

    public function mediaOwner(): ?Model
    {
        return team();
    }
}
Qué define Qué significa
$guards = ['team'] Los permisos retrieve, create, update y delete del recurso se crean en el guard team y se revisan contra los roles del equipo.
$layout = 'layouts.teams' Las pantallas se renderizan dentro del espacio de trabajo del equipo, con su barra lateral.
$section = 'team' El recurso aparece en la barra lateral del espacio de trabajo del equipo, y no en la del panel de administración.
indexQuery La lista muestra sólo los registros del equipo actual.
processDataBeforeSaving Un registro creado o actualizado desde el formulario pertenece al equipo actual, traiga lo que traiga la petición.
mediaOwner Un campo de imagen o de archivo del recurso sube a la biblioteca de archivos del equipo y cuenta contra el espacio del equipo, no del miembro.

Un recurso que en cambio extiende el App\Front\Resources\Resource de la base está mal de tres maneras a la vez: sus permisos caen en el guard web, así que un miembro con el rol de equipo correcto es rechazado; su lista muestra los registros de todos los equipos; y sus registros se guardan sin team_id.

Escribe uno

  1. La tabla necesita una columna team_id, con índice, que apunte a teams.
  2. Crea la clase bajo app/Front/Resources/Team/:
namespace App\Front\Resources\Team;

use App\Models\Project as Model;
use WeblaborMx\Front\Inputs;

class Project extends Resource
{
    public $base_url = '/team/projects';
    public $model = Model::class;
    public $icon = 'folder';

    public function fields()
    {
        return [
            Inputs\ID::make(),
            Inputs\Text::make('Name')->rules('required'),
            Inputs\Textarea::make('Description')->hideFromIndex(),
        ];
    }
}
  1. Regístrala en routes/team.php. Ese archivo ya corre dentro del grupo del equipo, con los middleware auth, security y team, así que el middleware team pone el contexto antes de que corra cualquier verificación, y la línea no necesita un grupo propio:
// routes/team.php
Route::front('Team\\Project');

El grupo no pide ninguna suscripción. Tu pantalla la protegen sus propios permisos, los que siembra el paso siguiente. Exigir una suscripción es decisión tuya: cuando la pantalla tenga que quedar cerrada para un equipo sin un plan activo, compruébalo en la propia pantalla, por ejemplo con team()->subscription('default')?->active(). No uses ensure.subscribed:team para eso, porque también pide manage plans y deja fuera a todo miembro que no tenga ese permiso.

Laravel Front nombra las rutas team.front.projects, team.front.projects.create y así sucesivamente.

  1. Siembra los permisos:
php artisan db:seed --class=PermissionSeeder

Con discover_front_permissions encendido en config/app.php, el seeder encuentra el recurso y crea retrieve project, create project, update project y delete project en el guard team: el singular del nombre de la tabla del modelo. El seeder sólo crea permisos; no se los da a ningún rol. Un equipo creado desde ese momento los recibe en su rol Administrador, porque TeamObserver::created() le da a ese rol todos los permisos team salvo los listados en team_restricted_permissions. Los equipos que ya existen no: escribe una migración que dé los permisos nuevos a cada rol llamado como team_owner_role en el guard team, como hace 2026_10_14_100001_create_the_manage_media_permission_of_the_team_guard.php con manage media. Cualquier otro miembro los recibe a través de un rol. Ve Roles y permisos del equipo.

  1. La barra lateral no necesita ninguna edición. Por $section = 'team', la barra lateral del espacio de trabajo del equipo lista el recurso, con su etiqueta en plural, para cada miembro cuyo rol pase el viewAny de la policy. Pon public $menu_group = 'Team'; para colocarlo en el grupo Equipo, junto a Miembros y Roles, o 'Billing', 'Files' o 'Administration' para uno de los otros grupos; sin él, el enlace queda arriba, junto a Dashboard. Los enlaces escritos a mano, como miembros, configuración y medios, están en resources/views/components/weblabor-teams/layouts/sidebars/team.blade.php.

La policy

Laravel Front le pregunta a la policy del modelo. Extiende App\Policies\BasePolicy y nombra el permiso:

namespace App\Policies;

class ProjectPolicy extends BasePolicy
{
    protected string $name = 'project';
}

La propiedad es protected string $name, como la declara BasePolicy: un public $name es un error fatal cuando la clase se carga. El nombre es la segunda palabra de los permisos que creó el seeder, aquí project.

BasePolicy revisa el guard correcto según el contexto y rechaza un registro de otro equipo en view, update y delete. restore y forceDelete además piden que la persona tenga el rol de propietario del equipo (team_owner_role). Dos propiedades opcionales cierran la policy entera: protected $requiredFeature = 'projects'; rechaza toda verificación mientras el equipo actual no tenga esa capacidad, y protected $requiredConfig = 'features.projects'; la rechaza mientras ese valor de configuración esté apagado. Sobrescribe un método sólo para una regla tuya, y llama primero al padre para que las verificaciones de equipo se mantengan.

El que trae el kit

App\Front\Resources\Team\Role, en /team/roles, es el CRUD de roles del equipo y el ejemplo a copiar para el acotado: extiende el App\Front\Resources\Role del panel de administración, no la clase base de arriba, y pone por sí mismo los mismos $guards, $layout y $section, acota su lista con indexQuery, escribe team_id y el guard team en processDataBeforeSaving, pone $menu_group = 'Team' y agrega la acción de clonar. Su ruta se registra de la misma manera, con Route::front('Team\\Role').

Volver