mirror of
https://github.com/discourse/discourse.git
synced 2024-11-28 05:33:38 +08:00
b2acc416e7
* FIX: Use Category.secured(guardian) for hashtag datasource Follow up to comments in #19219, changing the category hashtag datasource to use Category.secured(guardian) instead of Site.new(guardian).categories here since the latter does more work for not much benefit, and the query time is the same. Also eliminates some Hash -> Model back and forth busywork. Add some more specs too. * FIX: Server-side hashtag lookup cooking user loading When we were using the PrettyText.options.currentUser and parsing back and forth with JSON for the hashtag lookups server-side, we had a bug where the user's secure categories were not loaded since we never actually loaded a User model from the database, only parsed it from JSON. This commit fixes the issue by instead using the PretyText.options.userId and looking up the user directly from the database when calling hashtag_lookup via the PrettyText::Helpers code when cooking server-side. Added the missing spec to check for this as well.
142 lines
4.0 KiB
Ruby
142 lines
4.0 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 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_uploads = SiteSetting.secure_uploads? && secure
|
|
|
|
short_urls.each do |short_url|
|
|
result[short_url] = {
|
|
url: secure_uploads ? Upload.secure_uploads_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
|
|
|
|
# TODO (martin) Remove this when everything is using hashtag_lookup
|
|
# after enable_experimental_hashtag_autocomplete is default.
|
|
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, '')))
|
|
[tag.url, text]
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
def hashtag_lookup(slug, cooking_user_id, types_in_priority_order)
|
|
# This is _somewhat_ expected since we need to be able to cook posts
|
|
# etc. without a user sometimes, but it is still an edge case.
|
|
if cooking_user_id.blank?
|
|
cooking_user = Discourse.system_user
|
|
else
|
|
cooking_user = User.find(cooking_user_id)
|
|
end
|
|
|
|
result = HashtagAutocompleteService.new(
|
|
Guardian.new(cooking_user)
|
|
).lookup([slug], types_in_priority_order)
|
|
|
|
found_hashtag = nil
|
|
types_in_priority_order.each do |type|
|
|
if result[type.to_sym].any?
|
|
found_hashtag = result[type.to_sym].first.to_h
|
|
break
|
|
end
|
|
end
|
|
found_hashtag
|
|
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
|