Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/emmanueljarquin-sys/GrupoMecsaCMS/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Grupo Mecsa CMS uses a flexible role-based access control (RBAC) system where each employee is assigned a role that determines their access to different modules and features. Roles are stored in the Empleados table and referenced throughout the system.

Standard Roles

The system includes six predefined standard roles that cannot be deleted:

Administrador

Full system access with ability to manage users, roles, and all modules

Ventas

Access to sales-related modules including clients and opportunities

Proyectos

Project management access with ability to view and edit project data

Recepción

Reception desk access for basic customer service features

Mercadeo

Marketing team access for content, blog, and SEO management

Contabilidad

Accounting access for financial modules and reports

Role Structure

Database Schema

Roles are stored in the Empleados table in the public schema:
CREATE TABLE public."Empleados" (
  id UUID PRIMARY KEY,
  nombre VARCHAR,
  apellido VARCHAR,
  email VARCHAR UNIQUE,
  rol VARCHAR,  -- Role name (e.g., 'Administrador', 'Ventas')
  chat_role VARCHAR,
  departamento VARCHAR,
  activo BOOLEAN DEFAULT true,
  sistemas_acceso JSONB  -- Array of accessible systems ['CMS', 'Chat', etc.]
);

Session Storage

Role information is stored in the session after login:
login.php:95-97
$_SESSION['rol'] = $uData['rol'] ?? '';
$_SESSION['chat_role'] = $uData['chat_role'] ?? '';
$_SESSION['nombre'] = $uData['nombre'] ?? '';

Role Management Interface

Administrators can manage roles through the admin_roles.php interface.

Fetching Available Roles

The system fetches roles with user counts:
admin_roles_api.php:36-72
if ($action === 'get_roles') {
    // Get roles with user counts from Empleados table
    $res = supabase_request_service('GET', 
        'Empleados?select=rol&activo=eq.true', 
        null, 
        ['Accept-Profile: public']
    );
    $roles_raw = ($res['http'] === 200 && is_array($res['json'])) ? $res['json'] : [];
    
    // Count users per role
    $counts = [];
    foreach ($roles_raw as $r) {
        $rol = strtolower(trim($r['rol'] ?? ''));
        if ($rol === '') continue;
        $counts[$rol] = ($counts[$rol] ?? 0) + 1;
    }

    $standard = ['ventas', 'proyectos', 'administrador', 'recepcion', 'mercadeo', 'contabilidad'];
    $result = [];
    
    // Add standard roles first
    foreach ($standard as $s) {
        $result[] = [
            'nombre' => $s, 
            'total' => $counts[$s] ?? 0, 
            'is_standard' => true
        ];
    }
    
    // Add custom roles
    foreach ($counts as $nombre => $total) {
        if (!in_array($nombre, $standard)) {
            $result[] = [
                'nombre' => $nombre, 
                'total' => $total, 
                'is_standard' => false
            ];
        }
    }
    
    echo json_encode(['success' => true, 'roles' => $result]);
}
Standard roles are always displayed first, followed by any custom roles that have been created.

Creating New Roles

Administrators can create custom roles:
admin_roles_api.php:117-136
if ($action === 'create_rol') {
    $rol_nombre = trim($input['rol_nombre'] ?? '');
    if (empty($rol_nombre)) {
        echo json_encode(['success' => false, 'error' => 'Nombre de rol requerido']);
        exit;
    }

    // Define default views for new roles
    $vistas = [
        'dashboard','usuarios','categorias','clientes','proyectos','empleados',
        'departamentos','testimoniales','preguntas','contenido','templates',
        'menus','pages','media','seo','blog','vacantes','contactos'
    ];

    $rows = [];
    foreach ($vistas as $v) {
        $rows[] = [
            'rol_nombre' => $rol_nombre, 
            'vista_slug' => $v, 
            'puede_ver' => false
        ];
    }

    $res = supabase_request_service('POST', 'rol_permisos', $rows);
    echo json_encode(['success' => ($res['http'] >= 200 && $res['http'] < 300)]);
}
When a new role is created, it’s automatically assigned permission entries for all system views with puede_ver set to false. Administrators must then configure the permissions.

Deleting Custom Roles

Only custom roles without assigned users can be deleted:
admin_roles_api.php:139-149
if ($action === 'delete_rol') {
    $rol_nombre = trim($input['rol_nombre'] ?? '');
    
    // Check if role has assigned users
    $chk = supabase_request_service('GET', 
        "Empleados?rol=eq." . urlencode($rol_nombre) . "&select=id&limit=1", 
        null, 
        ['Accept-Profile: public']
    );
    if ($chk['http'] === 200 && !empty($chk['json'])) {
        echo json_encode(['success' => false, 'error' => 'El rol tiene usuarios asignados']);
        exit;
    }
    
    supabase_request_service('DELETE', "rol_permisos?rol_nombre=eq." . urlencode($rol_nombre));
    echo json_encode(['success' => true]);
}
Standard roles cannot be deleted. Custom roles can only be deleted if no employees are currently assigned to them.

Assigning Roles to Users

Roles are assigned through the employee management interface:
update_employee_role.php:25-38
$id = $_POST['id'] ?? '';
$rol = trim($_POST['rol'] ?? '');
$chat_role = trim($_POST['chat_role'] ?? '');
$departamento = trim($_POST['departamento'] ?? '');

if (empty($id)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'error' => 'ID requerido']);
    exit;
}

$payload = [];
if ($rol !== '') $payload['rol'] = $rol;
if ($chat_role !== '') $payload['chat_role'] = $chat_role;
if ($departamento !== '') $payload['departamento'] = $departamento;

$res = supabase_request_service('PATCH', "Empleados?id=eq.$id", $payload, ['Accept-Profile: public']);

Role Resolution

The system uses resolve_user.php to determine the current user’s role and permissions:
resolve_user.php:50-66
// Normalize and calculate permissions
$uRole = strtolower(trim($cms_user_role));
$uEmail = strtolower(trim($cms_user_email));

// Emergency admin bypass
$isEmmanuel = (
    $uEmail === 'emmanuel.jarquin@grupomecsa.net' || 
    $uEmail === 'emmanueljarquin@hotmail.com' || 
    $uEmail === 'emmanuelerj@gmail.com'
);

// Role mapping
$is_admin = ($uRole === 'administrador' || $uRole === 'admin') || $isEmmanuel;
$is_rrhh = ($uRole === 'rh' || $uRole === 'rrhh' || $uRole === 'recursos humanos');
$is_proyecto = ($uRole === 'proyectos' || $uRole === 'proyecto' || 
                $uRole === 'proyectos_edicion' || $uRole === 'proyectos_lectura');
$is_comercial = ($uRole === 'ventas' || $uRole === 'comercial');

Permission Variables

The resolve script provides these boolean variables for permission checks:
VariableDescription
$is_adminTrue if user is administrator
$is_rrhhTrue if user is Human Resources
$is_proyectoTrue if user has project role
$is_comercialTrue if user has sales role
$is_staffTrue if user has any valid role

Role-Based Page Protection

Pages can require specific roles using the resolve script:
admin_roles.php:3-9
session_start();
if (!isset($_SESSION['token'])) {
    header("Location: ../login.php");
    exit;
}
require_once __DIR__ . '/../functions/resolve_user.php';

if (!$is_admin) {
    http_response_code(403);
    die("Acceso denegado. Se requieren permisos de administrador.");
}
1

Include resolve_user.php

The script loads and evaluates the current user’s role.
2

Check permission variable

Use $is_admin, $is_rrhh, etc. to verify access.
3

Deny or allow access

Return 403 error or allow page to load based on role check.

Role Icons and Display

The admin interface uses icons for visual role identification:
admin_roles.php:145-156
const icons = {
    'ventas': 'fa-dollar-sign',
    'proyectos': 'fa-hard-hat',
    'administrador': 'fa-crown',
    'recepcion': 'fa-concierge-bell',
    'mercadeo': 'fa-ad',
    'contabilidad': 'fa-file-invoice-dollar'
};
const defaultIcon = 'fa-user-tag';
const roleIcon = icons[r.nombre.toLowerCase()] || defaultIcon;

Systems Access

In addition to roles, users have a sistemas_acceso field that controls which systems they can access:
update_employee_role.php:45-66
if ($activo !== null) {
    // Fetch current systems
    $resGet = supabase_request_service('GET', 
        "Empleados?id=eq.$id&select=sistemas_acceso", 
        null, 
        ['Accept-Profile: public']
    );
    
    if ($resGet['http'] === 200 && !empty($resGet['json'])) {
        $sistemas = $resGet['json'][0]['sistemas_acceso'] ?? [];
        if (is_string($sistemas)) {
            $sistemas = json_decode($sistemas, true) ?: [];
        }
        
        $brand = 'CMS';
        if ($activo) {
            // Add CMS access
            if (!in_array($brand, $sistemas) && !in_array('cms', $sistemas)) {
                $sistemas[] = $brand;
            }
        } else {
            // Remove CMS access
            $sistemas = array_values(array_filter($sistemas, 
                fn($s) => strtoupper($s) !== $brand
            ));
        }
        $payload['sistemas_acceso'] = $sistemas;
        $payload['activo'] = $activo;
    }
}
The sistemas_acceso field is a JSON array that can contain values like ['CMS', 'Chat', 'Portal']. Users must have ‘CMS’ in this array to access the CMS, regardless of their role.

Best Practices

Principle of Least Privilege

Assign users only the roles they need to perform their job functions

Regular Audits

Periodically review role assignments and remove unnecessary access

Custom Roles

Create specific roles for unique access patterns rather than modifying standard roles

Documentation

Document what each role can access for training and compliance

Build docs developers (and LLMs) love