Код обработки тегов для личных сообщений непоследователен.
В некоторых частях кодовой базы достаточно быть в группе 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.
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, если он хочет иметь возможность добавить тег к личному сообщению.
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",
});
}
Итог
| Класс | Сторона | Поведение |
|---|---|---|
| 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?
Последняя проблема особенно неприятна, так как функция не знает, работает ли она с личным сообщением.