DEV: Support `created-by:<username>` filter on `/filter` route (#21067)
This commit adds support for the `created-by:<username>` query filter which will return topics created by the specified user. Multiple usernames can be specified by comma seperating the usernames like so: `created-by:username1,username2`. This will filter for topics created by either of the specified users. Multiple `created-by:<username>` can also be composed together. `created-by:username1 created-by:username2` is equivalent to `created-by:username1,username2`.
This commit is contained in:
parent
584a17c948
commit
a1524b84e2
|
@ -16,9 +16,11 @@ class TopicsFilter
|
|||
return @scope if query_string.blank?
|
||||
|
||||
query_string.scan(
|
||||
/(?<key_prefix>[-=])?(?<key>\w+):(?<value>[^\s]+)/,
|
||||
/(?<key_prefix>[-=])?(?<key>[\w-]+):(?<value>[^\s]+)/,
|
||||
) do |key_prefix, key, value|
|
||||
case key
|
||||
when "created-by"
|
||||
filter_created_by_user(usernames: value.split(","))
|
||||
when "in"
|
||||
@scope = filter_state(state: value)
|
||||
when "status"
|
||||
|
@ -90,6 +92,17 @@ class TopicsFilter
|
|||
|
||||
private
|
||||
|
||||
def filter_created_by_user(usernames:)
|
||||
register_scope(
|
||||
key: :created_by_user,
|
||||
params: {
|
||||
usernames: usernames.map(&:downcase),
|
||||
},
|
||||
) do |usernames_lower|
|
||||
@scope.joins(:user).where("users.username_lower IN (?)", usernames_lower)
|
||||
end
|
||||
end
|
||||
|
||||
def filter_state(state:)
|
||||
case state
|
||||
when "pinned"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe TopicsFilter do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:user) { Fabricate(:user, username: "username") }
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
|
||||
|
@ -737,5 +737,78 @@ RSpec.describe TopicsFilter do
|
|||
).to contain_exactly(topic_without_tag.id, topic_with_group_only_tag.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when filtering by topic author" do
|
||||
fab!(:user2) { Fabricate(:user, username: "username2") }
|
||||
fab!(:topic_by_user) { Fabricate(:topic, user: user) }
|
||||
fab!(:topic2_by_user) { Fabricate(:topic, user: user) }
|
||||
fab!(:topic_by_user2) { Fabricate(:topic, user: user2) }
|
||||
|
||||
describe "when query string is `created-by:username`" do
|
||||
it "should return the topics created by the specified user" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{user.username}")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user.id, topic2_by_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:username2`" do
|
||||
it "should return the topics created by the specified user" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{user2.username}")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user2.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:username created-by:username2`" do
|
||||
it "should return the topics created by either of the specified users" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{user.username} created-by:#{user2.username}")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user.id, topic2_by_user.id, topic_by_user2.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:username,invalid`" do
|
||||
it "should only return the topics created by the user with the valid username" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{user.username},invalid")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user.id, topic2_by_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:username,username2`" do
|
||||
it "should return the topics created by either of the specified users" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{user.username},#{user2.username}")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user.id, topic2_by_user.id, topic_by_user2.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:invalid`" do
|
||||
it "should not return any topics" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:invalid")
|
||||
.pluck(:id),
|
||||
).to eq([])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1132,9 +1132,25 @@ RSpec.describe ListController do
|
|||
describe "#filter" do
|
||||
fab!(:category) { Fabricate(:category) }
|
||||
fab!(:tag) { Fabricate(:tag, name: "tag1") }
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
fab!(:private_category) { Fabricate(:private_category, group: Fabricate(:group)) }
|
||||
fab!(:private_message_topic) { Fabricate(:private_message_topic) }
|
||||
fab!(:topic_in_private_category) { Fabricate(:topic, category: private_category) }
|
||||
|
||||
before { SiteSetting.experimental_topics_filter = true }
|
||||
|
||||
it "should not return topics that the user is not allowed to view" do
|
||||
sign_in(user)
|
||||
|
||||
get "/filter.json"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
expect(
|
||||
response.parsed_body["topic_list"]["topics"].map { |topic| topic["id"] },
|
||||
).to contain_exactly(topic.id)
|
||||
end
|
||||
|
||||
it "should respond with 403 response code for an anonymous user" do
|
||||
get "/filter.json"
|
||||
|
||||
|
@ -1212,6 +1228,40 @@ RSpec.describe ListController do
|
|||
end
|
||||
end
|
||||
|
||||
describe "when filtering with the `created-by:<username>` filter" do
|
||||
fab!(:topic2) { Fabricate(:topic, user: admin) }
|
||||
|
||||
before do
|
||||
topic.update!(user: user)
|
||||
user.update!(username: "username")
|
||||
admin.update!(username: "username2")
|
||||
end
|
||||
|
||||
it "returns only topics created by the user when `q` query param is `created-by:username`" do
|
||||
sign_in(user)
|
||||
|
||||
get "/filter.json", params: { q: "created-by:username" }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
expect(
|
||||
response.parsed_body["topic_list"]["topics"].map { |topic| topic["id"] },
|
||||
).to contain_exactly(topic.id)
|
||||
end
|
||||
|
||||
it "returns only topics created by either user when `q` query param is `created-by:username,username2`" do
|
||||
sign_in(user)
|
||||
|
||||
get "/filter.json", params: { q: "created-by:username,username2" }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
expect(
|
||||
response.parsed_body["topic_list"]["topics"].map { |topic| topic["id"] },
|
||||
).to contain_exactly(topic.id, topic2.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when filtering with the `in:<topic_notification_level>` filter" do
|
||||
fab!(:user_muted_topic) do
|
||||
Fabricate(:topic).tap do |topic|
|
||||
|
|
Loading…
Reference in New Issue