Overview
Core Projects implements a role-based access control (RBAC) system that restricts access to features and data based on user job positions (cargos). Each employee account is assigned a single role that determines their permissions throughout the application.
Role Types
The system recognizes the following primary roles defined in the cargos table:
Administrador Full system access - complete control over all modules and configurations
Gerente Management access - dashboards, reporting, and oversight capabilities
Directora Comercial Sales leadership - sales operations and team management
Asesora Comercial Sales representative - client interactions and sales execution
Contador Accounting access - financial reports and payment tracking
Role Implementation
Database Structure
Roles are stored in the cargos (positions) table and linked to employees:
class Empleado extends Authenticatable
{
protected $table = 'empleados' ;
protected $primaryKey = 'id_empleado' ;
public function cargo ()
{
return $this -> belongsTo ( Cargo :: class , 'id_cargo' , 'id_cargo' );
}
public function dependencia ()
{
return $this -> belongsTo ( Dependencia :: class , 'id_dependencia' , 'id_dependencia' );
}
}
class Cargo extends Model
{
protected $table = 'cargos' ;
protected $primaryKey = 'id_cargo' ;
protected $fillable = [
'nombre' ,
'descripcion'
];
public function empleados ()
{
return $this -> hasMany ( Empleado :: class , 'id_cargo' , 'id_cargo' );
}
}
Middleware Protection
The CheckCargo middleware enforces role-based access control:
app/Http/Middleware/CheckCargo.php
namespace App\Http\Middleware ;
use Closure ;
use Illuminate\Http\ Request ;
use Illuminate\Support\Facades\ Auth ;
class CheckCargo
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\ Request $request
* @param \ Closure $next
* @param string ...$cargosPermitidos
* @return mixed
*/
public function handle ( Request $request , Closure $next , ... $cargosPermitidos )
{
$empleado = Auth :: guard ( 'web' ) -> user ();
if (
! $empleado ||
! $empleado -> cargo ||
! in_array ( $empleado -> cargo -> nombre , $cargosPermitidos )
) {
abort ( 403 , 'No tienes permiso para acceder a esta sección.' );
}
return $next ( $request );
}
}
The middleware accepts multiple role names as parameters, allowing flexible permission definitions at the route level.
Permission Matrix
Administrative Access
Administrador + Gerente
Route :: middleware ([ 'auth' , 'check.cargo:Gerente,Administrador' ]) -> group ( function () {
Route :: get ( '/dashboard' , [ DashboardController :: class , 'index' ]);
// Project Management
Route :: resource ( 'proyectos' , ProyectoController :: class );
Route :: resource ( 'empleados' , EmpleadoController :: class );
// Configuration
Route :: get ( '/estados' , [ EstadosController :: class , 'index' ]);
Route :: get ( '/dependencias-cargos' , [ DependenciasCargosController :: class , 'index' ]);
// Property Management
Route :: resource ( 'torres' , AdminTorreController :: class );
Route :: resource ( 'apartamentos' , ApartamentoWebController :: class );
Route :: resource ( 'locales' , LocalWebController :: class );
Route :: resource ( 'parqueaderos' , ParqueaderoWebController :: class );
// Pricing Policies
Route :: resource ( 'politicas-precio-proyecto' , PoliticaPrecioProyectoWebController :: class );
// Admin Sales View
Route :: get ( '/admin/ventas' , [ VentaAdminController :: class , 'index' ]);
Route :: get ( '/admin/clientes' , [ ClienteAdminController :: class , 'index' ]);
});
Create, edit, and delete projects
Manage employees and roles
Configure system settings and states
Manage towers, floors, and properties
Set pricing policies
View all sales and client data
Access audit logs
Manage geographic data (countries, cities)
Sales Access
Directora Comercial, Asesora Comercial, Gerente, Administrador
Route :: middleware ([ 'auth' , 'check.cargo:Directora Comercial,Asesora Comercial,Gerente,Administrador' ])
-> group ( function () {
// Property Catalog
Route :: get ( '/catalogo' , [ CatalogoWebController :: class , 'index' ]);
Route :: get ( '/catalogo/{tipo}/{id}' , [ CatalogoWebController :: class , 'show' ]);
// Sales Operations
Route :: resource ( 'ventas' , VentaWebController :: class );
Route :: post ( '/ventas/separaciones/{id}/cancelar' ,
[ VentaWebController :: class , 'cancelarSeparacion' ]);
Route :: post ( '/ventas/separaciones/{id}/convertir-venta' ,
[ VentaWebController :: class , 'convertirEnVenta' ]);
// Client Management
Route :: resource ( 'clientes' , ClienteWebController :: class );
// Payment Plans
Route :: get ( '/plan-amortizacion-venta' ,
[ PlanAmortizacionVentaWebController :: class , 'index' ]);
Route :: resource ( 'pagos' , PagoWebController :: class );
// Sales Tools
Route :: get ( 'cotizador' , [ CotizadorWebController :: class , 'index' ]);
Route :: get ( '/catalogo/simulador/{tipo}/{id}' ,
[ SimuladorWebController :: class , 'index' ]);
// Sales Targets
Route :: get ( '/metas' , [ MetasDashboardController :: class , 'index' ]);
});
View property catalog
Create and manage sales
Process separations and conversions
Manage client information
Create payment plans
Record payments
Use quotation tools
View personal sales targets
Management Access
Gerente Only
Route :: middleware ([ 'auth' , 'check.cargo:Gerente' ]) -> group ( function () {
// Management Dashboard
Route :: get ( '/gerencia/dashboard' , [ GerenciaDashboardWebController :: class , 'index' ]);
Route :: get ( '/gerencia/dashboard/datos' , [ GerenciaDashboardWebController :: class , 'datos' ]);
// Sales Target Management
Route :: get ( '/gerencia/metas' , [ MetasController :: class , 'index' ]);
Route :: post ( '/gerencia/metas' , [ MetasController :: class , 'store' ]);
Route :: put ( '/gerencia/metas/{id}' , [ MetasController :: class , 'update' ]);
Route :: delete ( '/gerencia/metas/{id}' , [ MetasController :: class , 'destroy' ]);
// Reports
Route :: get ( '/gerencia/plan-pagos-ci/export' ,
[ PlanPagosCIExportController :: class , 'export' ]);
Route :: get ( '/gerencia/login-logs' , [ GerenciaLoginLogController :: class , 'index' ]);
});
Manager-Specific Permissions
Access management dashboard with KPIs
Set and modify sales targets for team
Export payment plan reports
View login audit logs
Access advanced analytics
Accounting Access
Contador
Route :: middleware ([ 'auth' , 'check.cargo:Contador' ]) -> prefix ( 'contabilidad' ) -> group ( function () {
// Sales Financial View
Route :: get ( '/ventas' , [ ContabilidadVentasWebController :: class , 'index' ]);
Route :: get ( '/ventas/{id}' , [ ContabilidadVentasWebController :: class , 'show' ]);
// Financial Reports
Route :: get ( '/reportes/plan-pagos-ci' ,
[ ContabilidadVentasWebController :: class , 'planPagosCI' ]);
Route :: get ( '/reportes/plan-pagos-ci/export' ,
[ ContabilidadVentasWebController :: class , 'exportPlanPagosCI' ]);
});
View all sales with financial details
Access payment tracking
View installment plans
Export financial reports
Read-only access to sales data
Role-Based Dashboards
Each role sees a tailored dashboard upon login:
Administrator Dashboard
System-wide statistics
Project overview
User management quick access
Recent activity logs
Configuration shortcuts
Manager Dashboard
app/Http/Controllers/Gerencia/GerenciaDashboardWebController.php
public function index ()
{
return Inertia :: render ( 'Gerencia/Dashboard' , [
'ventasTotales' => $this -> calcularVentas (),
'metasCumplimiento' => $this -> evaluarMetas (),
'estadisticasEquipo' => $this -> estadisticasVendedores (),
'proyectosActivos' => Proyecto :: activos () -> count (),
]);
}
Features:
Sales performance metrics
Team target tracking
Project sales velocity
Commission calculations
Revenue forecasting
Sales Representative Dashboard
Property catalog access
Personal sales pipeline
Active separations
Payment follow-ups
Personal targets and progress
Quick quotation tools
Accountant Dashboard
Pending payments overview
Payment plan summaries
Collection reports
Financial reconciliation tools
Authentication Flow
Checking Permissions in Code
In Controllers
use Illuminate\Support\Facades\ Auth ;
public function sensitiveAction ()
{
$empleado = Auth :: user ();
if ( $empleado -> cargo -> nombre !== 'Administrador' ) {
abort ( 403 , 'Acción no permitida' );
}
// Proceed with action
}
In Blade/Vue Templates
< template >
< div >
< button
v-if = " $page . props . auth . user . cargo . nombre === 'Administrador' "
@ click = " deleteProject "
>
Eliminar Proyecto
</ button >
</ div >
</ template >
In Routes (Preferred)
Route :: middleware ([ 'auth' , 'check.cargo:Administrador' ]) -> group ( function () {
// Only administrators can access these routes
});
Always enforce permissions at the route/controller level, not just in the UI. Client-side checks are for UX only and can be bypassed.
Audit Trail
The system tracks user authentication events:
class LoginLog extends Model
{
protected $fillable = [
'id_empleado' ,
'email' ,
'ip_address' ,
'user_agent' ,
'login_at'
];
public function empleado ()
{
return $this -> belongsTo ( Empleado :: class , 'id_empleado' , 'id_empleado' );
}
}
Administrators and Managers can view login logs to:
Monitor user activity
Detect suspicious access patterns
Verify employee work hours
Audit system usage
Best Practices
Principle of Least Privilege Grant users only the permissions necessary for their job function
Role-Based, Not User-Based Define permissions by role, not individual users
Server-Side Enforcement Always validate permissions on the backend
Audit Everything Log sensitive actions for accountability
Architecture System architecture and design patterns
Projects Project management and structure