Codice/ requisiti incoerenti per il tag PM

Il codice per la gestione del tagging dei messaggi personali è incoerente.

In alcune parti della codebase, essere in pm_tags_allowed_for_groups è sufficiente per poter taggare un messaggio personale.

In altre parti della codebase, è necessario essere sia in pm_tags_allowed_for_groups che in tag_topic_allowed_groups.

Questo è particolarmente restrittivo quando c’è la necessità che gli utenti possano taggare i propri messaggi personali mentre non si desidera che tagghino argomenti pubblici (ad esempio, questo Private template permissions to override allowed PM tagging groups), cioè quando pm_tags_allowed_for_groups non è un sottoinsieme proprio di tag_topic_allowed_groups.

Analisi

In TagGuardian queste sono impostazioni distinte. È sufficiente essere in pm_tags_allowed_for_groups per poter taggare un 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

Lo stesso vale per Guardian.can_tag? Le impostazioni sono distinte.

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

    topic.private_message? ? can_tag_pms? : can_tag_topics?
  end

Anche ListController si accontenta solo di 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?

Tuttavia, TopicGuardian richiede che un utente sia sia in tag_topic_allowed_groups che in pm_tags_allowed_for_groups se desidera poter taggare un 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

Sul lato client, la stessa restrizione si trova in 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"))
    );
  }

Ma la modale Move to Topic non ha questa restrizione:

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

e nemmeno ChatToTopicSelector

@alias("site.can_tag_pms") canTagMessages;

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

Riepilogo

Classe C/S Comportamento
TagGuardian server solo pm_tags_allowed_for_groups
Guardian server solo pm_tags_allowed_for_groups
ListController server solo pm_tags_allowed_for_groups
TopicGuardian server sia pm_tags_allowed_for_groups che tag_topic_allowed_groups
Composer client sia pm_tags_allowed_for_groups che tag_topic_allowed_groups
TopicController client sia pm_tags_allowed_for_groups che tag_topic_allowed_groups
Modale Move to Topic client solo pm_tags_allowed_for_groups
ChatToTopicSelector client solo pm_tags_allowed_for_groups

Problemi aggiuntivi

Ho trovato altri due impedimenti:

PostRevisor utilizza tc.guardian.can_tag_topics? invece di tc.guardian.can_tag?(tc.topic)

e in DiscourseTagging

tag_topic_by_names fa la cosa giusta

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

ma poi tags_for_saving no


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

Quest’ultimo è particolarmente insidioso poiché la funzione non è consapevole se sta lavorando su un PM.

6 Mi Piace