Roles y Capacidades
Controla quién puede hacer qué dentro de tu plugin. Gestiona el sistema de usuarios, añade capacidades personalizadas y restringe el acceso a funciones sensibles de forma granular.
El control de acceso es el pilar de la seguridad de cualquier plugin. En este capítulo, desentrañaremos el sistema de roles y capacidades de WordPress, dejando atrás la dependencia de perfiles genéricos para adoptar una gestión basada puramente en acciones atómicas. Aprenderás a blindar tu código utilizando current_user_can(), a registrar roles personalizados adaptados a la lógica de negocio de tu proyecto y a asignar permisos propios con precisión quirúrgica. Dominar esta jerarquía es fundamental para garantizar que cada usuario interactúe únicamente con las funciones permitidas, creando extensiones fiables y profesionales.
12.1 El sistema de roles por defecto
WordPress implementa un sistema de control de acceso basado en roles (RBAC - Role-Based Access Control) que se apoya fundamentalmente en dos conceptos interconectados: Roles (perfiles) y Capabilities (capacidades).
Para desarrollar plugins seguros y bien integrados, es imperativo comprender que un rol no es más que una etiqueta o contenedor que agrupa un conjunto específico de capacidades. WordPress no evalúa inherentemente qué rol tiene un usuario para permitirle una acción, sino que verifica si el usuario posee la capacidad requerida para ejecutarla.
Los roles predeterminados
Una instalación estándar de WordPress (Single Site) incluye cinco roles por defecto. En instalaciones de red (Multisite), se añade un sexto rol jerárquicamente superior. A continuación, se detalla la estructura predeterminada de mayor a menor privilegio, junto con algunas de sus capacidades distintivas:
- Super Admin (Solo Multisite): Tiene acceso absoluto a la administración de la red de sitios y sobreescribe cualquier comprobación de capacidad.
- Administrator (Administrador): Posee todas las capacidades dentro de un sitio individual. Es el único rol estándar que puede interactuar con el ecosistema de extensiones (
activate_plugins,install_themes,manage_options). - Editor: Tiene el control total sobre el contenido. Puede crear, editar, publicar y eliminar cualquier tipo de entrada o página, independientemente de quién sea el autor (
edit_others_posts,publish_pages,moderate_comments). - Author (Autor): Puede gestionar única y exclusivamente su propio contenido. Tiene la capacidad de redactar, subir archivos multimedia y publicar sus propias entradas (
publish_posts,upload_files), pero no tiene acceso a páginas. - Contributor (Colaborador): Puede redactar y gestionar sus propias entradas, pero carece del privilegio de publicarlas (
edit_posts,delete_posts). Su contenido debe ser revisado por un Editor o Administrador. Tampoco puede subir archivos multimedia. - Subscriber (Suscriptor): El rol más básico. Solo tiene la capacidad de leer contenido público y gestionar su propio perfil de usuario en el panel (
read).
Arquitectura de datos: Cómo se almacenan los roles
A diferencia de otros sistemas de gestión de contenido, las definiciones de los roles y sus capacidades asociadas no están hardcodeadas en los archivos del núcleo de PHP para cada ejecución. Se almacenan de forma persistente en la base de datos.
Específicamente, el esquema completo de roles se guarda en la tabla wp_options (o el prefijo equivalente configurado en el capítulo 5) bajo la clave de opción wp_user_roles. Almacenarlo en la base de datos permite que los plugins puedan modificar permanentemente estas estructuras (como veremos en la sección 12.3).
Cuando un usuario recibe un rol, este no se asigna mediante una columna separada en la tabla wp_users. En su lugar, se guarda en la tabla wp_usermeta bajo la clave wp_capabilities. El valor es un array serializado que generalmente contiene el nombre del rol como clave y un booleano como valor.
TEXT
La clase global WP_Roles
WordPress gestiona todo este ecosistema en tiempo de ejecución a través de la clase WP_Roles. Durante el flujo de carga del núcleo (visto en el Capítulo 1), WordPress inicializa la variable global $wp_roles.
Esta instancia es la responsable de extraer la opción wp_user_roles de la base de datos y proveer los métodos para interactuar con ella. Si bien manipularás las capacidades más adelante con funciones envoltura (wrappers), es útil saber cómo inspeccionar el sistema por defecto directamente a través de su API de clases.
El siguiente bloque de código muestra cómo podrías recuperar y visualizar todos los roles registrados y sus capacidades asociadas utilizando la función wp_roles(), que actúa de forma segura sobre la global $wp_roles:
PHP
Comprender que los roles son mutables y que residen en la base de datos es el primer paso vital. Como desarrollador, tu código casi nunca debe preguntar "¿El usuario actual es un Autor?". Si tu plugin añade una funcionalidad para exportar un PDF, tu lógica debe abstraerse de los roles predeterminados y evaluar en base a capacidades: "¿El usuario actual tiene la capacidad de exportar_pdfs?". Si confías ciegamente en el nombre del rol, tu plugin fallará o se volverá inseguro si otro administrador decide eliminar el rol "Autor" de su sitio, o si otro plugin altera drásticamente los permisos por defecto.
12.2 Comprobación de capacidades
Como establecimos en la sección anterior, la regla de oro en la seguridad y el control de acceso en WordPress es comprobar siempre capacidades, nunca roles. Los roles pueden ser renombrados, modificados o eliminados por otros plugins, pero las capacidades representan la acción atómica que tu código está a punto de ejecutar.
WordPress proporciona una API sencilla pero extremadamente potente para realizar estas comprobaciones en cualquier punto de la ejecución de tu plugin.
La función principal: current_user_can()
La herramienta más utilizada en el arsenal de un desarrollador de WordPress es current_user_can(). Esta función evalúa si el usuario que ha iniciado la sesión actual posee una capacidad específica. Devuelve un valor booleano (true o false).
Su uso es obligatorio antes de procesar datos sensibles, renderizar páginas de opciones o permitir la ejecución de rutinas críticas.
PHP
Es importante destacar un "antipatrón" común: current_user_can( 'administrator' ). Aunque por razones de retrocompatibilidad WordPress permite pasar el nombre de un rol a esta función y devolverá true si el usuario tiene ese rol, es una práctica fuertemente desaconsejada. Rompe la abstracción del sistema de capacidades y hará que tu plugin sea incompatible con gestores de roles personalizados.
Comprobación en usuarios específicos: user_can()
En ocasiones, tu plugin no necesita evaluar al usuario que está navegando, sino a un usuario específico de la base de datos (por ejemplo, al renderizar una lista de usuarios y mostrar un botón de "Editar" solo junto a aquellos que tienen ciertos privilegios).
Para estos casos se utiliza user_can( $user, $capability ), donde $user puede ser un ID de usuario numérico o una instancia del objeto WP_User.
PHP
Capacidades Primitivas vs. Capacidades Meta
Para dominar el sistema de permisos, es crucial entender la diferencia entre dos tipos de capacidades que WordPress maneja internamente:
- Capacidades Primitivas: Son los permisos absolutos otorgados a un usuario y guardados en la base de datos. Por ejemplo,
edit_posts(editar entradas),manage_options(gestionar opciones) oupload_files(subir archivos). Son genéricas y no dependen del contexto. - Capacidades Meta: Son comprobaciones condicionales que dependen de un objeto específico. Por ejemplo,
edit_post(en singular). No puedes simplemente comprobar si un usuario tieneedit_post; necesitas decirle qué post quiere editar, porque el usuario podría tener permiso para editar sus propios posts, pero no los de otro autor.
Cuando pasas una capacidad meta a current_user_can(), debes pasar el ID del objeto como segundo argumento.
PHP
El flujo de evaluación (La función map_meta_cap)
¿Cómo sabe WordPress si edit_post para el ID 150 debe devolver true o false? Lo hace a través de un proceso de mapeo o traducción.
WordPress utiliza internamente la función map_meta_cap() para traducir una "capacidad meta" en una o varias "capacidades primitivas" requeridas para ese objeto específico.
TEXT
Este sistema de mapeo es extremadamente flexible y se utiliza exhaustivamente al desarrollar Custom Post Types (CPTs) complejos. Si tu plugin registra un CPT llamado factura, puedes definir capacidades meta como edit_factura y read_factura, y configurar cómo se mapean a las primitivas, permitiendo un control granular inmenso.
Puntos estratégicos de comprobación en un plugin
En el desarrollo de plugins, las comprobaciones de capacidades rara vez ocurren en el vacío. Existen "cuellos de botella" arquitectónicos donde siempre debes implementar estas validaciones:
- Registro de menús de administración: Funciones como
add_menu_page()oadd_submenu_page()(vistas en el Capítulo 7) requieren explícitamente una capacidad como argumento. WordPress ocultará el menú si el usuario no la posee. - Callbacks de AJAX (Capítulo 9): Los hooks
wp_ajax_*son puntos ciegos si no los proteges. Aunque ocultes un botón en el front-end o en el admin, un usuario malintencionado puede enviar una petición POST directa aadmin-ajax.php. Tu callback de PHP debe invocarcurrent_user_can()en la primera línea. - Endpoints de la REST API (Capítulo 13): Al registrar una ruta con
register_rest_route(), el argumentopermission_callbackes el lugar exacto y obligatorio para retornar el resultado de una evaluación de capacidades.
Utilizar current_user_can() de forma consistente asegura que la lógica de negocio de tu plugin respeta herméticamente la jerarquía y los permisos configurados por el administrador del sitio.
12.3 Creación de roles personalizados
A medida que tus plugins crecen en complejidad, es probable que los roles predeterminados de WordPress dejen de encajar con la lógica de negocio de tu proyecto. Si estás desarrollando un plugin de gestión escolar, asignar el rol de "Autor" a un profesor o de "Suscriptor" a un alumno puede resultar confuso semánticamente y limitante a nivel de arquitectura.
La solución es registrar roles personalizados que definan perfiles de usuario exactos para tu ecosistema.
La función add_role()
WordPress proporciona la función add_role() para insertar un nuevo perfil en el sistema. Su firma es bastante directa y requiere tres parámetros:
$role(string): El identificador interno o slug del rol (ej.gestor_eventos). Debe usar minúsculas y guiones bajos.$display_name(string): El nombre legible por humanos que aparecerá en la interfaz de administración (ej. "Gestor de Eventos"). Debería ser traducible.$capabilities(array): Un array asociativo donde las claves son los nombres de las capacidades y los valores son booleanos (truepara conceder la capacidad,falsepara denegarla explícitamente).
El error más común: El lugar de ejecución
Como vimos en la sección 12.1, los roles se guardan de forma persistente en la base de datos (en la tabla wp_options). Esto introduce una regla arquitectónica vital que separa a los desarrolladores novatos de los profesionales: nunca debes registrar un rol en hooks que se ejecutan en cada carga de página, como init o admin_init.
Llamar a add_role() en cada petición obliga a WordPress a actualizar la base de datos innecesariamente, lo que penaliza el rendimiento y puede causar problemas de concurrencia.
El lugar correcto para registrar un rol es la rutina de activación de tu plugin (cubierta en el Capítulo 2). De este modo, la escritura en la base de datos ocurre una única vez cuando el administrador activa la extensión.
TEXT
Implementación práctica en la activación
Veamos cómo estructurar el código para crear un rol llamado "Auditor", cuyo propósito sea poder leer todo el contenido y acceder al panel de administración, pero sin poder modificar absolutamente nada.
PHP
Al utilizar add_role(), si el rol ya existe en la base de datos (por ejemplo, si el plugin fue desactivado y reactivado, y el rol no se eliminó), la función fallará silenciosamente y devolverá null, evitando sobrescribir las capacidades que un administrador haya podido modificar posteriormente.
Clonar un rol existente
En muchas ocasiones, no querrás escribir decenas de capacidades primitivas desde cero para un rol que es casi idéntico a uno predeterminado. Puedes aprovechar la función get_role() para extraer las capacidades de un rol existente y usarlas como base.
PHP
Limpieza durante la desactivación o desinstalación
Mantener limpia la base de datos es una señal de código profesional. Si tu plugin crea roles exclusivos, lo habitual es eliminarlos cuando el plugin se desinstala mediante remove_role( $role ).
Dependiendo de la naturaleza de tu plugin, podrías decidir eliminar el rol en la desactivación (hook de desactivación) o preservarlo hasta que el usuario elimine el plugin por completo (archivo uninstall.php).
PHP
Nota de precaución: Si eliminas un rol, los usuarios que lo tenían asignado no perderán su cuenta, pero se quedarán sin ningún rol válido en el sistema (sus capacidades previas desaparecen). Si tu plugin va a eliminar roles en la desinstalación, es una buena práctica reasignar esos usuarios a un rol predeterminado, como subscriber, antes de ejecutar remove_role().
12.4 Asignación de permisos propios
Crear roles personalizados desde cero es útil para arquitecturas cerradas, pero en la inmensa mayoría de los plugins comerciales, el objetivo es integrarse con la estructura existente. Si tu plugin añade una nueva página de opciones o un Custom Post Type (CPT), lo ideal es definir capacidades propias (ej. gestionar_ajustes_devplugin, edit_facturas) y asignarlas selectivamente a los roles predeterminados que tengan sentido (como el Administrador y el Editor).
Inyección de capacidades a roles existentes
El proceso para añadir una capacidad a un rol existente se realiza mediante el método add_cap() de la clase WP_Role.
Al igual que ocurre con la creación de roles (sección 12.3), la asignación de capacidades modifica el array serializado guardado en la tabla wp_options. Por lo tanto, esta operación debe ejecutarse exclusivamente durante la rutina de activación del plugin, nunca en hooks de ejecución continua como init.
El siguiente patrón de código ilustra cómo inyectar permisos propios a los roles de Administrador y Editor cuando el plugin se activa:
PHP
Es un error común asumir que el rol administrator recibe mágicamente cualquier capacidad nueva que inventes. Si usas current_user_can('mi_capacidad_secreta') y no se la has asignado explícitamente al administrador (o no la has mapeado a una capacidad nativa como manage_options), el propio administrador del sitio tendrá el acceso denegado.
Limpieza de capacidades en la desinstalación
Del mismo modo que es tu responsabilidad añadir estas capacidades, debes ser un buen ciudadano del ecosistema y eliminarlas cuando tu plugin se elimine del sistema. Esto se logra iterando sobre los roles y utilizando el método hermano remove_cap().
PHP
Asignación de permisos a usuarios específicos
El sistema de roles y capacidades de WordPress tiene un nivel más de profundidad: las capacidades no solo se asignan a los roles, sino que pueden asignarse directamente a un usuario individual.
Cuando evaluamos a un usuario, WordPress construye sus permisos fusionando las capacidades del rol (o roles) que posee con las capacidades individuales que se le hayan asignado explícitamente en la tabla wp_usermeta.
TEXT
Esto es extremadamente potente para casos de uso excepcionales. Por ejemplo, si tienes 100 usuarios con el rol "Autor", pero quieres que solo uno de ellos (por ser el autor destacado del mes) pueda además publicar entradas sin revisión (publish_posts), no necesitas crear un rol nuevo llamado "Autor Destacado". Simplemente le asignas la capacidad a ese usuario en particular a través de la clase WP_User.
PHP
Notarás el uso de $usuario->add_cap( 'upload_files', false ). Esto inserta la capacidad en el perfil del usuario pero con un valor booleano falso. En la resolución de conflictos de WordPress, una capacidad denegada explícitamente a nivel de usuario siempre sobrescribe la misma capacidad concedida a nivel de rol. Es la forma perfecta de "banear" a un usuario de realizar una acción específica sin alterar su rol principal ni afectar al resto de usuarios de su mismo nivel.
Resumen del capítulo
En este capítulo hemos diseccionado el sistema de Control de Acceso Basado en Roles (RBAC) de WordPress, una pieza fundamental para garantizar la seguridad operativa y estructural de tus plugins. Hemos establecido que la regla inquebrantable es evaluar siempre capacidades (current_user_can) y nunca depender de los nombres de los roles. Comprendimos que tanto los roles como sus capacidades asociadas persisten en la base de datos, lo que nos obliga a interactuar con ellos mediante las funciones add_role, remove_role, add_cap y remove_cap exclusivamente en los ciclos de activación y desinstalación del plugin. Finalmente, hemos visto cómo el sistema permite una granularidad absoluta, permitiendo inyectar capacidades personalizadas a roles existentes o crear excepciones de permisos a nivel de usuario individual, facilitando la creación de flujos de trabajo altamente personalizados y seguros.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página