diff --git a/app/assets/javascripts/discourse/controllers/discovery_sortable_controller.js b/app/assets/javascripts/discourse/controllers/discovery_sortable_controller.js index f37d509456b..1a7ffaeaddc 100644 --- a/app/assets/javascripts/discourse/controllers/discovery_sortable_controller.js +++ b/app/assets/javascripts/discourse/controllers/discovery_sortable_controller.js @@ -1,6 +1,6 @@ Discourse.DiscoverySortableController = Discourse.Controller.extend({ needs: ['discovery/topics'], - queryParams: ['order', 'ascending', 'status'], + queryParams: ['order', 'ascending', 'status', 'state', 'search'], order: Em.computed.alias('controllers.discovery/topics.order'), ascending: Em.computed.alias('controllers.discovery/topics.ascending'), status: Em.computed.alias('controllers.discovery/topics.status') diff --git a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 index c519b6c9581..267a5738df4 100644 --- a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 +++ b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 @@ -4,7 +4,9 @@ export default function(filter) { queryParams: { sort: { replace: true }, ascending: { replace: true }, - status: { replace: true } + status: { replace: true }, + state: { replace: true }, + search: { replace: true } }, beforeModel: function() { @@ -19,10 +21,11 @@ export default function(filter) { Discourse.ScreenTrack.current().stop(); var findOpts = {}; - if (params && params.order) { findOpts.order = params.order; } - if (params && params.ascending) { findOpts.ascending = params.ascending; } - if (params && params.status) { findOpts.status = params.status; } - + if(params){ + _.keys(this.queryParams).forEach(function(opt) { + if (params[opt]) { findOpts[opt] = params[opt]; } + }); + } return Discourse.TopicList.list(filter, findOpts).then(function(list) { var tracking = Discourse.TopicTrackingState.current(); @@ -36,10 +39,9 @@ export default function(filter) { setupController: function(controller, model, trans) { - controller.setProperties({ - order: Em.get(trans, 'queryParams.order'), - ascending: Em.get(trans, 'queryParams.ascending') - }); + controller.setProperties(Em.getProperties(trans, _.keys(this.queryParams).map(function(v){ + return 'queryParams.' + v; + }))); var period = filter.indexOf('/') > 0 ? filter.split('/')[1] : '', filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0}); diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index 7e0ac7874c4..18ec8d64d4a 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -270,6 +270,7 @@ class ListController < ApplicationController min_posts: params[:min_posts], max_posts: params[:max_posts], status: params[:status], + state: params[:state], search: params[:search] } options[:no_subcategories] = true if params[:no_subcategories] == 'true' diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 34464bea7c1..f4c84ccaebe 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -23,6 +23,7 @@ class TopicQuery no_subcategories no_definitions status + state search ).map(&:to_sym) @@ -265,6 +266,19 @@ class TopicQuery result = result.where("topics.id in (select pp.topic_id from post_search_data pd join posts pp on pp.id = pd.post_id where pd.search_data @@ #{Search.ts_query(search.to_s)})") end + # NOTE protect against SYM attack can be removed with Ruby 2.2 + # + state = options[:state] + if @user && state && + TopicUser.notification_levels.keys.map(&:to_s).include?(state) + level = TopicUser.notification_levels[state.to_sym] + result = result.where('topics.id IN ( + SELECT topic_id + FROM topic_users + WHERE user_id = ? AND + notification_level = ?)', @user.id, level) + end + if status = options[:status] case status when 'open'