Botão de aprovação no perfil do usuário não funciona

Continuando a discussão de A notificação afirma que há usuários X para aprovação, mas nenhum é encontrado:

Habiliti recentemente novamente a opção require_approval no meu fórum. Logo em seguida, recebi notificações sobre um usuário aguardando aprovação, mas ao clicar no link da mensagem, não havia nenhum usuário na fila de revisão. Desde então, recebo essa notificação a cada 7 dias. Por isso, usei o Data Explorer para encontrar o usuário que não foi aprovado, mas que não aparece na fila de revisão.

Passos mais detalhados citados de outro tópico

Então, quando olho para a página de administração dos usuários, há o botão de aprovação esperado. O problema é que ele não funciona. Não há nenhum feedback visível, como um modal mostrando um erro. Mas há um erro no console do meu navegador:

Erro no console do 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>O software que alimenta este fórum de discussão encontrou um problema inesperado. Pedimos desculpas pelo inconveniente.</p>\n    <p>Informações detalhadas sobre o erro foram registradas e uma notificação automática foi gerada. Vamos analisar.</p>\n    <p>Nenhuma ação adicional é necessária. No entanto, se o erro persistir, você pode fornecer detalhes adicionais, incluindo passos para reproduzir o erro, postando um tópico de discussão na categoria de feedback do site.</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

Em seguida, verifiquei /logs:

Erro em /logs
Mensagem (14 cópias relatadas)

Reviewable::InvalidAction (Não é possível executar `approve_user` em 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

Não tenho certeza do que causa isso. Há outros usuários anonimizados que foram aprovados sem problemas quando ativei a configuração.

2 curtidas

Isso é um „eu também

2 curtidas

Sua confirmação de que o fato de meu usuário ter sido anonimizado não é a razão para este erro foi muito útil.

O explorador de dados indica que o usuário é revisável pelo 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 curtida

Não entendo como isso está falhando, mas consigo ao menos encontrar algumas partes do código que concluem que essa ação não pode ser realizada. Porém, não vejo por que eles chegam a essa conclusão. Suponho que a lógica esteja na linha 859 do reviewable.rb.

O approve() está na linha 306 do users_controller.rb

O perform() está na linha 360 do reviewable.rb

O validate_action!() está na linha 860 do reviewable.rb, que lança a exceção

Acho que o problema pode ser que o usuário já tenha sido revisado antes. Não tenho certeza se é possível revisar o mesmo usuário novamente. Até agora, não consegui reproduzir isso.

Ainda não consegui reproduzir isso. Mas descobri que o usuário que não aparece na fila de revisão havia sido marcado como suspect_user após se cadastrar em dezembro. Naquela época, must_approve_users estava desativado no meu fórum. Então, tomei uma atitude em relação a ele na época. Não tenho certeza se disagreed significa que escolhi manter o usuário. Mas, quando tentei reproduzir agora, a única outra opção era excluir o usuário. Não sei como status = 2 aconteceu.
Quando ativei must_approve_users algumas semanas atrás, o usuário não foi aprovado automaticamente porque havia um reviewable com o user_id como target_id. Isso faz sentido.

Mas ainda não faço ideia de como acabei com um usuário que não aprovei, mas também não excluí quando ele foi 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 'pendente'
      WHEN rs.status = 1 THEN 'concordado'
      WHEN rs.status = 2 THEN 'discordado'
      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 curtida

Ótimo — parece que o mesmo acontece comigo: um usuário (no meu caso, um usuário ativo e vivo até algumas semanas atrás) que, no passado distante, adquiriu o status de usuário suspeito.

Acho que esse usuário provavelmente descobriu-se incapaz de usar o fórum desde que ativei a aprovação de novos usuários.

Participou em 9 de abr. de 2021 | Última postagem em 16 de abr. | Visto em 16 de abr. | Visualizações: 1311 | Nível de confiança: membro

Estatísticas: 78 dias visitados | 4h de tempo de leitura | 3m de tempo de leitura recente | 83 tópicos visualizados

491 postagens lidas | 6 dados | 31 recebidos | 4 tópicos criados | 25 postagens criadas

Ao mergulhar de volta na minha fila de revisão, não vejo nenhum item naquela data, nem nenhum item com esse nome de usuário.

Agora percebo que, no meu caso, tivemos um usuário de spam que assumiu o ID 332, foi sinalizado e excluído. Alguns dias depois, um novo usuário assumiu novamente o ID 332.

Conhecendo o ID do usuário válido afetado, executei esta consulta no Data Explorer:

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