feat(api): endpoint fea/v1/crear-autor para alta de autores (#166)
POST /wp-json/fea/v1/crear-autor — permite a Mixbot/Inma dar de alta autores nuevos sin depender de intervención manual, sin necesitar el permiso sensible create_users de WP. Rol 'author' fijo en el código (no lo decide quien llama). Auth: is_user_logged_in() + edit_others_posts (nivel Editor+, ya lo cumple su cuenta actual). Idempotente por slug: si ya existe, devuelve el usuario existente en vez de duplicar/errorar. Ver gitea.feadulta.com#166 (protocolo entre Claudes, opción B elegida sobre A porque WP no permite nativamente restringir create_users a un solo rol, y sobre C porque evita el salto humano/agente en el bucle). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Fe Adulta — API crear-autor
|
||||||
|
* Description: Endpoint REST acotado para que Mixbot (Inma) dé de alta autores
|
||||||
|
* nuevos sin depender de que Rafa esté disponible, sin necesitar
|
||||||
|
* el permiso sensible create_users de WP. El rol siempre es
|
||||||
|
* 'author' (fijo en el código, no lo decide quien llama).
|
||||||
|
* Idempotente: si el slug ya existe, devuelve el usuario existente.
|
||||||
|
* Version: 1.0
|
||||||
|
*
|
||||||
|
* Ver issue gitea.feadulta.com/rafa/feadulta#166.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
add_action('rest_api_init', function () {
|
||||||
|
register_rest_route('fea/v1', '/crear-autor', [
|
||||||
|
'methods' => WP_REST_Server::CREATABLE,
|
||||||
|
'callback' => 'fea_crear_autor_handle',
|
||||||
|
'permission_callback' => 'fea_crear_autor_can_call',
|
||||||
|
'args' => [
|
||||||
|
'nombre' => ['required' => true],
|
||||||
|
'slug' => ['required' => false],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Editor o superior (mismo nivel que ya usan Inma/Mixbot para editar posts). */
|
||||||
|
function fea_crear_autor_can_call(WP_REST_Request $request) {
|
||||||
|
if (!is_user_logged_in()) {
|
||||||
|
return new WP_Error(
|
||||||
|
'fea_crear_autor_not_authenticated',
|
||||||
|
'Debes autenticarte para crear un autor.',
|
||||||
|
['status' => 401]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!current_user_can('edit_others_posts')) {
|
||||||
|
return new WP_Error(
|
||||||
|
'fea_crear_autor_forbidden',
|
||||||
|
'No tienes permiso para crear autores.',
|
||||||
|
['status' => 403]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fea_crear_autor_handle(WP_REST_Request $request) {
|
||||||
|
$nombre = trim((string) $request->get_param('nombre'));
|
||||||
|
if ($nombre === '') {
|
||||||
|
return new WP_Error(
|
||||||
|
'fea_crear_autor_invalid',
|
||||||
|
'nombre es obligatorio.',
|
||||||
|
['status' => 400]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$slug_input = trim((string) $request->get_param('slug'));
|
||||||
|
$login = sanitize_user(sanitize_title($slug_input !== '' ? $slug_input : $nombre), true);
|
||||||
|
if ($login === '') {
|
||||||
|
return new WP_Error(
|
||||||
|
'fea_crear_autor_invalid',
|
||||||
|
'No se pudo derivar un slug válido de nombre/slug.',
|
||||||
|
['status' => 400]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idempotencia: si el login/slug ya existe, se devuelve tal cual (created=false).
|
||||||
|
$existing = get_user_by('login', $login);
|
||||||
|
if ($existing) {
|
||||||
|
return fea_crear_autor_response($existing, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$email = $login . '@feadulta.com';
|
||||||
|
$i = 2;
|
||||||
|
while (email_exists($email)) {
|
||||||
|
$email = $login . $i . '@feadulta.com';
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = wp_insert_user([
|
||||||
|
'user_login' => $login,
|
||||||
|
'user_pass' => wp_generate_password(20),
|
||||||
|
'user_email' => $email,
|
||||||
|
'display_name' => $nombre,
|
||||||
|
'nickname' => $nombre,
|
||||||
|
'role' => 'author', // fijo: este endpoint nunca crea otro rol.
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (is_wp_error($user_id)) {
|
||||||
|
return new WP_Error(
|
||||||
|
'fea_crear_autor_failed',
|
||||||
|
'No se pudo crear el usuario: ' . $user_id->get_error_message(),
|
||||||
|
['status' => 500]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fea_crear_autor_response(get_userdata($user_id), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fea_crear_autor_response(WP_User $user, bool $created) {
|
||||||
|
return rest_ensure_response([
|
||||||
|
'id' => $user->ID,
|
||||||
|
'login' => $user->user_login,
|
||||||
|
'slug' => $user->user_nicename,
|
||||||
|
'display_name' => $user->display_name,
|
||||||
|
'role' => 'author',
|
||||||
|
'created' => $created,
|
||||||
|
]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user