Por qué comprobar capacidades de usuario y no roles WordPress
En el tutorial sobre como comprobar el rol de un usuario, un lector me preguntaba cómo podía obtener el rol con más peso. Yo le contesté que no pensaba que ese concepto de roles con peso existiera en WordPress. Esta idea me estuvo rondado unos días y finalmente he llegado a la conclusión de que el concepto existe pero que no nos puede servir de base para decidir sobre niveles de acceso del usuario. Aquí explico por qué llegué a esa conclusión.
User levels vs roles
En WordPress 1.5 se introdujo el sistema de «user levels», un sistema para controlar lo que cada usuario podía o no podía hacer en base al peso asignado al grupo o nivel al que perteneciera. Este sistema fue depreciado en WordPress 3.0 y se reemplazó totalmente por el sistema de roles y capacidades que había sido introducido en la versión 2.5 (voy a decir capacidades por ser la palabra utilizada en la documentación oficial en español aunque creo que sería más apropiado hablar de competencias).
En el sistema de roles y capacidades, cada rol tiene unas capacidades predeterminadas asignadas y generalmente los roles reciben nombres que rápidamente asociamos con una determinada jerarquía. Con esta jerarquía hacemos el sistema de roles equivalente al sistema de «user levels» mentalmente en un instante.
Pero, ¿por qué WordPress introduciría un nuevo sistema de usuarios igual que el anterior? Ahí está la clave, no son iguales.
Comprueba capacidades, no roles
Como decía, cada rol tiene asignado unas determinadas competencias predeterminadas. Para no desprestigiar la flexibilidad de WordPress, estas capacidades se pueden modificar a nuestro antojo. Por ejemplo, puedo quitar la capacidad para publicar posts al rol author:
$author = get_role('author');
$author->remove_cap( 'publish_posts' );
Pero el sistema de roles y capacidades no se queda ahí, también se pueden asignar capacidades concretas a usuarios individuales, del mismo modo que a un determinado usuario se le puede quitar alguna capacidad, independientemente de los roles que tenga asignados. Por ejemplo, a un usuario concreto, de rol author o no, si puedo permitirle publicar posts:
$user = new WP_User( $user_id );
$user->add_cap( 'publish_posts' );
Y más aún. Puedo definir roles y capacidades a mi antojo sin que necesariamente los nombres elegidos para los roles hagan referencia a su nivel de capacidades. Ni si quiera las capacidades tienen por qué ser mayores o menores. Es totalmente mi decisión. Por ejemplo:
add_role(
'mind_reader',
__( 'The Mind reader' ),
array(
'fly' => false,
'read_minds' => true
)
);
add_role(
'flying',
__( 'The Flying' ),
array(
'fly' => true,
'read_minds' => false
)
);
// El usuario de ID 85 puede hacer las dos cosas
// sin importar el rol que tenga
$user = new WP_User( 85 );
$user->add_cap( 'fly' );
$user->add_cap( 'read_minds' );
¿Cuál de los dos roles tiene más peso? ¿Y qué pasa con el usuario 85?. Cómo ves, es muy fácil deducir que comprobar roles de usuario no tiene ningún sentido para decidir si el usuario puede o no hacer algo o si puede o no acceder a alguna parte privada de nuestra web. Así que en lugar de roles de usuario tenemos que comprobar capacidades de usuario. Y es muy fácil, basta con comprobar el return de la función current_user_can()
.
if( current_user_can( 'fly' ) ) {
// El usuario puede volar
}
if( current_user_can( 'read_minds' ) ) {
// El usuario puede leer mentes
}
Ejemplo: comprobar si un usuario puede moderar comentarios vs comprobar si el usuario es administrador o editor
Vamos a suponer que hemos desarrollado un plugin y queremos mostrar la página de opciones sólo a usuarios que pueden moderar comentarios. De primeras se nos puede venir a la cabeza: «Ah, tengo que comprobar si el usuario es editor o administrador, que son los roles que tienen asignadas esas capacidades de forma pedeterminada».
Muy mal. Puede que otro plugin de la web, por el motivo que haya querido su dueño, que es su web y es libre de hacer lo que quiera, hay quitado la capacidad de moderar comentarios de los editores; o puede que a un determinado usuario le haya dado esa capacidad pero no el rol de editor ni el resto de sus capacidades. Así que la comprobación de si el usuario es «editor o superior» es un mal planteamiento.
Si queremos mostrar la página de opciones de nuestro plugin a los usuarios que pueden moderar comentarios, comprobemos eso y no otra cosa. Ya no sólo por qué las capacidades de roles y usuarios se puedan modificar y podamos acabar con resultados inesperados, sino también por que es lo conceptualmente correcto.
Así que NO haríamos esto:
$user = wp_get_current_user();
if( ! empty( $user ) && count( array_intersect( [ "editor", "administrator" ], (array) $user->roles ) ) ) {
// Dejar acceder al usuario por que puede moderar comentarios ¿Seguro?
}
Y haríamos esto:
if( current_user_can( "moderate_comments" ) ) {
// Dejar acceder al usuario por que puede moderar comentarios 100% seguro
}
Otro buen ejemplo lo tenemos en el tutorial sobre el acceso a wp-admin sólo a administradores. En ese caso lo idóneo no era comprobar el rol «admin» sino la capacidad «manage_options». En conclusión, las capacidades del usuario son lo que importa, el rol es tan sólo una etiqueta sin mucha importancia.