diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 055215bfcbf..c51774fe187 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -84,7 +84,7 @@ class TopicsController < ApplicationController raise Discourse::InvalidParameters.new(:title) if title.length < SiteSetting.min_title_similar_length raise Discourse::InvalidParameters.new(:raw) if raw.length < SiteSetting.min_body_similar_length - topics = Topic.similar_to(title, raw) + topics = Topic.similar_to(title, raw, current_user) render_serialized(topics, BasicTopicSerializer) end diff --git a/app/models/topic.rb b/app/models/topic.rb index 25e76157c39..08161471fd5 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -98,16 +98,19 @@ class Topic < ActiveRecord::Base scope :secured, lambda {|guardian| ids = guardian.secure_category_ids if guardian + + # Query conditions condition = if ids.present? ["NOT c.secure or c.id in (:cats)", cats: ids] else ["NOT c.secure"] end - where("category_id IS NULL OR category_id IN ( - SELECT c.id FROM categories c - WHERE #{condition[0]})", condition[1]) - } + + where("category_id IS NULL OR category_id IN ( + SELECT c.id FROM categories c + WHERE #{condition[0]})", condition[1]) + } # Helps us limit how many favorites can be made in a day class FavoriteLimiter < RateLimiter @@ -234,7 +237,7 @@ class Topic < ActiveRecord::Base end # Search for similar topics - def self.similar_to(title, raw) + def self.similar_to(title, raw, user=nil) return [] unless title.present? return [] unless raw.present? @@ -242,6 +245,7 @@ class Topic < ActiveRecord::Base Topic.select(sanitize_sql_array(["topics.*, similarity(topics.title, :title) AS similarity", title: title])) .visible .where(closed: false, archived: false) + .secured(Guardian.new(user)) .listable_topics .limit(SiteSetting.max_similar_results) .order('similarity desc') diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index d78bb3d23f5..ba910a33fc2 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -162,10 +162,19 @@ describe TopicsController do end it "delegates to Topic.similar_to" do - Topic.expects(:similar_to).with(title, raw).returns([Fabricate(:topic)]) + Topic.expects(:similar_to).with(title, raw, nil).returns([Fabricate(:topic)]) xhr :get, :similar_to, title: title, raw: raw end + context "logged in" do + let(:user) { log_in } + + it "passes a user throught if logged in" do + Topic.expects(:similar_to).with(title, raw, user).returns([Fabricate(:topic)]) + xhr :get, :similar_to, title: title, raw: raw + end + end + end diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index 0c7f4ba4c58..007c4a41cfb 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -175,6 +175,26 @@ describe Topic do Topic.similar_to("has evil trout made any topics?", "i am wondering has evil trout made any topics?").should == [topic] end + context "secure categories" do + + let(:user) { Fabricate(:user) } + let(:category) { Fabricate(:category, secure: true) } + + before do + topic.category = category + topic.save + end + + it "doesn't return topics from private categories" do + expect(Topic.similar_to("has evil trout made any topics?", "i am wondering has evil trout made any topics?", user)).to be_blank + end + + it "should return the cat since the user can see it" do + Guardian.any_instance.expects(:secure_category_ids).returns([category.id]) + expect(Topic.similar_to("has evil trout made any topics?", "i am wondering has evil trout made any topics?", user)).to include(topic) + end + end + end end