PM 标签的不一致代码/需求

处理个人消息标签的代码不一致。

在代码库的某些部分,位于 pm_tags_allowed_for_groups 中就足以标记个人消息。

而在代码库的其他部分,则需要同时位于 pm_tags_allowed_for_groupstag_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_groupspm_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)
    );
  }

TopicController

  @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。

6 个赞