API está generando errores 404

Hola comunidad de Discourse,

Actualmente me encuentro con problemas en los puntos finales de la API de Discourse, específicamente relacionados con la suspensión de usuarios, y agradecería enormemente cualquier ayuda o guía que puedan ofrecer.

Resumen de los problemas

  1. 404 No encontrado:

    • Al usar el punto final:
      /admin/users/15/suspend.json, recibo consistentemente un error de “Página no encontrada”, a pesar de que el usuario existe.
    • También he probado el punto final alternativo:
      /admin/u/15/suspend.json, que resulta en el mismo problema.
  2. Respuesta HTML inesperada:

    • En lugar de devolver la respuesta JSON esperada, la API devuelve una página HTML con el mensaje:
      “¡Uy! Esa página no existe o es privada.”
    • Esto ocurre independientemente de si estoy usando curl o PowerShell para la solicitud.
  3. Clave API y permisos:

    • La clave API que se está utilizando tiene acceso completo de administrador, sin embargo, las solicitudes continúan devolviendo un error 404.
    • También he probado a usar claves granulares (restringidas a acciones de suspensión) y una clave de solo lectura, pero el problema persiste.
    • Curiosamente, el punto final funciona perfectamente cuando se accede a través de un navegador, pero falla cuando se utilizan solicitudes API con la clave.

Ejemplos de solicitudes

Ejemplo de curl

curl -X PUT "https://your-discourse-domain.com/admin/users/15/suspend.json" \
-H "Api-Key: [REDACTED_API_KEY]" \
-H "Api-Username: system" \
-H "Content-Type: application/json" \
-d '{"suspend_until": "2024-12-31", "reason": "Violation of community guidelines"}'

Ejemplo de PowerShell

# Script de PowerShell para suspender un usuario en Discourse

$baseUrl = "https://your-discourse-domain.com"
$userId = 15
$apiKey = "[REDACTED_API_KEY]"
$apiUsername = "system"
$suspendUntil = "2024-12-31"
$reason = "Violation of community guidelines"

$headers = @{
    "Api-Key" = $apiKey
    "Api-Username" = $apiUsername
    "Content-Type" = "application/json"
}

$body = @{
    suspend_until = $suspendUntil
    reason = $reason
} | ConvertTo-Json

$endpoint = "$baseUrl/admin/users/$userId/suspend.json"

try {
    $response = Invoke-RestMethod -Uri $endpoint -Method Put -Headers $headers -Body $body -ErrorAction Stop
    Write-Host "¡Usuario suspendido con éxito!" -ForegroundColor Green
} catch {
    Write-Host "Error al suspender al usuario:" -ForegroundColor Red
    Write-Host $_.Exception.Message
}

Detalles adicionales

  • Versión de Discourse: 3.4.0.beta3
  • Pasos de solución de problemas realizados: He intentado ajustar las cabeceras de la solicitud, incluyendo User-Agent y Referer, pero sin éxito.

Cualquier información o sugerencia para ayudar a resolver estos problemas sería muy apreciada. ¡Gracias de antemano por su tiempo y apoyo!

Saludos cordiales,
Ross

Tu ejemplo funciona tal cual, salvo por los parámetros esperados en nuestro sitio de prueba:

○ → curl -i -X PUT "https://try.discourse.org/admin/users/41/suspend.json" \
  -H "Api-Key: swordfish" \
  -H "Api-Username: michael" \
  -H "Content-Type: application/json" \
  -d '{"suspend_until": "2024-12-31", "reason": "Violation of community guidelines"}'

HTTP/2 200
server: nginx
date: Mon, 11 Nov 2024 19:27:44 GMT
content-type: application/json; charset=utf-8
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
x-permitted-cross-domain-policies: none
referrer-policy: strict-origin-when-cross-origin
x-discourse-username: michael
x-discourse-route: users/suspend
cache-control: no-cache, no-store
x-request-id: fe9c5ddc-b11a-45ba-ab41-9403eb53f255
cdck-proxy-id: app-router-tiehunter03.sea1
strict-transport-security: max-age=31536000
cdck-proxy-id: app-balancer-tieinterceptor1b.sea1

{
  "suspension": {
    "suspend_reason": "Violation of community guidelines",
    "full_suspend_reason": "Violation of community guidelines",
    "suspended_till": "2024-12-31T00:00:00.000Z",
    "suspended_at": "2024-11-11T19:27:44.927Z",
    "suspended_by": {
      "id": 85,
      "username": "michael",
      "name": "Michael Brown",
      "avatar_template": "/user_avatar/try.discourse.org/michael/{size}/639_2.png"
    }
  }
}
  • valida la clave API
    ¿muestra Discourse una autenticación de usuario válida (x-discourse-username) al hacer una simple GET con esa clave?
  • valida el ID de usuario
    ¿existe realmente? devolverá 404 si no es así
  • ¿estás detrás de Cloudflare?
    puede interferir con los parámetros
2 Me gusta
  1. Validación de la clave de API
    Se confirmó que la clave de API es válida usando el siguiente comando:
curl -X GET "https://redactedurl.com/admin/users/list/active.json" -H "Api-Key: LIVEPRODKEYHERE" -H "Api-Username: system"

La respuesta (con datos sensibles redactados por confidencialidad) es la siguiente:

[
  {
    "id": 1,
    "username": "User1",
    "name": "Redacted",
    "avatar_template": "/user_avatar/yourforum.com/user1/{size}/avatar.png",
    "active": true,
    "admin": true,
    "moderator": true,
    "trust_level": 4,
    "title": "Recognized Member",
    "days_visited": 6,
    "post_count": 3
  },
  {
    "id": 19,
    "username": "User2",
    "name": "Redacted",
    "avatar_template": "/letter_avatar_proxy/v4/letter/j/{size}.png",
    "active": true,
    "admin": false,
    "moderator": false,
    "trust_level": 1,
    "title": "Member (Unverified)"
  },
  {
    "id": 3,
    "username": "User3",
    "name": "Redacted",
    "avatar_template": "/user_avatar/yourforum.com/user3/{size}/avatar.png",
    "active": true,
    "admin": true,
    "moderator": true,
    "trust_level": 4,
    "title": "Community Founder"
  },
  {
    "id": -1,
    "username": "system",
    "name": "system",
    "avatar_template": "/user_avatar/yourforum.com/system/{size}/avatar.png",
    "active": true,
    "admin": true,
    "moderator": true,
    "trust_level": 4,
    "title": "Bot"
  }
]
  1. Confirmación de existencia del usuario
    Se verificó que el usuario de prueba (ID: 15) existe, como se demuestra al consultar los datos del usuario usando /admin/users/15/suspend.json:
{
  "id": 15,
  "username": "User15",
  "active": true,
  "admin": false,
  "moderator": false,
  "trust_level": 0,
  "days_visited": 1,
  "post_count": 0,
  "can_send_activation_email": true,
  "can_activate": false,
  "can_deactivate": true,
  "can_grant_admin": true,
  "can_grant_moderation": true,
  "can_impersonate": true,
  "groups": [
    {
      "name": "trust_level_0",
      "bio_excerpt": "New members with limited abilities"
    }
  ]
}

  1. Configuración de red
    El sitio no utiliza Cloudflare. En su lugar, opera detrás de un proxy inverso NGINX. La aplicación escucha en el puerto 8080 internamente, y NGINX maneja la terminación SSL en el puerto 443 para el acceso externo. La configuración app.yml no se vincula directamente al puerto 443, ya que NGINX se encarga de la gestión de certificados y SSL para garantizar una conectividad y disponibilidad seguras.

Hola,
Solo para hacer un seguimiento, creo que el alcance global en las claves API no incluye el alcance de suspensión. Estaba enfrentando el mismo error. Tuve que cambiar mi clave a una clave granular con el alcance de suspensión para que funcionara. También esperaba que la función de reactivar suspensión funcionara, pero parece que aún no está disponible a través de la API.