• ¡Bienvenido a XenFácil!

    Estás viendo el sitio como Invitado. Para poder participar en este sitio

    y obtendrás privilegios adicionales, acceso a otras áreas y mucho mas.

    ¡Es gratis!


    ¿Ya eres miembro? Inicia sesión

XF2.1 REST API

XenFacil.com

Administrador
#1
Bienvenido a otro Lo que ves para 2.1 y este es algo grande. Si no has visto los anteriores Lo que ves para XF 2.1, consulta aquí.

A pesar de que Halloween ha terminado, ¿por qué hacer clic en el enlace "Seguir foro" para darte un capricho? Se te enviará un correo electrónico cada vez que publiquemos información de novedades.

Mientras escribo esto, lo más sugerido ha sido una REST API y en 2.1 aquí está. Si bien esta es una característica más centrada en el desarrollador en sí misma, abre muchas más opciones de integración. Esto hará que sea más fácil obtener datos dentro o fuera de XenForo, sin tener que entender el marco PHP subyacente en el que se basa XF.

La API se descompone en algunos componentes distintos, así que analicemos esos a su vez.

Texto Original en XenForo (en inglés)...
 
Última edición por un moderador:

lms

Administrador
#2
Claves API

Todos los accesos API precisan autentificación mediante claves. Éstas solo pueden generarse en el panel de control por un super administrador y, dado que crearlas es muy potente, el solo acceso a las mismas requerirá de contraseña. Es similar al "modo sudo" de GitHub.

Cuando se accede a la API, siempre actuarás como un único usuario. Esto se podrá utilizar para conocer quien ha creado un determinado contenido o qué permisos se utilizan, con alguna excepción tal y como se verá más adelante. Así, existen tres tipos de claves APIs:
  1. Claves de invitado. Solo podrán acceder a los datos que puede acceder un invitado. Por recalcarlo, debe crearse una clave incluso para el acceso de invitados.
  2. Claves de usuario. Están vinculadas a un usuario en particular. Todas las acciones (como crear untema) se atribuirán a este usuario teniendo en cuenta sus permisos.
  3. Claves de super-usuario. Estas son las más potentes y pueden acceder a la API como si fueran cualquier usuario evitando los permisos si fuera preciso. Estan diseñadas primordialmente para integraciones complejas. Por ejemplo, puede integrarse con un CMS de terceras partes que cree un tema cuando se publique un nuevo artículo. También permite crear temas como otro usuario dependiendo del autor del artículo o en un foro para el que el usuario no tiene permiso.
Las claves de super-usuario (o claves de usuario privilegiadas) son muy potentes, por lo que resulta importantísimo proteger cualquier clave creada de API por poderse utilizar por vías inesperadas, tales como la eliminación masiva de temas e incluso de nodos completos .

Para ayudar a limitar el daño potencial hecho por una clave comprometida, cada clave tiene un conjunto de ámbitos permitidos:






Esta captura de pantalla solo muestra unos pocos de los ámbitos disponibles. Cada tipo de contenido o acción expuesta por la API se cubrirá por algún tipo de ámbito. Por ejemplo, los temas y los mensajes se cubren por distintos ámbitos para limitar la lectura, escritura (creación, actualización o retirada de la vista pública) y eliminación física. Por seguridad, solo se obtendrá una clave por ámbito de API que se intente utilizar.

Ninguna clave API adopta una acción en particular salvo en un ámbito relevante. Por ejemplo, si se tiene una integración que precisa de una clave de super-usuario para publicar un tema, se querrá obtenerla del tipo thread:write -tema:escritura- (así como thread:read -tema:lectura-), pero no se querrá obtener una del tipo node:delete -nodo:eliminar o user:delete -usuario:eliminar-.

(Para los que lleven la cuenta, los ámbitos de API utilizan los valores de relación de entidad a través de cierres tal y como se indicó el martes. La convención tipo:acción se dá en varias APIs, por lo que tiene sentido el utilizarlo también, pero eso no es válido como nombre de frase.)

Para mejorar la seguridad, cuando se genera o modifica una clave API, se enviará un email a todos los super admins.

Ahora que ya tenemos una clave API, se querrá acceder a la API...
 
Última edición:

lms

Administrador
#3
Accediendo a la API

La API de una instalación particular siempre se encuentra en <XF url>/api/. (Adviértase que, para asegurar URLs consistentes, la API siempre utiliza el estilo "URLs amistosas".) Se accederá a todas las rutas desde esta URL.

La clave APIgenerada debe pasarse a través de un encabezado XF-Api-Key personalizado agregado al requerimiento.

Si se utiliza una clave de super-usuario, puede pasarse el ID de usuario del usuario efectivo a través del encabezado XF-Api-User; si no se pasa ningún usuario en ella, la solicitud devendrá a actuar como invitado.

Se pueden enviar parámetros adicionales de solicitud a través de la cadena de consulta o en el cuerpo de application/x-www-form-urlencoded. (Nota: también se admite multipart/form-data, pero solo para solicitudes POST).

Por defecto, todas las solicitudes respetarán los permisos de usuario. Las claves de super usuario pueden evitar esto mediante solicitud-por-solicitud configurando a 1 el parámetro api_bypass_permissions.

La API siempre responde con JSON. Los errores siempre devolverán un código de respuesta del rango 400. Las solicitudes con éxitos devuelven un código 200. While not commonly used, las redirecciones devolverán un código de rango 300.

Los errores siempre adoptan una forma estándar. Este es un ejemplo:
JSON:
{
    "errors": [
        {
            "code": "api_key_not_found",
            "message": "API key provided in request was not found.",
            "params": []
        }
    ]
}

Adviértase que se puede devolver más de un error (tal y como se tienen al crear un tema).

La mayoría de las veces, El código de error es el nombre de una frase utilizada a este fin. El mensaje en sí mismo puede cambiar y no debe utilizarse para automatizar procesos.

Para las solicitudes exitosas, la respuesta variará según la ruta, por lo que se hablará más sobre rutas ...
 
Última edición:

lms

Administrador
#4
Rutas de API

Como esto es un estilo REST de la API, el contenido al que se accede y la acción adoptada se basan en la URL y en el método HTTP utilizado. Primariamente se utilizan GET, POST y DELETE.

Existen numerosas rutas en la API por lo que no se van a baordar en detalle todas ellas. Para más detalles de las rutas disponibles y de sus métodos de entrada y salida se enconrarán en la documentación sobre la API (existen herramientas incluidas para ayudar en la generación automática de documentación que los desarrolladores de complementos pueden utilizar para sus propias rutas API.)

Se adoptará /api/threads/123/ como ejemplo. Cuando se solicita esta URL, lo que ocurre depende del método utilizado:
  • GET - Obtiene información sobre el tema con ID 123. Si se pasa el parámetro with_posts, también se incluye una página de mensajes.
  • POST - Actualiza la información de los temas, tasl como el título o si está anclado o no. Cualquier elemento que no se desee actualizar puede omitirse en los parámetros. Adviértase que esto no sirve para responder en este tema.
  • DELETE - como cabría suponer, permite eliminar el tema. Pueden pasarse los parametros para controlar el tipo de eliminación (físico/retirada de la vista pública), razón esgrimida, etc.
Cada ruta puede tener también acciones más específicas. Por ejemplo, GET /api/threads/123/posts?page=2 obtendrá la segunda página de los mensajes de este tema.

Este es un ejemplo de la salida de GET /api/threads/2/:
JSON:
 {
    "thread": {
        "thread_id": 2,
        "node_id": 2,
        "title": "Test API thread",
        "reply_count": 2,
        "view_count": 19,
        "user_id": 1,
        "username": "Example",
        "post_date": 1538157093,
        "sticky": false,
        "discussion_state": "visible",
        "discussion_open": true,
        "discussion_type": "",
        "first_post_id": 3,
        "last_post_date": 1540908968,
        "last_post_id": 21,
        "last_post_user_id": 1,
        "first_post_reaction_score": 0,
        "prefix_id": 0,
        "Forum": {
            "node_id": 2,
            "title": "Main forum",
            "node_name": null,
            "description": "",
            "node_type_id": "Forum",
            "parent_node_id": 1,
            "display_order": 100,
            "display_in_list": true,
            "breadcrumbs": [
                {
                    "node_id": 1,
                    "title": "Main category",
                    "node_type_id": "Category"
                }
            ],
            "type_data": {
                "allow_posting": true,
                "allow_poll": true,
                "require_prefix": false,
                "min_tags": 0,
                "discussion_count": 6,
                "message_count": 20,
                "last_post_id": 22,
                "last_post_date": 1540982158,
                "last_post_username": "test",
                "last_thread_id": 3,
                "last_thread_title": "Test API thread",
                "last_thread_prefix_id": 0,
                "can_create_thread": true,
                "can_upload_attachment": true
            }
        },
        "User": {
            "user_id": 1,
            "username": "Example",
            "email": "example@example.com",
            "visible": true,
            "activity_visible": true,
            "user_group_id": 2,
            "secondary_group_ids": [
                3,
                4
            ],
            "message_count": 16,
            "register_date": 1536666416,
            "trophy_points": 0,
            "user_state": "valid",
            "is_moderator": true,
            "is_admin": true,
            "is_staff": true,
            "is_banned": false,
            "reaction_score": 0,
            "custom_title": "",
            "warning_points": 0,
            "is_super_admin": true,
            "user_title": "Administrator",
            "age": 43,
            "dob": {
                "year": 1975,
                "month": 1,
                "day": 1
            },
            "signature": "",
            "location": "Somewhere",
            "website": "http://xenforo.com",
            "last_activity": 1540988599,
            "avatar_urls": {
                "o": null,
                "h": null,
                "l": null,
                "m": null,
                "s": null
            },
            "custom_fields": {
                "skype": "",
                "facebook": "",
                "twitter": ""
            },
            "is_ignored": false,
            "is_following": false,
            "can_edit": true,
            "can_ban": false,
            "can_warn": false,
            "can_view_profile": true,
            "can_view_profile_posts": true,
            "can_post_profile": true,
            "can_follow": false,
            "can_ignore": false,
            "can_converse": false
        },
        "is_watching": true,
        "visitor_post_count": 3,
        "can_edit": true,
        "can_edit_tags": false,
        "can_reply": true,
        "can_soft_delete": true,
        "can_hard_delete": false,
        "can_view_attachments": true
    }
}
Estos se derivan del sistema entidad. Mayormente, la entrada de mayor nivel es la entidad Thread (tema), aunque también pueden desearse ver un nodo (Forum) y User (usuario). La estructura de la API de una entidad en particular se define por opciones en campos específicos y por un nuevo método que permite definir otros elementos personalizados a incluir (como los resultados de varias salidas can_xyz).
 
Última edición:

lms

Administrador
#5
La API por dentro

Para el personal que desee utilizar la API no le es necesario entender cómo funciona internamente. Sin embargo, para los desarrolladores de complementos que quieran expandir los datos devueltos o agregar sus propias acciones es preciso conocer algo sobre su construcción. Esto es un resumen elevado.

La API se define a través de nuevos tipos de ruta. El sistema API utiliza, esencialmente, el mismo sistema de rutas de URL bien públicas bien admin, pero con pequeños ajustes. Por convención, threads/ reproduce al controlador XF:Threads y threads/123/ reproduce a XF:Thread. La última ruta se define con un sub-nombre con - y el formato de ruta incluye el modificador + que precisa que esté presente el parámetro. Por mayor facilidad, cuando se genera un enlace, si se pasa el dato en él, se intentará que coincida con la ruta correcta automáticamente.

Cuando se determina el nombre de una acción a llamar, el método de solicitud HTTP se antepondrá. Por ejemplo, GET /api/threads/123/ llama a XF:Thread y al método actionGet(). Similarmente, POST /api/threads/123/watch llama a XF:Thread :: actionPostWatch().

Los métodos del controlador de la API se devuelven, generalmente, mediante llamadas al método XF\Api\Controller\AbstractController::apiResult($result). Esto contendrá una matríz, una entidad o un objeto resultante de la API. Estos se convertirán en la representación precisa JSON si fuera necesario.

La mayoría de veces, los resultados del controlador se realizarán sobre elementos estructurales y de representación en entidades de la API. Para una entidad en particular, puede llamarse a $entity->toApiResult() o a $collection->toApiResults() como colección. Ambos conllevan argumentos que permiten pasar en un nivel "verbal" u otras opciones de control del nivel de la salida.

Para las entidades y por defecto, emitirán una excepción si se intenta obtener su representación en la API. Las entidades deben optar específicamente por ser representables en la API. Las columnas individuales también son opcionales.

Para activar la representación API de una entidad, puede desearse el sobreescribir el método setupApiResultData() en el tipo de entidad. Para una entidad muy básica, esto puede quedar vacío. do puede incluir código arbitrario para determinar qué dato se expone. Por ejemplo, algunos datos dependerán de que el visitante esté registrado:
PHP:
if ($visitor->user_id)
{
   $result->is_watching = isset($this->Watch[$visitor->user_id]);
   $result->visitor_post_count = $this->getUserPostCount();
}
Others might be the results from specific methods:
PHP:
$result->can_reply = $this->canReply();
$result->can_soft_delete = $this->canDelete();
Otras pueden precisar permisos específicos:
PHP:
if ($isBypassingPermissions || $visitor->hasAdminPermission('user'))
{
   $result->includeColumn(['email', 'user_group_id', 'secondary_group_ids', 'user_state']);
}
En la estructura de la entidad, pueden definirse columnas y relaciones en particular como resultados de la API etiquetándolos como 'api' => true.

En el fondo, extendiendo la API no existen diferencias significativas sobre el cómo se escribe el código "estándar" de XF2.
 
Última edición:
Arriba