166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| class EmbedController < ApplicationController
 | |
|   include TopicQueryParams
 | |
| 
 | |
|   skip_before_action :check_xhr, :preload_json, :verify_authenticity_token
 | |
| 
 | |
|   before_action :prepare_embeddable, except: [ :info ]
 | |
|   before_action :ensure_api_request, only: [ :info ]
 | |
| 
 | |
|   layout 'embed'
 | |
| 
 | |
|   rescue_from Discourse::InvalidAccess do
 | |
|     if current_user.try(:admin?)
 | |
|       @setup_url = "#{Discourse.base_url}/admin/customize/embedding"
 | |
|       @show_reason = true
 | |
|       @hosts = EmbeddableHost.all
 | |
|     end
 | |
|     render 'embed_error', status: 400
 | |
|   end
 | |
| 
 | |
|   def topics
 | |
|     discourse_expires_in 1.minute
 | |
| 
 | |
|     unless SiteSetting.embed_topics_list?
 | |
|       render 'embed_topics_error', status: 400
 | |
|       return
 | |
|     end
 | |
| 
 | |
|     if @embed_id = params[:discourse_embed_id]
 | |
|       raise Discourse::InvalidParameters.new(:embed_id) unless @embed_id =~ /^de\-[a-zA-Z0-9]+$/
 | |
|     end
 | |
| 
 | |
|     if @embed_class = params[:embed_class]
 | |
|       raise Discourse::InvalidParameters.new(:embed_class) unless @embed_class =~ /^[a-zA-Z0-9\-_]+$/
 | |
|     end
 | |
| 
 | |
|     if params.has_key?(:template) && params[:template] == "complete"
 | |
|       @template = "complete"
 | |
|     else
 | |
|       @template = "basic"
 | |
|     end
 | |
| 
 | |
|     list_options = build_topic_list_options
 | |
| 
 | |
|     if params.has_key?(:per_page)
 | |
|       list_options[:per_page] =
 | |
|         [params[:per_page].to_i, SiteSetting.embed_topic_limit_per_page].min
 | |
|     end
 | |
| 
 | |
|     if params[:allow_create]
 | |
|       @allow_create = true
 | |
|       create_url_params = {}
 | |
|       create_url_params[:category_id] = params[:category] if params[:category].present?
 | |
|       create_url_params[:tags] = params[:tags] if params[:tags].present?
 | |
|       @create_url = "#{Discourse.base_url}/new-topic?#{create_url_params.to_query}"
 | |
|     end
 | |
| 
 | |
|     topic_query = TopicQuery.new(current_user, list_options)
 | |
|     top_period = params[:top_period]
 | |
|     begin
 | |
|       TopTopic.validate_period(top_period)
 | |
|       valid_top_period = true
 | |
|     rescue Discourse::InvalidParameters
 | |
|       valid_top_period = false
 | |
|     end
 | |
| 
 | |
|     @list = if valid_top_period
 | |
|       topic_query.list_top_for(top_period)
 | |
|     else
 | |
|       topic_query.list_latest
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def comments
 | |
|     embed_url = params[:embed_url]
 | |
|     embed_username = params[:discourse_username]
 | |
|     embed_topic_id = params[:topic_id]&.to_i
 | |
| 
 | |
|     unless embed_topic_id || EmbeddableHost.url_allowed?(embed_url)
 | |
|       raise Discourse::InvalidAccess.new('invalid embed host')
 | |
|     end
 | |
| 
 | |
|     topic_id = nil
 | |
|     if embed_url.present?
 | |
|       topic_id = TopicEmbed.topic_id_for_embed(embed_url)
 | |
|     else
 | |
|       topic_id = params[:topic_id].to_i
 | |
|     end
 | |
| 
 | |
|     if topic_id
 | |
|       @topic_view = TopicView.new(topic_id,
 | |
|                                   current_user,
 | |
|                                   limit: SiteSetting.embed_post_limit,
 | |
|                                   only_regular: true,
 | |
|                                   exclude_first: true,
 | |
|                                   exclude_deleted_users: true,
 | |
|                                   exclude_hidden: true)
 | |
|       raise Discourse::NotFound if @topic_view.blank?
 | |
| 
 | |
|       @posts_left = 0
 | |
|       @second_post_url = "#{@topic_view.topic.url}/2"
 | |
|       @reply_count = @topic_view.filtered_posts.count - 1
 | |
|       @reply_count = 0 if @reply_count < 0
 | |
|       @posts_left = @reply_count - SiteSetting.embed_post_limit if @reply_count > SiteSetting.embed_post_limit
 | |
|     elsif embed_url.present?
 | |
|       Jobs.enqueue(:retrieve_topic,
 | |
|                       user_id: current_user.try(:id),
 | |
|                       embed_url: embed_url,
 | |
|                       author_username: embed_username,
 | |
|                       referer: request.env['HTTP_REFERER']
 | |
|                   )
 | |
|       render 'loading'
 | |
|     end
 | |
| 
 | |
|     discourse_expires_in 1.minute
 | |
|   end
 | |
| 
 | |
|   def info
 | |
|     embed_url = params.require(:embed_url)
 | |
|     @topic_embed = TopicEmbed.where(embed_url: embed_url).first
 | |
| 
 | |
|     raise Discourse::NotFound if @topic_embed.nil?
 | |
| 
 | |
|     render_serialized(@topic_embed, TopicEmbedSerializer, root: false)
 | |
|   end
 | |
| 
 | |
|   def count
 | |
|     embed_urls = params[:embed_url]
 | |
|     by_url = {}
 | |
| 
 | |
|     if embed_urls.present?
 | |
|       urls = embed_urls.map { |u| u.sub(/#discourse-comments$/, '').sub(/\/$/, '') }
 | |
|       topic_embeds = TopicEmbed.where(embed_url: urls).includes(:topic).references(:topic)
 | |
| 
 | |
|       topic_embeds.each do |te|
 | |
|         url = te.embed_url
 | |
|         url = "#{url}#discourse-comments" unless params[:embed_url].include?(url)
 | |
|         if te.topic.present?
 | |
|           by_url[url] = I18n.t('embed.replies', count: te.topic.posts_count - 1)
 | |
|         else
 | |
|           by_url[url] = I18n.t('embed.replies', count: 0)
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     render json: { counts: by_url }, callback: params[:callback]
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def prepare_embeddable
 | |
|     response.headers.delete('X-Frame-Options')
 | |
|     @embeddable_css_class = ""
 | |
|     embeddable_host = EmbeddableHost.record_for_url(request.referer)
 | |
|     @embeddable_css_class = " class=\"#{embeddable_host.class_name}\"" if embeddable_host.present? && embeddable_host.class_name.present?
 | |
| 
 | |
|     @data_referer = request.referer
 | |
|     @data_referer = '*' if SiteSetting.embed_any_origin? && @data_referer.blank?
 | |
|   end
 | |
| 
 | |
|   def ensure_api_request
 | |
|     raise Discourse::InvalidAccess.new('api key not set') if !is_api?
 | |
|   end
 | |
| end
 |