Código / requisitos inconsistentes para marcação de PM

O código para o manuseio de marcação de mensagens pessoais é inconsistente.

Em algumas partes da base de código, estar em pm_tags_allowed_for_groups é suficiente para poder marcar uma mensagem pessoal.

Em outras partes da base de código, é necessário estar tanto em pm_tags_allowed_for_groups quanto em tag_topic_allowed_groups.

Isso é especialmente restritivo quando há a necessidade de os usuários poderem marcar suas próprias mensagens pessoais, enquanto você não quer que eles marquem tópicos públicos (por exemplo, este Private template permissions to override allowed PM tagging groups), ou seja, quando pm_tags_allowed_for_groups não é um subconjunto adequado de tag_topic_allowed_groups.

Análise

Em TagGuardian essas são configurações distintas. Você só precisa estar em pm_tags_allowed_for_groups para poder marcar um 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

O mesmo vale para Guardian.can_tag? As configurações são distintas.

  def can_tag?(topic)
    return false if topic.blank?

    topic.private_message? ? can_tag_pms? : can_tag_topics?
  end

ListController também se contenta apenas com 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?

No entanto, TopicGuardian exige que um usuário esteja em tag_topic_allowed_groups e pm_tags_allowed_for_groups se quiser poder marcar um 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

No lado do cliente, a mesma restrição está em 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)
    );
  }

e TopicController

  @discourseComputed("model.isPrivateMessage")
  canEditTags(isPrivateMessage) {
    return (
      this.site.get("can_tag_topics") &&
      (!isPrivateMessage || this.site.get("can_tag_pms"))
    );
  }

Mas o modal Move to Topic não tem essa restrição:

  get canTagMessages() {
    return this.site.can_tag_pms;
  }

e nem ChatToTopicSelector

@alias("site.can_tag_pms") canTagMessages;

e nem 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",
      });
    }

Resumo

Classe C/S Comportamento
TagGuardian servidor apenas pm_tags_allowed_for_groups
Guardian servidor apenas pm_tags_allowed_for_groups
ListController servidor apenas pm_tags_allowed_for_groups
TopicGuardian servidor ambos pm_tags_allowed_for_groups e tag_topic_allowed_groups
Composer cliente ambos pm_tags_allowed_for_groups e tag_topic_allowed_groups
TopicController cliente ambos pm_tags_allowed_for_groups e tag_topic_allowed_groups
Modal Mover para Tópico cliente apenas pm_tags_allowed_for_groups
ChatToTopicSelector cliente apenas pm_tags_allowed_for_groups

Questões adicionais

Encontrei mais dois impedimentos adicionais:

PostRevisor usa tc.guardian.can_tag_topics? em vez de tc.guardian.can_tag?(tc.topic)

e em DiscourseTagging

tag_topic_by_names faz a coisa certa

  def self.tag_topic_by_names(topic, guardian, tag_names_arg, append: false)
    if guardian.can_tag?(topic)

mas então tags_for_saving não faz


   def self.tags_for_saving(tags_arg, guardian, opts = {})
    return [] unless guardian.can_tag_topics? && tags_arg.present?

Este último é especialmente complicado, pois a função não sabe se está trabalhando em um PM.

6 curtidas