为安全模式添加服务器端插件禁用功能

我发现,当出现问题且用户使用了第三方自定义内容时,他们往往首先尝试安全模式。这很合理,因为你还不知道问题出在哪里。

然而,安全模式仅禁用 JavaScript。如果存在任何服务器端代码,通常的即时解决方案是在 app.yml 文件中取消注释所有插件。这没问题,但这需要重新构建,并且相对“技术性”。如果你是非技术用户,在 app.yml 中注释掉某些内容可不是件容易上手的事。

我在考虑是否可以通过一个 PR 来实现在安全模式下禁用服务器端插件的可行性。我的想法是在安全模式控制器中加入类似以下的内容:

find_opts = {
  include_official: params["only_official"] != 'true',
  include_unofficial: params["no_plugins"] == "true"
}
      
Discourse.find_plugins(find_opts).each do |plugin|
  if plugin.enabled_site_setting.present?
    SiteSetting.set(plugin.enabled_site_setting, false)
  end
end

是的,用户可以通过进入他们的站点设置并手动关闭插件来达到同样的效果,但我发现用户很少真正这样做。

2 个赞

当前的安全模式仅针对当前页面生效,在新标签页或刷新后即失效。因此,它完全适用于测试。

您的提议将改变其含义,变为永久性地切换设置,从而影响整个网站。这意味着该操作也必须限制为管理员权限。

我理解您的提议,但这将带来行为上的重大变更。

3 个赞

确实。

我认为关键点在于,非技术背景的网站管理员在站点出问题时,往往希望找到一种修复方案使其恢复正常运行。“安全模式”通常被认为能够实现这一目标(无论这种认知是否正确)。或许,一种可行的方式是增加额外的管理员安全模式控制选项。

你可以在 /admin/plugins 路由中添加一个大按钮,以同样的方式自动禁用所有插件,但我不确定这是否能达到相同的效果。也许可以。

我也对这一方案很感兴趣,因为它在当前 Discourse 插件架构中是完全可以实现的。

5 个赞

你觉得怎么样,@sam

通常,导致插件失效的是核心层面的不兼容变更。很多时候,如果包含有问题的插件或引导程序,系统甚至无法正常启动。

若要实现“关闭所有插件”的功能,必须某种方式重启应用程序才能生效。

我认为可以考虑对 Docker 管理器插件进行调整,允许用户通过将插件文件移入或移出插件目录来轻松禁用或启用插件,并重启应用程序,这样可以让调试过程更加高效。

4 个赞

我认为那也会是个不错的方案。

不过,我发现有相当数量的错误源于封装在服务器端插件 API 中的代码,而这一机制应该能够处理此类问题(我认为是这样?)。

目前,“安全模式”(或类似机制)也并非解决崩溃问题的完整方案。增加自动禁用插件的功能,将使该方案稍显完善,减少需要完全重启或修改配置的情况,也更符合非技术背景站点管理员的认知方式。

我希望能采取一些循序渐进且相对简单的步骤。也许 Docker 管理器的改动在技术层面上同样 straightforward。

是的,如果未来能够实现,在管理员设置中提供一个无需重建容器即可生效的“禁用所有插件”布尔开关,将非常有益。不过,我并非 Discourse 开发者(仅有一年 node.jsvuejs 应用开发经验),凭直觉判断,这并非易事,且会对架构造成重大改动。

我们之前的 LAMP 论坛具备这一功能,我们曾多次利用该布尔开关快速定位由插件引起的错误。然而,由于软件架构差异巨大,直接对比并无太大意义。

我个人相信 Discourse 团队会想出解决方案。许多用户依赖插件,未来难免会遇到更多棘手问题。

感谢您对此问题的关注。

1 个赞

对我来说,一个关键因素是这一功能将完全面向自托管用户。我并不想在核心代码中为插件引入安全模式,这显然不是我们会使用的方案,跨 5 个集群协调重启非常困难。

Docker 管理器是合适的解决方案,它已经支持应用重启,而这是您的提案生效所必需的。此外,它可以在不修改 Discourse 核心的情况下完成所有必要操作。

5 个赞

明白了,我会把注意力集中在那里。

4 个赞