El botón de aprobación en el perfil del usuario no funciona

Continuando la discusión de La notificación indica que hay usuarios de X pendientes de aprobación, pero no se encuentra ninguno:

Hace poco volví a habilitar require_approval en mi foro. Inmediatamente después, recibí notificaciones sobre un usuario pendiente de aprobación, pero al hacer clic en el enlace del mensaje, no había ningún usuario en la cola de revisión. Desde entonces, he recibido esa notificación cada 7 días. Por eso, utilicé el explorador de datos para buscar al usuario que no había sido aprobado pero que no aparecía en la cola de revisión.

Pasos más detallados citados de otro tema

Así que, cuando miro la página de administración de usuarios, aparece el botón de aprobación esperado. El problema es que no funciona. No hay ninguna retroalimentación visible, como un modal que muestre un error. Pero sí hay uno en la consola de mi navegador.

Error en la consola del navegador
ajax.js:233  PUT https://my-forum.discourse.group/admin/users/123/approve 500 (Internal Server Error)
send @ jquery.js:9940
ajax @ jquery.js:9521
performAjax @ ajax.js:233
(anonymous) @ ajax.js:246
approve @ admin-user.js:220
approve @ index.js:224
(anonymous) @ d-button.gjs:206
invoke @ index.js:264
flush @ index.js:180
flush @ index.js:334
_end @ index.js:762
end @ index.js:565
_runExpiredTimers @ index.js:869
setTimeout
setTimeout @ index.js:39
_installTimerTimeout @ index.js:912
_reinstallTimerTimeout @ index.js:896
_later @ index.js:829
later @ index.js:652
next @ index.js:562
_triggerAction @ d-button.gjs:203
click @ d-button.gjs:161


/admin/users/123/anon84265489:1 Uncaught (in promise) {jqXHR: {…}, textStatus: 'error', errorThrown: ''}errorThrown: ""jqXHR: abort: ƒ (e)always: ƒ ()catch: ƒ (e)done: ƒ ()fail: ƒ ()getAllResponseHeaders: ƒ ()getResponseHeader: ƒ (e)jqTextStatus: "error"overrideMimeType: ƒ (e)pipe: ƒ ()progress: ƒ ()promise: ƒ (e)readyState: 4requestedUrl: "/admin/users/123/approve"responseText: "<!DOCTYPE html>\n<html>\n<head>\n  <title>Oops - Error 500</title>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n    <h1>Oops</h1>\n    <p>El software que impulsa este foro de discusión encontró un problema inesperado. Pedimos disculpas por las molestias.</p>\n    <p>Se registró información detallada sobre el error y se generó una notificación automática. Lo revisaremos.</p>\n    <p>No es necesaria ninguna acción adicional. Sin embargo, si el error persiste, puedes proporcionar detalles adicionales, incluidos los pasos para reproducir el error, publicando un tema de discusión en la categoría de retroalimentación del sitio.</p>\n</body>\n</html>\n"setRequestHeader: ƒ (e,t)state: ƒ ()status: 500statusCode: ƒ (e)statusText: "error"then: ƒ (e,i,n)[[Prototype]]: ObjecttextStatus: "error"[[Prototype]]: Object
Promise.then
approve @ admin-user.js:222
approve @ index.js:224
(anonymous) @ d-button.gjs:206
invoke @ index.js:264
flush @ index.js:180
flush @ index.js:334
_end @ index.js:762
end @ index.js:565
_runExpiredTimers @ index.js:869
setTimeout
setTimeout @ index.js:39
_installTimerTimeout @ index.js:912
_reinstallTimerTimeout @ index.js:896
_later @ index.js:829
later @ index.js:652
next @ index.js:562
_triggerAction @ d-button.gjs:203
click @ d-button.gjs:161

A continuación, revisé /logs:

Error en /logs
Mensaje (14 copias reportadas)

Reviewable::InvalidAction (No se puede realizar `approve_user` en ReviewableUser)
app/models/reviewable.rb:860:in 'Reviewable#validate_action!'
app/models/reviewable.rb:360:in 'Reviewable#perform'
app/controllers/admin/users_controller.rb:306:in 'Admin::UsersController#approve'
app/controllers/application_controller.rb:452:in 'block in ApplicationController#with_resolved_locale'
app/controllers/application_controller.rb:452:in 'ApplicationController#with_resolved_locale'
app/controllers/application_controller.rb:1101:in 'ApplicationController#ensure_dont_cache_page'
lib/middleware/omniauth_bypass_middleware.rb:35:in 'Middleware::OmniauthBypassMiddleware#call'
lib/middleware/crawler_hooks.rb:13:in 'Middleware::CrawlerHooks#call'
lib/content_security_policy/middleware.rb:12:in 'ContentSecurityPolicy::Middleware#call'
lib/middleware/anonymous_cache.rb:417:in 'Middleware::AnonymousCache#call'
lib/middleware/csp_script_nonce_injector.rb:12:in 'Middleware::CspScriptNonceInjector#call'
lib/middleware/track_view_session_id_injector.rb:12:in 'Middleware::TrackViewSessionIdInjector#call'
config/initializers/008-rack-cors.rb:26:in 'Discourse::Cors#call'
lib/middleware/default_headers.rb:13:in 'Middleware::DefaultHeaders#call'
config/initializers/100-quiet_logger.rb:20:in 'DiscourseRackQuietAssetsLogger#call'
config/initializers/100-silence_logger.rb:29:in 'SilenceLogger#call'
lib/middleware/enforce_hostname.rb:23:in 'Middleware::EnforceHostname#call'
lib/middleware/request_tracker.rb:372:in 'Middleware::RequestTracker#call'
lib/middleware/overload_protections.rb:18:in 'Middleware::OverloadProtections#call'
lib/middleware/processing_request.rb:14:in 'Middleware::ProcessingRequest#call'


Backtrace

app/models/reviewable.rb:860:in 'Reviewable#validate_action!'
app/models/reviewable.rb:360:in 'Reviewable#perform'
app/controllers/admin/users_controller.rb:306:in 'Admin::UsersController#approve'
actionpack (8.0.5) lib/action_controller/metal/basic_implicit_render.rb:8:in 'ActionController::BasicImplicitRender#send_action'
actionpack (8.0.5) lib/abstract_controller/base.rb:215:in 'AbstractController::Base#process_action'
actionpack (8.0.5) lib/action_controller/metal/rendering.rb:193:in 'ActionController::Rendering#process_action'
actionpack (8.0.5) lib/abstract_controller/callbacks.rb:261:in 'block in AbstractController::Callbacks#process_action'
activesupport (8.0.5) lib/active_support/callbacks.rb:120:in 'block in ActiveSupport::Callbacks#run_callbacks'
app/controllers/application_controller.rb:452:in 'block in ApplicationController#with_resolved_locale'
i18n (1.14.8) lib/i18n.rb:354:in 'I18n::Base#with_locale'
app/controllers/application_controller.rb:452:in 'ApplicationController#with_resolved_locale'
activesupport (8.0.5) lib/active_support/callbacks.rb:129:in 'block in ActiveSupport::Callbacks#run_callbacks'
app/controllers/application_controller.rb:1101:in 'ApplicationController#ensure_dont_cache_page'
activesupport (8.0.5) lib/active_support/callbacks.rb:129:in 'block in ActiveSupport::Callbacks#run_callbacks'
activesupport (8.0.5) lib/active_support/callbacks.rb:140:in 'ActiveSupport::Callbacks#run_callbacks'
actionpack (8.0.5) lib/abstract_controller/callbacks.rb:260:in 'AbstractController::Callbacks#process_action'
actionpack (8.0.5) lib/action_controller/metal/rescue.rb:27:in 'ActionController::Rescue#process_action'
actionpack (8.0.5) lib/action_controller/metal/instrumentation.rb:76:in 'block in ActionController::Instrumentation#process_action'
activesupport (8.0.5) lib/active_support/notifications.rb:210:in 'block in ActiveSupport::Notifications.instrument'
activesupport (8.0.5) lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'
activesupport (8.0.5) lib/active_support/notifications.rb:210:in 'ActiveSupport::Notifications.instrument'
actionpack (8.0.5) lib/action_controller/metal/instrumentation.rb:75:in 'ActionController::Instrumentation#process_action'
actionpack (8.0.5) lib/action_controller/metal/params_wrapper.rb:259:in 'ActionController::ParamsWrapper#process_action'
activerecord (8.0.5) lib/active_record/railties/controller_runtime.rb:39:in 'ActiveRecord::Railties::ControllerRuntime#process_action'
actionpack (8.0.5) lib/abstract_controller/base.rb:152:in 'AbstractController::Base#process'
actionview (8.0.5) lib/action_view/rendering.rb:40:in 'ActionView::Rendering#process'
rack-mini-profiler (4.0.1) lib/mini_profiler/profiling_methods.rb:90:in 'block in ActionController::Base#profile_method'
actionpack (8.0.5) lib/action_controller/metal.rb:252:in 'ActionController::Metal#dispatch'
actionpack (8.0.5) lib/action_controller/metal.rb:335:in 'ActionController::Metal.dispatch'
actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:67:in 'ActionDispatch::Routing::RouteSet::Dispatcher#dispatch'
actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:50:in 'ActionDispatch::Routing::RouteSet::Dispatcher#serve'
actionpack (8.0.5) lib/action_dispatch/routing/mapper.rb:32:in 'block in <class:Constraints>'
actionpack (8.0.5) lib/action_dispatch/routing/mapper.rb:62:in 'ActionDispatch::Routing::Mapper::Constraints#serve'
actionpack (8.0.5) lib/action_dispatch/journey/router.rb:53:in 'block in ActionDispatch::Journey::Router#serve'
actionpack (8.0.5) lib/action_dispatch/journey/router.rb:133:in 'block in ActionDispatch::Journey::Router#find_routes'
actionpack (8.0.5) lib/action_dispatch/journey/router.rb:126:in 'Array#each'
actionpack (8.0.5) lib/action_dispatch/journey/router.rb:126:in 'ActionDispatch::Journey::Router#find_routes'
actionpack (8.0.5) lib/action_dispatch/journey/router.rb:34:in 'ActionDispatch::Journey::Router#serve'
actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:908:in 'ActionDispatch::Routing::RouteSet#call'
lib/middleware/omniauth_bypass_middleware.rb:35:in 'Middleware::OmniauthBypassMiddleware#call'
lib/middleware/crawler_hooks.rb:13:in 'Middleware::CrawlerHooks#call'
rack (2.2.23) lib/rack/tempfile_reaper.rb:15:in 'Rack::TempfileReaper#call'
rack (2.2.23) lib/rack/conditional_get.rb:40:in 'Rack::ConditionalGet#call'
rack (2.2.23) lib/rack/head.rb:12:in 'Rack::Head#call'
actionpack (8.0.5) lib/action_dispatch/http/permissions_policy.rb:38:in 'ActionDispatch::PermissionsPolicy::Middleware#call'
lib/content_security_policy/middleware.rb:12:in 'ContentSecurityPolicy::Middleware#call'
lib/middleware/anonymous_cache.rb:417:in 'Middleware::AnonymousCache#call'
lib/middleware/csp_script_nonce_injector.rb:12:in 'Middleware::CspScriptNonceInjector#call'
lib/middleware/track_view_session_id_injector.rb:12:in 'Middleware::TrackViewSessionIdInjector#call'
config/initializers/008-rack-cors.rb:26:in 'Discourse::Cors#call'
rack (2.2.23) lib/rack/session/abstract/id.rb:266:in 'Rack::Session::Abstract::Persisted#context'
rack (2.2.23) lib/rack/session/abstract/id.rb:260:in 'Rack::Session::Abstract::Persisted#call'
actionpack (8.0.5) lib/action_dispatch/middleware/cookies.rb:706:in 'ActionDispatch::Cookies#call'
actionpack (8.0.5) lib/action_dispatch/middleware/callbacks.rb:31:in 'block in ActionDispatch::Callbacks#call'
activesupport (8.0.5) lib/active_support/callbacks.rb:100:in 'ActiveSupport::Callbacks#run_callbacks'
actionpack (8.0.5) lib/action_dispatch/middleware/callbacks.rb:30:in 'ActionDispatch::Callbacks#call'
actionpack (8.0.5) lib/action_dispatch/middleware/debug_exceptions.rb:31:in 'ActionDispatch::DebugExceptions#call'
actionpack (8.0.5) lib/action_dispatch/middleware/show_exceptions.rb:32:in 'ActionDispatch::ShowExceptions#call'
logster (2.21.0) lib/logster/middleware/reporter.rb:40:in 'Logster::Middleware::Reporter#call'
lib/middleware/default_headers.rb:13:in 'Middleware::DefaultHeaders#call'
lograge (0.14.0) lib/lograge/rails_ext/rack/logger.rb:18:in 'Rails::Rack::Logger#call_app'
railties (8.0.5) lib/rails/rack/logger.rb:29:in 'Rails::Rack::Logger#call'
config/initializers/100-quiet_logger.rb:20:in 'DiscourseRackQuietAssetsLogger#call'
config/initializers/100-silence_logger.rb:29:in 'SilenceLogger#call'
actionpack (8.0.5) lib/action_dispatch/middleware/request_id.rb:34:in 'ActionDispatch::RequestId#call'
lib/middleware/enforce_hostname.rb:23:in 'Middleware::EnforceHostname#call'
rack (2.2.23) lib/rack/method_override.rb:24:in 'Rack::MethodOverride#call'
rack (2.2.23) lib/rack/sendfile.rb:127:in 'Rack::Sendfile#call'
plugins/discourse-prometheus/lib/middleware/metrics.rb:14:in 'DiscoursePrometheus::Middleware::Metrics#call'
rack-mini-profiler (4.0.1) lib/mini_profiler.rb:191:in 'Rack::MiniProfiler#call'
message_bus (4.5.2) lib/message_bus/rack/middleware.rb:60:in 'MessageBus::Rack::Middleware#call'
lib/middleware/request_tracker.rb:372:in 'Middleware::RequestTracker#call'
actionpack (8.0.5) lib/action_dispatch/middleware/remote_ip.rb:96:in 'ActionDispatch::RemoteIp#call'
lib/middleware/overload_protections.rb:18:in 'Middleware::OverloadProtections#call'
lib/middleware/processing_request.rb:14:in 'Middleware::ProcessingRequest#call'
rails_failover (2.3.0) lib/rails_failover/active_record/middleware.rb:67:in 'block in RailsFailover::ActiveRecord::Middleware#call'
activerecord (8.0.5) lib/active_record/connection_handling.rb:401:in 'ActiveRecord::ConnectionHandling#with_role_and_shard'
activerecord (8.0.5) lib/active_record/connection_handling.rb:149:in 'ActiveRecord::ConnectionHandling#connected_to'
rails_failover (2.3.0) lib/rails_failover/active_record/middleware.rb:64:in 'RailsFailover::ActiveRecord::Middleware#call'
rails_multisite (7.0.0) lib/rails_multisite/middleware.rb:26:in 'RailsMultisite::Middleware#call'
railties (8.0.5) lib/rails/engine.rb:535:in 'Rails::Engine#call'
railties (8.0.5) lib/rails/railtie.rb:226:in 'Kernel#public_send'
railties (8.0

Env

HTTP HOSTS: my-forum.discourse.group

No estoy seguro de qué causa esto. Hay otros usuarios anonimizados que fueron aprobados sin problemas cuando habilité la configuración.

2 Me gusta

Eso es un «yo también» de mi parte, también.

(Edición: He descubierto exactamente un usuario en este estado, activo hace unas pocas semanas, no anonimizado)

2 Me gusta

Tu ‘yo también’ es muy útil como confirmación de que el hecho de que mi usuario haya sido anonimizado no es la razón de este error.

Data Explorer indica que el usuario es revisable por el moderador

user_id id type target_id target_type reviewable_by_moderator
anon84265489 264 ReviewableUser 123 User true
consulta
SELECT 
    u.id AS user_id,
    r.id,
    r.type,
    r.target_id,
    r.target_type,
    r.reviewable_by_moderator
FROM reviewables r
JOIN users u
    ON r.target_id = u.id
WHERE u.approved = false
  AND u.active = true
1 me gusta

No entiendo por qué esto está fallando, pero al menos puedo encontrar algunas partes del código que concluyen que esta acción no se puede realizar. Sin embargo, no veo por qué llegan a esa conclusión. Supongo que la lógica está en la línea 859 de reviewable.rb.

approve() tiene la línea 306 en users_controller.rb

perform() tiene la línea 360 en reviewable.rb

validate_action!() tiene la línea 860 en reviewable.rb, donde se lanza la excepción

Creo que el problema podría ser que el usuario ya ha sido revisado anteriormente. No estoy seguro de que sea posible volver a revisar al mismo usuario. Hasta ahora no he logrado reproducir esto.

Aún no he podido reproducirlo. Pero descubrí que el usuario que no aparece en la cola de revisión había sido marcado como suspect_user después de registrarse en diciembre. En ese momento, must_approve_users estaba desactivado en mi foro. Por lo tanto, actué sobre ellos en aquel entonces. No estoy seguro de que disagreed signifique que seleccioné mantener al usuario. Pero cuando intenté reproducirlo ahora, la única otra opción era eliminar al usuario. No sé cómo ocurrió status = 2.
Cuando activé must_approve_users hace unas semanas, el usuario no fue aprobado automáticamente porque había un elemento revisable con el user_id como target_id. Eso tiene sentido.

Pero aún no tengo idea de cómo terminé con un usuario que no aprobé, pero tampoco eliminé cuando fue marcado.

reviewable status status reason context created_at
264 disagreed 2 suspect_user NULL 2025-12-18T14:16:28.322Z
consulta
SELECT
    rs.reviewable_id,
    CASE
      WHEN rs.status = 0 THEN 'pendiente'
      WHEN rs.status = 1 THEN 'acordado'
      WHEN rs.status = 2 THEN 'discrepado'
      WHEN rs.status = 3 THEN 'ignorado'
    END as status,
    rs.status as status_id,
    rs.reason,
    rs.context,
    rs.created_at
FROM reviewable_scores rs
JOIN reviewables r
ON rs.reviewable_id = r.id
JOIN users u
ON r.target_id = u.id
WHERE u.approved = false
AND u.active = true
1 me gusta

Genial, parece que me ocurre lo mismo: un usuario (en mi caso, un usuario activo y en línea hasta hace un par de semanas) que, en un pasado lejano, adquirió el estado de usuario sospechoso.

Creo que este usuario probablemente se ha visto imposibilitado de usar el foro desde que activé la aprobación de nuevos usuarios.

Unido el 9 de abr. de 2021, última publicación el 16 de abr., visto el 16 de abr., 1311 vistas, nivel de confianza: miembro.

Estadísticas: 78 días visitados, 4 horas de tiempo de lectura, 3 minutos de tiempo de lectura reciente, 83 temas vistos, 491 publicaciones leídas, 6 dadas, 31 recibidas, 4 temas creados, 25 publicaciones creadas.

Al revisar nuevamente mi cola de revisión, no encuentro ningún elemento de esa fecha ni ningún elemento con ese nombre de usuario.

Ahora veo que en mi caso tuvimos un usuario spam, que obtuvo el ID 332, fue marcado y eliminado. Unos días después, tuvimos un nuevo usuario, que nuevamente obtuvo el ID 332.

Conociendo el ID de usuario del usuario válido afectado, ejecuté esta consulta en Data Explorer:

SELECT *
FROM reviewables
WHERE target_id = 332
ORDER BY created_at DESC