为匿名和登录用户设置基于组的细粒度权限

在我们的代码库中,一直存在一个历史上令人困惑的伪组 @everyone,它可用于:

  • 类型为 group_list 的站点设置
  • 分类权限
  • 标签组

在某些情况下,人们将 @everyone 理解为“所有匿名用户和所有登录用户”,而另一些人则将其理解为“仅所有登录用户”。实际上,对于大多数站点设置而言,它仅表示“所有登录用户”。

此外,@everyone 组还可用于某些站点设置,而这些设置显然不应允许“所有匿名用户和登录用户”访问相关功能,例如 pm_tags_allowed_for_groups,这进一步加剧了混乱。

从功能标记和开发者体验的角度来看,这也存在混淆,因为对于某些即将推出的变更或其他设置,我们可能确实希望为“所有匿名用户和登录用户”启用它们。

解决方案

我们将引入两个独立的自动伪组:

  • anonymous_users (ID 4) - 代表没有账户、访问您站点的匿名用户
  • logged_in_users (ID 5) - 代表所有已登录您站点的用户,其效果类似于 trust_level_0 自动组,但更加具体

这些组已经引入,但仅在您的站点启用了即将推出的变更 granular_anonymous_and_logged_in_groups_permissions 后才会生效。

当启用该即将推出的变更时,任何将 everyone 选为组的设置都会自动转换为 logged_in_users ID,因此在切换该变更时,站点设置表中的数据不会发生变化。当该变更成为永久性变更后,我们将对所有组设置进行数据迁移以完成此更改。

此外,对于某些站点设置(例如 personal_message_enabled_groups),我们已经将 anonymous_users 标记为 disallowed_group,因为这些设置显然不适用于匿名用户。

与现有组名称的冲突将通过自动重命名现有组并更新帖子中的组提及来处理。

关于标签和分类权限?

这些权限将保持不变,因为它们的“所有人”概念在几个方面有所不同,且不依赖于底层的自动组。

9 个赞

等等……这是怎么回事😳 这是否意味着,当该功能启用后,所有当前对公众(所有人)开放的类别都将变为需要登录才能访问的封闭类别?

[quote=“martin, post:1, topic:402273”]
任何将 everyone 选为指定组的设置,都会自动转换为 logged_in_users ID。[/quote]

不,因为:

这仅影响当前允许你选择“所有人”的群组列表类型站点设置,如下所示:

1 个赞

有人能帮我理解我需要如何调整我的主题组件吗?

我尝试以 copy-post 组件为例,因为我记得它也使用了一个组设置来授予对该功能的访问权限。而且当时有一个 问题,因为“所有人”(everyone)这个伪组需要单独检查,就像在我的组件中一样,因为仅仅比较用户所属组的 ID 没有帮助——这些 ID 需要单独检查。因此,我预期那里最近会有变更,因为据我理解,新组也是伪组,其 ID 也需要单独检查。我是否遗漏了什么,导致这里不需要这样做?

我的 favorite filters 组件有两个组设置:一个允许组保存自己的过滤器,另一个提供标准过滤器。
默认情况下,只有 trust_level_0 组的成员可以使用自定义过滤器,因为只有注册用户才能在自定义用户字段中存储数据。因此,在这里,如果我不允许选择 anonymous_users,将是合理的。在主题组件中该如何实现这一点?是否已有相关示例?

默认过滤器的默认设置是“所有人”(everyone),因为我认为即使未注册用户也能查看和使用默认过滤器是有帮助的。问题是,尽管我明确选择了“所有人”,它却变成了“已登录用户”(logged_in_users)。我是否需要为此创建一个自定义迁移,以便当前使用“所有人”的管理员在未来仍能为未注册用户保留过滤器?这个迁移需要在什么时候执行?还是说,在你运行迁移后,每个管理员都需要单独更改这个设置?

我所担心的这些是否实际上是不必要的?如果需要调整,考虑到可能受影响的社区维护组件数量,不到四周的时间似乎相当短。
除了“copy-post”,我还查看了 unanswered filter 组件,但也没有在那里发现任何变更。感觉我似乎忽略了某些重要的东西。毕竟,该变更已默认启用近一周了。因此我假设,如果需要调整,官方组件应该已经更新了。

1 个赞

3 篇帖子已合并到现有主题:现代化 Foundation 主题

查看这些组件,currentUser?.groups 无论如何都不可靠,因为它仅包含用户的可见群组,而可能影响权限的所属群组可能并未在此处序列化:

我们在核心插件中通过在当前用户序列化器中执行类似以下操作来解决这个问题:

但显然,主题组件和主题及其设置无法使用此方法。

嗯,我不太确定,需要再想想。如果你确实是指 everyone,那么它需要同时更改为 logged_in_usersanonymous_users。正如原帖所述,这是 everyone 的主要问题——有些人认为它仅指已登录用户,而另一些人则认为它指已登录用户加匿名用户,这非常依赖于具体情境。

我选择了“仅已登录用户”这一解释,因为从安全角度来看这更稳妥。

不,我只是没考虑到主题组件和主题及其设置会如何受到此更改的影响,我当时主要关注的是站点设置。像这类问题尤其难以发现,因为它甚至没有使用 AUTO_GROUPS 常量:

image

总之,我会针对这些问题想出一些解决方案,在找到解决方法之前,我不会将此更改推进到稳定版。

3 个赞

快速更新一下,我有一个处理这个想法的方案,我们正在进行一些内部讨论。希望不会花太长时间 :crossed_fingers:

1 个赞

这说的就是我 :upside_down_face:;因此,为了创建一个仅限注册用户访问的类别,我将其访问权限设置为仅限 TL0,依靠 TL0 自动用户组来区分已登录用户和访客。

我想知道是否有一张表格,用于区分该术语在不同语境下的含义。这些差异既令人困惑又让人不安——因为当人们最初选择此设置时,他们可能并不知道其实际含义,因此他们会希望检查相关设置。目前,我只能逐一检查设置组的位置,并通过查看启用“Granular group”功能后它被更改为什么来确认它过去的含义——这感觉像是在黑暗中摸索。

2 个赞

这个想法不错……我或许能利用 AI 变通一下,去查找所有使用基于组的设置的地方,并输出 anonymous 是否有可能访问这些内容。

有很多设置已经不允许选择 anonymous_users 组,所以这些可能是一个不错的起点……我会在此处汇报调查结果。

我现在正在为此编写 PR:

随后很快会有跟进的 PR 和文档更改。

3 个赞

@Noble_Fish ,这是基于 AI 生成的按组设置列表,包含每个设置的用途,以及匿名用户/已登录用户如何受该设置影响。请注意,虽然我有相当把握认为这是正确的,但就像所有 AI 生成的内容一样,最好还是你自己核实一下事实。

我认为最有趣的列是“everyone 在更改前是否也包含 anonymous_users?”,如果这里是 Yes,那就意味着在应用即将进行的更改之前,everyone 指的是已登录用户和匿名用户。

如你所见,其中只有少数几个,因此管理员只需要在站点设置中明确将 anonymous_users 添加到这些设置中:

  • hidden_post_visible_groups - 我实际上需要修改这一项以允许 anonymous_users,当前的代码对于即将进行的更改来说并不完全正确。
  • lazy_load_categories_groups - 我也需要修复这一项,它执行了一个多余的 everyone 检查,而 user.in_any_groups? 内部已经完成了这个检查。
  • styleguide_allowed_groups - 这一项目前可以正常工作,但我会稍微调整一下。

当即将进行的更改变为永久时,将仅使用 logged_in_usersanonymous_users 组,而 everyone 将被删除。


设置项 描述 logged_in_users 是否适用? anonymous_users 是否适用? everyone 在更改前是否也包含 anonymous_users 代码查找结果
whispers_allowed_groups 允许指定组的成员在主题内进行私密通信。 不允许 everyonelogged_in_usersanonymous_users;运行时还期望具体的组/成员资格。
hidden_post_visible_groups 允许这些组的成员查看隐藏帖子。工作人员用户始终可以查看隐藏帖子。 在拒绝匿名用户之前检查 everyone;否则使用 in_any_groups?
about_page_hidden_groups 不在 /about 页面上显示特定组的成员。 使用 group_users;伪组没有成员行。
about_page_extra_groups 在关于页面上版主下方显示的组。 加载具体组及其成员以进行显示。
anonymous_posting_allowed_groups 允许启用匿名发帖的组。 通过 in_any_groups? 进行已登录用户门控;不允许 anonymous_users
personal_message_enabled_groups 允许这些组中的用户创建个人消息。 通过 in_any_groups? 进行已登录用户门控;不允许 anonymous_users
shared_drafts_allowed_groups 允许这些组中的用户查看和编辑共享草稿。 Guardian/用户门控;不允许 anonymous_users
here_mention_allowed_groups 允许提及 @here 的组。 需要已认证用户;不允许 anonymous_users
approve_unless_allowed_groups 不属于这些组的用户发布的帖子必须经过审核。 通过 in_any_groups? 进行用户门控;不允许 anonymous_users
approve_new_topics_unless_allowed_groups 不属于这些组的用户创建的新主题必须经过审核。 通过 in_any_groups? 进行用户门控;不允许 anonymous_users
skip_review_media_groups 这些组之外的用户发布的包含嵌入媒体的帖子将发送进行审核。 通过 in_any_groups? 进行用户门控;不允许 anonymous_users
content_localization_allowed_groups 允许更新本地化内容的组。 Guardian/用户门控;不允许 anonymous_users
email_in_allowed_groups 允许通过电子邮件发布新主题的组。 电子邮件发送者用户门控;不允许 anonymous_users
view_raw_email_allowed_groups 可以查看原始传入电子邮件内容的组。 Guardian 用户门控;不允许 anonymous_users
uploaded_avatars_allowed_groups 指定允许上传自定义头像的组。 当前/目标用户门控;不允许 anonymous_users
create_topic_allowed_groups 允许创建新主题的组。 需要用户并使用 in_any_groups?;不允许 anonymous_users
topic_timers_allowed_groups 允许设置主题计时器的组。 Guardian 用户门控;不允许 anonymous_users
edit_wiki_post_allowed_groups 允许编辑标记为 wiki 的帖子的组。 Guardian 用户门控;不允许 anonymous_users
edit_post_allowed_groups 允许编辑帖子的组。 Guardian 用户门控;不允许 anonymous_users
self_wiki_allowed_groups 允许这些组中的用户将自己的帖子设为 wiki。 Guardian 用户门控;不允许 anonymous_users
send_email_messages_allowed_groups 允许通过电子邮件发送个人消息的组。 Guardian 用户门控;不允许 anonymous_users
flag_post_allowed_groups 允许标记帖子的组。 Guardian 用户门控;不允许 anonymous_users
post_links_allowed_groups 允许在帖子中包含链接的组。 需要已认证用户;不允许 anonymous_users
embedded_media_post_allowed_groups 这些组中的用户允许在帖子中嵌入媒体项目。 操作用户门控;不允许 anonymous_users
profile_background_allowed_groups 允许上传个人资料背景的组。 用户门控;不允许 anonymous_users
user_card_background_allowed_groups 允许上传用户卡片背景的组。 用户门控;不允许 anonymous_users
invite_allowed_groups 允许邀请用户的组。 Guardian 用户门控;不允许 anonymous_users
ignore_allowed_groups 允许忽略其他用户的组。 Guardian 用户门控;不允许 anonymous_users
delete_all_posts_and_topics_allowed_groups 允许删除其他用户创建的帖子和主题并查看已删除内容的组。 Guardian/当前用户门控;不允许 anonymous_users
edit_all_topic_groups 允许该组中的用户编辑其他用户的主题标题、标签和类别。 原始分割后使用 in_any_groups?;不允许 anonymous_users
edit_all_post_groups 允许该组中的用户编辑其他用户的帖子。 通过 in_any_groups? 进行用户门控;不允许 anonymous_users
change_post_ownership_allowed_groups 允许这些组中的用户更改帖子所有权。 当前用户门控;不允许 anonymous_users
cross_origin_opener_unsafe_none_groups 隐藏的 COOP 覆盖组;匹配的用户将获得 Cross-Origin-Opener-Policy: unsafe-none 需要 current_user.present?;匿名选择在运行时没有影响。
user_api_key_allowed_groups 生成用户 API 密钥所需的组成员资格。 当前用户门控;不允许 anonymous_users
create_tag_allowed_groups 允许创建标签的组。 Guardian 用户门控;不允许 anonymous_users
edit_tags_allowed_groups 允许编辑标签、标签描述和标签同义词的组。 Guardian 用户门控;不允许 anonymous_users
tag_topic_allowed_groups 允许为主题添加标签的组。 Guardian 用户门控;不允许 anonymous_users
pm_tags_allowed_for_groups 允许包含的组成员标记任何个人消息。 Guardian 用户门控;不允许 anonymous_users
lazy_load_categories_groups 仅为这些组的用户懒加载类别信息。 显式的 everyone 检查加上 guardian in_any_groups?anonymous_users 具有实际意义。
chat_allowed_groups 这些组中的用户可以聊天,但匿名用户只有在添加到该设置时才能查看聊天。 已登录聊天使用 in_any_groups?;匿名公共聊天显式检查 anonymous_users
direct_message_enabled_groups 允许这些组中的用户创建用户间个人聊天。 已登录聊天 guardian 门控;没有有意义的匿名 DM 路径。
chat_pinning_messages_allowed_groups 这些组中的用户允许固定聊天消息。 需要聊天访问权限/当前用户;没有匿名固定路径。
chat_message_flag_allowed_groups 这些组中的用户允许标记聊天消息。 用户门控;匿名路径被周围的聊天权限阻止。
no_ads_for_groups 不向这些组中的用户显示广告。 仅添加到 current_user 序列化器;没有匿名当前用户负载。
adsense_exclude_groups 不会向这些组的成员显示广告。 通过 in_any_groups? 进行当前用户广告标志;没有匿名当前用户负载。
dfp_exclude_groups 不会向这些组的成员显示广告。 通过 in_any_groups? 进行当前用户广告标志。
amazon_exclude_groups 不会向这些组的成员显示广告。 通过 in_any_groups? 进行当前用户广告标志。
carbonads_exclude_groups 不会向这些组的成员显示广告。 通过 in_any_groups? 进行当前用户广告标志。
adbutler_exclude_groups 不会向这些组的成员显示广告。 通过 in_any_groups? 进行当前用户广告标志。
composer_ai_helper_allowed_groups 这些组中的用户将在编辑器中看到 AI 助手按钮。 通过 in_any_groups? 进行已登录 AI 助手门控。
post_ai_helper_allowed_groups 允许访问帖子中 AI 助手功能的用户组。 通过 in_any_groups? 进行已登录 AI 助手门控。
ai_pm_summarization_allowed_groups 允许在个人消息中创建和查看摘要的组。 使用原始 user.group_ids,因此伪组不匹配。
ai_bot_debugging_allowed_groups 允许这些组查看显示原始 AI 请求和响应的调试按钮。 对匿名用户显式返回 false,然后使用 in_any_groups?
ai_bot_allowed_groups 当 GPT Bot 有权访问个人消息时,它将回复这些组的成员。 主要门控使用 in_any_groups?;一个游乐场路径使用原始 group_ids
ai_bot_public_sharing_allowed_groups 允许这些组通过唯一链接与公众共享 AI 个人消息。 对匿名用户显式返回 false,然后使用 in_any_groups?
assign_allowed_on_groups 这些组中的用户允许分配主题。 使用原始 user.group_ids/GroupUser;伪组没有行。
discourse_post_event_allowed_on_groups 允许创建事件的组。 原始 groups.where(id: ...)everyone 是特殊处理的,但 logged_in_users 不是。
discourse_kanban_manage_board_allowed_groups 允许创建和配置看板板的组。 Guardian 使用 in_any_groups?,但写控制器需要登录。
create_policy_allowed_groups 向帖子添加策略所需的组成员资格。 通过 in_any_groups? 进行帖子/用户门控。
flag_posts_voting_comments_allowed_groups 允许标记帖子投票评论的组。 通过 in_any_groups? 进行用户门控。
allow_solved_in_groups 允许在这些组的组消息中标记解决方案。 无用户门控 无用户门控 无用户门控 匹配 PM topic.allowed_groups,而不是当前用户成员资格。
accept_all_solutions_allowed_groups 允许在任何主题上接受解决方案的组。 通过 in_any_groups? 进行已认证/当前用户门控。
discourse_templates_groups_allowed_private_templates 允许使用私有模板的组。 原始 GroupUser.exists?;仅 everyone 是特殊处理的。
poll_create_allowed_groups 允许创建投票的组。 通过 in_any_groups? 进行操作/当前用户门控。
styleguide_allowed_groups 将样式的可见性限制为所提供组的成员。 控制器显式处理 anonymous_users;在更改之前也允许通过 everyone 进行匿名访问。
2 个赞

将这些调整拆分到一个新的 PR 中:

2 个赞

@moin 这个 PR DEV: Add resolve_group_membership functionality to theme settings - Pull Request #41360 - discourse/discourse - GitHub 已经合并,我正在 DEV: Docs for theme setting resolve_group_membership - Pull Request #41537 - discourse/discourse - GitHub 中添加文档。我通过 DEV: Use resolve_group_membership core theme functionality - Pull Request #37 - discourse/discourse-copy-post - GitHub 修复了 discourse-copy-post,现在我正在检查我们的其他官方插件,看看是否有其他插件需要相同的处理(例如,你已经指出了 GitHub - discourse/discourse-unanswered-filter · GitHub

对于你自己的 Filter Favorites ,你可以参考我做的 copy-post 示例,但基本上你需要在 default_favorite_filters_groupscustom_favorite_filters_allowed_groups 中添加 resolve_group_membership: true,然后它们将根据用户的组成员身份在 settings 中作为布尔值可用,分别为 settings.user_in_default_favorite_filters_groupssettings.user_in_custom_favorite_filters_allowed_groups,你现在不再需要在前端手动检查用户组 ID。

我会将你的主题组件中 default_favorite_filters_groups 的默认值更改为 4|5,即已登录和匿名用户,而不是即将废弃的 0 (everyone)

我会记下在移除 everyone 组时对主题设置运行数据库迁移,我也需要对站点设置执行一次迁移,这将在即将到来的更改在接下来几周内变为永久时发生(具体取决于是否会出现其他问题,以及我修复其他需要添加 resolve_group_membership 的主题/组件的速度)。

目前还没有像站点设置那样的方法来实现这一点……我认为现在没有必要添加,你只需在设置描述中提及这一点,并无论如何在前端使用 currentUser 进行防护即可。也许未来如果有更多需求,我会添加这个功能。

3 个赞

这是否也适用于对象设置中的 groups 类型?

不,它需要吗?我之前没注意到这一点,不知道它是否用于权限管理。

我认为它例如在 Discourse Group Sidebar Menus 中被使用,以便管理员配置哪些群组可以查看每个侧边栏部分,并且在 Notification Banners 中用于配置每个横幅的可见性。

我原以为你也会在 adds 组件 中使用它。但似乎它依赖的是群组名称的字符串。

我倾向于使用群组类型设置,因为它们帮助管理员通过下拉菜单轻松输入群组,同时它们依赖的是群组 ID,相比名称更不容易变更。而且我认为,如果对象设置中的群组列表与列表类型的工作方式不一致,会造成混淆。

对我来说,写下 "everyone" 也会导致 "trust_level_0",因为这对访客不起作用 与新版不同,新版的下拉菜单明确提供了 "anonymous_users" 选项——即使我说明它不起作用。如果仅在描述中说明就足够了,你也可以对站点设置做同样的处理。对于同时使用这两种设置的管理员来说,很难理解为什么在某些地方不起作用的群组被隐藏了,而在其他地方却没有——这并非因为组件开发者不在意,而是因为在那个位置目前还无法实现。

2 个赞

好的,感谢找到示例,需要将此更改整合到具有群组类型的主题设置对象中。例如,这个来自群组侧边栏菜单的,我认为我会让它以相同的方式工作,这样你在配置中会有:

groups:
  type: groups
  required: true
  resolve_group_memberships: true
  validations:
    max: 20

然后在客户端,groups 将变为 user_in_groups 作为布尔值。

disallowed_groups 功能实际上可能并不难……再次参考上面的内容,你会得到这个以去除 anonymous_users

groups:
  type: groups
  required: true
  resolve_group_memberships: true
  disallowed_groups: "4"
  validations:
    max: 20

而对于常规群组类型的主题设置:

copy_button_allowed_groups:
  type: list
  list_type: group
  default: "11" # trust_level_1
  disallowed_groups: "4" # anonymous_users
  description: "选择允许使用复制按钮的群组。"
  resolve_group_membership: true

将看看是否添加此功能。