discourse/lib/pretty_text/helpers.rb
Dan Ungureanu cf02c518b9
DEV: Merge category and tag hashtags code paths (#10216)
Category and tag hashtags used to be handled differently even though
most of the code was very similar. This design was the root cause of
multiple issues related to hashtags.

This commit reduces the number of requests (just one and debounced
better), removes the use of CSS classes which marked resolved hashtags,
simplifies a lot of the code as there is a single source of truth and
previous race condition fixes are now useless.

It also includes a very minor security fix which let unauthorized users
to guess hidden tags.
2020-07-13 19:13:17 +03:00

125 lines
3.4 KiB
Ruby

# frozen_string_literal: true
module PrettyText
module Helpers
extend self
TAG_HASHTAG_POSTFIX = "::tag"
# functions here are available to v8
def t(key, opts)
key = "js." + key
unless opts
I18n.t(key)
else
str = I18n.t(key, Hash[opts.entries].symbolize_keys).dup
opts.each { |k, v| str.gsub!("{{#{k.to_s}}}", v.to_s) }
str
end
end
def avatar_template(username)
return "" unless username
user = User.find_by(username_lower: username.downcase)
return "" unless user.present?
# TODO: Add support for ES6 and call `avatar-template` directly
UrlHelper.schemaless(UrlHelper.absolute(user.avatar_template))
end
def lookup_primary_user_group(username)
return "" unless username
user = User.find_by(username_lower: username.downcase)
return "" unless user.present?
user.primary_group.try(:name) || ""
end
# Overwrite this in a plugin to change how markdown can format
# usernames on the server side
def format_username(username)
username
end
def category_hashtag_lookup(category_slug)
if category = Category.query_from_hashtag_slug(category_slug)
[category.url, category_slug]
else
nil
end
end
def lookup_upload_urls(urls)
map = {}
result = {}
urls.each do |url|
sha1 = Upload.sha1_from_short_url(url)
map[url] = sha1 if sha1
end
if map.length > 0
reverse_map = {}
map.each do |key, value|
reverse_map[value] ||= []
reverse_map[value] << key
end
Upload.where(sha1: map.values).pluck(:sha1, :url, :extension, :original_filename, :secure).each do |row|
sha1, url, extension, original_filename, secure = row
if short_urls = reverse_map[sha1]
secure_media = SiteSetting.secure_media? && secure
short_urls.each do |short_url|
result[short_url] = {
url: secure_media ? Upload.secure_media_url_from_upload_url(url) : Discourse.store.cdn_url(url),
short_path: Upload.short_path(sha1: sha1, extension: extension),
base62_sha1: Upload.base62_sha1(sha1)
}
end
end
end
end
result
end
def get_topic_info(topic_id)
return unless topic_id.is_a?(Integer)
# TODO this only handles public topics, secured one do not get this
topic = Topic.find_by(id: topic_id)
if topic && Guardian.new.can_see?(topic)
{
title: Rack::Utils.escape_html(topic.title),
href: topic.url
}
elsif topic
{
title: I18n.t("on_another_topic"),
href: Discourse.base_url + topic.slugless_url
}
end
end
def category_tag_hashtag_lookup(text)
is_tag = text =~ /#{TAG_HASHTAG_POSTFIX}$/
if !is_tag && category = Category.query_from_hashtag_slug(text)
[category.url, text]
elsif (!is_tag && tag = Tag.find_by(name: text)) ||
(is_tag && tag = Tag.find_by(name: text.gsub!(TAG_HASHTAG_POSTFIX, '')))
["#{Discourse.base_url}/tag/#{tag.name}", text]
else
nil
end
end
def get_current_user(user_id)
return unless user_id.is_a?(Integer)
{ staff: User.where(id: user_id).where("moderator OR admin").exists? }
end
end
end