# Roles y permisos — bewpro.com

> Última actualización: 2026-05-07
> Sistema: Spatie Permission v5+ sobre rol/permiso pivot estándar.
> Fuente de verdad: `database/seeders/BewProRolesPermissionsSeeder.php`

## Filosofía

Spatie permite asignar **permisos directos al rol** y `$user->can('permission')`
chequea si el user tiene ese permiso (vía cualquiera de sus roles).

En vez de hardcodear `role:Administrator|System Admin` en middleware (frágil —
si agregás un rol nuevo hay que tocar todos los controllers), usamos
`permission:customers.view` etc. — al agregar un rol nuevo, solo tocás el seeder.

## Roles canónicos del marketplace

| Rol | Quién es | Acceso macro |
|---|---|---|
| **Client** | Customer pagante regular | Solo su panel `/my-projects` |
| **Reseller** | Partner que vende con su marca | Su panel + tools extra para gestionar muchos proyectos |
| **Admin Comercial** | Staff de operación día-a-día | Customers + Soporte + aprobar Resellers |
| **Administrator** | Admin general (founder, lead técnico) | Todo lo anterior + plataforma + estructura |
| **System Admin** | Idem Administrator hoy (alias para compatibilidad) | Todo |

> **Roles legacy del CMS** (`Author`, `Contributor`, `Editor`, `Member`, `Super Admin`)
> NO se tocan acá. Rigen los tenants pagantes. No los modifiques en bewpro.com
> sin saber qué hacés.

## Matriz de permisos

| Permiso | Client | Reseller | Comercial | Admin |
|---|:-:|:-:|:-:|:-:|
| `my.projects` | ✅ | ✅ | ✅ | ✅ |
| `my.billing` | ✅ | ✅ | ✅ | ✅ |
| `my.support` | ✅ | ✅ | ✅ | ✅ |
| `reseller.dashboard` | ❌ | ✅ | ❌ | ✅ |
| `reseller.bulk-import` | ❌ | ✅ | ❌ | ✅ |
| `reseller.white-label` | ❌ | ✅ | ❌ | ✅ |
| `reseller.commissions` | ❌ | ✅ | ❌ | ✅ |
| `customers.view` | ❌ | ❌ | ✅ | ✅ |
| `customers.edit` | ❌ | ❌ | ✅ | ✅ |
| `customers.reset-password` | ❌ | ❌ | ✅ | ✅ |
| `customers.export-csv` | ❌ | ❌ | ✅ | ✅ |
| `customers.assign-roles` | ❌ | ❌ | ❌ | ✅ |
| `customers.delete` | ❌ | ❌ | ❌ | ✅ |
| `resellers.review-applications` | ❌ | ❌ | ✅ | ✅ |
| `resellers.manage-program` | ❌ | ❌ | ❌ | ✅ |
| `support.view-all` | ❌ | ❌ | ✅ | ✅ |
| `support.respond` | ❌ | ❌ | ✅ | ✅ |
| `support.close` | ❌ | ❌ | ✅ | ✅ |
| `platform.settings` | ❌ | ❌ | ❌ | ✅ |
| `platform.modules` | ❌ | ❌ | ❌ | ✅ |
| `platform.commands` | ❌ | ❌ | ❌ | ✅ |

`Admin Comercial` no puede borrar customers ni cambiar roles (operación día-a-día
**sin** tocar estructura). Eso queda solo para Admin General.

## Test users canónicos

`php artisan bewpro:seed-test-users` crea/sincroniza:

| Email | Rol | Password | URL post-login |
|---|---|---|---|
| `coke_colombres@hotmail.com` | Client | `Customer1!` | `/my-projects` |
| `lacompaniad@gmail.com` | Reseller | `Reseller1!` | `/my-projects` (con items extra) |
| `leandro@lacompaniadigital.com` | Admin Comercial | `Comercial1!` | `/admin/customers` (read+edit, no delete/roles) |
| `juan@bewpro.com` | Administrator | `Admin1!` | `/admin/customers` (full) |

Idempotente — re-correr resincroniza password al conocido + asigna el rol único.

## Cómo agregar un permiso nuevo

1. Editá `database/seeders/BewProRolesPermissionsSeeder.php` → agregá el permiso al array del/los roles que deben tenerlo.
2. `php artisan db:seed --class=BewProRolesPermissionsSeeder` (idempotente).
3. En el controller relevante: `$this->middleware('permission:nuevo.permiso')->only(['metodo'])`.
4. En blade: `@can('nuevo.permiso') <button>...</button> @endcan`.

## Cómo agregar un rol nuevo

1. Agregá la entrada en `ROLE_PERMISSIONS` del seeder.
2. Re-correr el seeder.
3. Asignar a un user específico: `$user->assignRole('Nuevo Rol')` o vía `/admin/customers/{id}/edit`.

## Cómo asignar un rol a un user existente

**Vía panel** (Admin General logueado):
- `/admin/customers` → click en el email → checkboxes de roles → Guardar.

**Vía artisan**:
```bash
php artisan tinker
> User::where('email', '...')->first()->syncRoles(['Reseller']);
```

**Vía bulk** (Admin General):
- `/admin/customers` → seleccionar varios → "Asignar rol →" → elegir rol → Ejecutar.

## Permission cache

Spatie cachea permisos por 24h por default. Si cambiás la matriz y no ves el efecto inmediato:

```bash
php artisan permission:cache-reset
# o desde tinker:
app(Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();
```

El seeder ya hace `forgetCachedPermissions()` antes y después de modificar — re-correr el seeder es la forma más simple de invalidar.

## Anclajes

- Seeder: `database/seeders/BewProRolesPermissionsSeeder.php`
- Comando test users: `app/Console/Commands/SeedTestUsers.php`
- Controller con permissions granulares: `app/Modules/Clients/Controllers/Admin/CustomersController.php`
- Sidebar config: `config/demo1/menu.php` (filtra items por rol — Spatie no filtra en UI, solo en backend)
- Trait que carga permisos en User: `Spatie\Permission\Traits\HasRoles` en `app/Models/User.php:24`
