处理个人消息标签的代码不一致。
在代码库的某些部分,位于 pm_tags_allowed_for_groups 中就足以标记个人消息。
而在代码库的其他部分,则需要同时位于 pm_tags_allowed_for_groups 和 tag_topic_allowed_groups 中。
当用户需要能够标记自己的个人消息,但又不希望他们标记公开主题时(例如:Private template permissions to override allowed PM tagging groups ),这种情况会变得尤其严格,即当 pm_tags_allowed_for_groups 不是 tag_topic_allowed_groups 的真子集时。
分析
在 TagGuardian 中,这些是独立的设置。您只需要位于 pm_tags_allowed_for_groups 中即可标记 PM。
def can_tag_topics?
SiteSetting.tagging_enabled && @user.in_any_groups?(SiteSetting.tag_topic_allowed_groups_map)
end
def can_tag_pms?
return false if !SiteSetting.tagging_enabled
return false if @user.blank?
return true if @user == Discourse.system_user
group_ids = SiteSetting.pm_tags_allowed_for_groups_map
group_ids.include?(Group::AUTO_GROUPS[:everyone]) ||
@user.group_users.exists?(group_id: group_ids)
end
Guardian.can_tag? 也是如此。设置是独立的。
def can_tag?(topic)
return false if topic.blank?
topic.private_message? ? can_tag_pms? : can_tag_topics?
end
ListController 也只满足于 can_tag_pms?
when :private_messages_tag
raise Discourse::NotFound if target_user.id != current_user.id
raise Discourse::NotFound if !guardian.can_tag_pms?
然而,TopicGuardian 要求用户同时位于 tag_topic_allowed_groups 和 pm_tags_allowed_for_groups 中,才能标记 PM。
def can_edit_tags?(topic)
return false unless can_tag_topics?
return false if topic.private_message? && !can_tag_pms?
return true if can_edit_topic?(topic)
if topic&.first_post&.wiki &&
@user.in_any_groups?(SiteSetting.edit_wiki_post_allowed_groups_map)
return can_create_post?(topic)
end
false
end
客户端,相同的限制存在于 Composer
@discourseComputed("model.canEditTitle", "model.creatingPrivateMessage")
canEditTags(canEditTitle, creatingPrivateMessage) {
const isPrivateMessage =
creatingPrivateMessage || this.get("model.topic.isPrivateMessage");
return (
canEditTitle &&
this.site.can_tag_topics &&
(!isPrivateMessage || this.site.can_tag_pms)
);
}
@discourseComputed("model.isPrivateMessage")
canEditTags(isPrivateMessage) {
return (
this.site.get("can_tag_topics") &&
(!isPrivateMessage || this.site.get("can_tag_pms"))
);
}
但是 Move to Topic 模态框没有此限制:
get canTagMessages() {
return this.site.can_tag_pms;
}
ChatToTopicSelector 也没有:
@alias("site.can_tag_pms") canTagMessages;
UserPrivateMessagesController 也没有:
@readOnly("site.can_tag_pms") pmTaggingEnabled;
if (this.pmTaggingEnabled) {
content.push({
id: this.router.urlFor("userPrivateMessages.tags", usernameLower),
name: i18n("user.messages.tags"),
icon: "tags",
});
}
摘要
| 类 | C/S | 行为 |
|---|---|---|
| TagGuardian | 服务器端 | 仅 pm_tags_allowed_for_groups |
| Guardian | 服务器端 | 仅 pm_tags_allowed_for_groups |
| ListController | 服务器端 | 仅 pm_tags_allowed_for_groups |
| TopicGuardian | 服务器端 | pm_tags_allowed_for_groups 和 tag_topic_allowed_groups 都需要 |
| Composer | 客户端 | pm_tags_allowed_for_groups 和 tag_topic_allowed_groups 都需要 |
| TopicController | 客户端 | pm_tags_allowed_for_groups 和 tag_topic_allowed_groups 都需要 |
| Move to Topic 模态框 | 客户端 | 仅 pm_tags_allowed_for_groups |
| ChatToTopicSelector | 客户端 | 仅 pm_tags_allowed_for_groups |
额外问题
我发现了另外两个额外的障碍:
PostRevisor 使用 tc.guardian.can_tag_topics? 而不是 tc.guardian.can_tag?(tc.topic)
以及在 DiscourseTagging 中
tag_topic_by_names 做的事情是正确的
def self.tag_topic_by_names(topic, guardian, tag_names_arg, append: false)
if guardian.can_tag?(topic)
但 tags_for_saving 则不是
def self.tags_for_saving(tags_arg, guardian, opts = {})
return [] unless guardian.can_tag_topics? && tags_arg.present?
最后一个尤其糟糕,因为该函数不知道它是在处理 PM。