你说得对。审核队列排序错误的发生是因为在插件被移除后,数据库中仍残留有 Akismet 审核项。我想到两种可能的解决方案:
- 提供一个 Rake 任务,在用户决定永久移除插件之前,从数据库中删除这些记录。
- 为 Reviewable 类应用一个默认作用域,在插件被禁用时自动排除这些记录。
你觉得呢?
你说得对。审核队列排序错误的发生是因为在插件被移除后,数据库中仍残留有 Akismet 审核项。我想到两种可能的解决方案:
你觉得呢?
另外,如果您编辑处于队列中的主题或帖子,图片在编辑器预览中似乎会不可见。
这种情况是发生在帖子等待审核时,还是发生在拒绝之后?正如我之前所说,系统会自动删除被拒绝的待处理帖子的上传内容。
是的,当它们处于审核等待状态时,@Roman,我在编辑器预览中看不到这些图片。
我认为插件卸载的情况很少见,而默认的 scope 机制更可能引入 bug。
如果我们添加一个 rake 任务,并在 README 的“卸载”部分说明执行该任务以移除旧记录,这应该是合理的。就这么办吧!
系统正在发送这些通知,因为队列中存在待处理的项目。您修改的设置是针对队列中帖子的提醒,请将 notify_about_flags_after 设置为 0。
该任务现已可用。您可以通过以下方式从数据库中删除所有与插件相关的记录:
bundle exec rake akismet_uninstall:delete_reviewables
请确保已安装该插件,并阅读了 README 中的卸载部分:
感谢 @Roman——我可以确认,将 notify_about_flags_after 修改为 0 后,通知已停止 ![]()
非常感谢您为此添加了 rake 任务!我会在今天流量低谷时重新安装 Akismet 并运行该 rake 任务,然后在此帖中更新结果。
对此有什么想法吗?@Roman @eviltrout
似乎那些帖子直接进入审核队列的用户可以绕过相当多的关于主题和帖子/回复创建的速率限制。
看似可绕过的速率限制选项:
创建主题速率限制、新用户创建主题速率限制、每日最大主题数、创建帖子速率限制、新用户创建帖子速率限制、唯一帖子间隔分钟数、最大连续回复数。
此外,配合“禁止顶帖”插件还可绕过顶帖限制:Discourse No Bump - #26
直接将主题和帖子发送至审核队列的选项:
“批准帖子数量”(新用户需要其首个主题/帖子获得批准),以及各个分类中的“要求版主批准所有新主题”选项,很可能(我仅测试了新主题选项)还包括“要求版主批准所有新回复”。
是的,这是设计使然。如果您的帖子经过审核并被判定为可接受,无论有何限制,都将会发布。
啊,我明白了。谢谢你的解释。我就分享一下自己的使用经验供参考。
由于没有强制执行限制,新用户(需审核帖子数量)可以无限制或几乎无限制地随意向审核队列中大量提交内容,而受信任的老账户则受到速率限制。除非启用了“批准所有主题或回复”的类别选项,此时受信任的老用户也会不受限制或限制很少。
虽然工作量不小,但批准所有新主题以及新用户创建的首批主题/帖子(如果受到速率限制)还是相对可行的。但在我的情况下,由于用户可以大量刷屏,这几乎变得不可行。
无论如何,非常感谢你澄清这是设计如此,这非常有帮助。我打算调整策略,关闭那些直接将主题或帖子发送到审核队列的选项,将审核队列主要用于标记内容。然后对受速率限制的实时提交内容进行事后审核,这样应该效果不错,对用户来说也会更加高效流畅。
So I went ahead and reinstalled Akismet and ran the rake task. My process was:
cd /var/discourse
./launcher enter app
bundle exec rake akismet_uninstall:delete_reviewables
I received an error unfortunately, tried running it a few times:
rake aborted!
ActiveRecord::NoDatabaseError: FATAL: Peer authentication failed for user "discourse"
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:50:in `rescue in postgresql_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:33:in `postgresql_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:887:in `new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:931:in `checkout_new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:910:in `try_to_checkout_new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:871:in `acquire_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:593:in `checkout'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:437:in `connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:1119:in `retrieve_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_handling.rb:221:in `retrieve_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_handling.rb:189:in `connection'
/var/www/discourse/lib/site_settings/db_provider.rb:61:in `table_exists?'
/var/www/discourse/lib/site_settings/db_provider.rb:16:in `all'
/var/www/discourse/lib/site_settings/defaults_provider.rb:29:in `db_all'
/var/www/discourse/lib/site_setting_extension.rb:287:in `block in refresh!'
/var/www/discourse/lib/site_setting_extension.rb:284:in `synchronize'
/var/www/discourse/lib/site_setting_extension.rb:284:in `refresh!'
/var/www/discourse/lib/site_setting_extension.rb:505:in `block in setup_methods'
/var/www/discourse/config/initializers/004-message_bus.rb:120:in `<main>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `block in load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:666:in `block in load_config_initializer'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:182:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:665:in `load_config_initializer'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:625:in `block (2 levels) in <class:Engine>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:624:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:624:in `block in <class:Engine>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:32:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:32:in `run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:50:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:50:in `tsort_each_child'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:60:in `run_initializers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:363:in `initialize!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/config/environment.rb:7:in `<main>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/zeitwerk-2.3.0/lib/zeitwerk/kernel.rb:23:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:324:in `block in require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:324:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:339:in `require_environment!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:523:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Caused by:
PG::ConnectionBad: FATAL: Peer authentication failed for user "discourse"
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/pg-1.2.3/lib/pg.rb:58:in `initialize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/pg-1.2.3/lib/pg.rb:58:in `new'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/pg-1.2.3/lib/pg.rb:58:in `connect'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:46:in `postgresql_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:887:in `new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:931:in `checkout_new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:910:in `try_to_checkout_new_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:871:in `acquire_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:593:in `checkout'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:437:in `connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:1119:in `retrieve_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_handling.rb:221:in `retrieve_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_handling.rb:189:in `connection'
/var/www/discourse/lib/site_settings/db_provider.rb:61:in `table_exists?'
/var/www/discourse/lib/site_settings/db_provider.rb:16:in `all'
/var/www/discourse/lib/site_settings/defaults_provider.rb:29:in `db_all'
/var/www/discourse/lib/site_setting_extension.rb:287:in `block in refresh!'
/var/www/discourse/lib/site_setting_extension.rb:284:in `synchronize'
/var/www/discourse/lib/site_setting_extension.rb:284:in `refresh!'
/var/www/discourse/lib/site_setting_extension.rb:505:in `block in setup_methods'
/var/www/discourse/config/initializers/004-message_bus.rb:120:in `<main>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `block in load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:666:in `block in load_config_initializer'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:182:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:665:in `load_config_initializer'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:625:in `block (2 levels) in <class:Engine>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:624:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:624:in `block in <class:Engine>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:32:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:32:in `run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:50:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:50:in `tsort_each_child'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/initializable.rb:60:in `run_initializers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:363:in `initialize!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/config/environment.rb:7:in `<main>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/zeitwerk-2.3.0/lib/zeitwerk/kernel.rb:23:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:324:in `block in require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:324:in `require'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:339:in `require_environment!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.3.1/lib/rails/application.rb:523:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => akismet_uninstall:delete_reviewables => environment
(See full trace by running task with --trace)
能否在执行任务前,先运行 su discourse 切换到 discourse 用户?
我最近将站点设置改为“仅限邀请”,现在系统为某个用户账户在审核队列中生成了一条标记为“需要批准”的项目。
奇怪的是,这是一个已有 4 年的账户,拥有多条帖子且信任等级为 TL2,但最近并不活跃(上次发帖是 2 年前)。然而,该账户今天登录后,审核标志就被触发了。
我尚未使用“批准用户”功能,该项目仍停留在审核队列中,但该账户似乎已启用并能正常使用论坛(这符合预期)。
这是否意味着,当启用“仅限邀请”模式时,审核队列会将最近重新激活的账户识别为新账户,并标记为需要审核?
编辑:现在一个非常新的账户(仅在该设置启用前几天创建)也出现了同样的情况。
我认为在切换到仅限邀请模式时,我之前见过这种情况。在某些情况下,Discourse 会认为需要批准该用户,因为他们是通过常规注册获得网站访问权限的。当切换该开关后,他们的记录中并未设置“已批准”标志。
我对此进行了进一步调查,发现这些账户(共四个)唯一的共同点是:它们都在设置 invite_only 之后,通过电子邮件登录路径(通过 forgot_password 或直接通过 email_login)登录过。
是否考虑过为 Akismet 标记的审核主题/帖子添加“暂停”功能?在我们实例中有人提出过这个建议,原因很简单:因为我们使用 SSO(单点登录),删除成员通常收效甚微——成员只需在主要提供商处重新登录其账户,就能立即重新进入论坛继续活动。而暂停功能则能增加他们的难度,迫使他们使用新邮箱在提供商处创建新账户。
我知道这个请求有点奇怪,但我的 moderators 经常问到这个问题。目前,他们只能手动在系统中四处操作以暂停用户,这增加了他们的工作量,但这样做是值得的,因为用户最终不愿意再放弃一个邮箱地址。
我认为这应该是一个下拉按钮,而不是添加大量额外的按钮。