mirror of
https://github.com/discourse/discourse.git
synced 2026-08-03 01:49:44 -05:00
FEATURE: support group querying in created-by filter (/filter) (#35692)
Currently, there is no way to query topics `created by anyone in this (input-group)` , with this PR we address that. It is an overload – similar to what assign does: https://github.com/discourse/discourse/blob/a54e3208cb1e331346d17c1687f593dcdd9eb583/plugins/discourse-assign/plugin.rb#L327-L345 I used the same tests as in https://github.com/discourse/discourse/pull/35631
This commit is contained in:
@@ -2893,9 +2893,9 @@ en:
|
||||
activity_after: "Show topics with last activity after a date (YYYY-MM-DD or days ago)"
|
||||
created_before: "Show topics created before a date (YYYY-MM-DD or days ago)"
|
||||
created_after: "Show topics created after a date (YYYY-MM-DD or days ago)"
|
||||
created_by: "Show topics created by a specific user"
|
||||
created_by_user: "Show topics created by username (without @)"
|
||||
created_by_multiple: "Show topics created by any of the specified users (comma-separated)"
|
||||
created_by: "Show topics created by a specific user or group"
|
||||
created_by_user: "Show topics created by username or group (without @)"
|
||||
created_by_multiple: "Show topics created by any of the specified users or groups (comma-separated)"
|
||||
latest_post_before: "Show topics with last post before a date (YYYY-MM-DD or days ago)"
|
||||
latest_post_after: "Show topics with last post after a date (YYYY-MM-DD or days ago)"
|
||||
likes_min: "Show topics with at least this many likes"
|
||||
|
||||
+29
-8
@@ -52,7 +52,7 @@ class TopicsFilter
|
||||
when "created-before"
|
||||
filter_by_created(before: filter_values)
|
||||
when "created-by"
|
||||
filter_created_by_user(usernames: filter_values.flat_map { |value| value.split(",") })
|
||||
filter_created_by(names: filter_values.flat_map { |value| value.split(",") })
|
||||
when "in"
|
||||
filter_in(values: filter_values)
|
||||
when "latest-post-after"
|
||||
@@ -197,7 +197,7 @@ class TopicsFilter
|
||||
{
|
||||
name: "created-by:",
|
||||
description: I18n.t("filter.description.created_by"),
|
||||
type: "username",
|
||||
type: "username_group_list",
|
||||
delimiters: [{ name: ",", description: I18n.t("filter.description.created_by_multiple") }],
|
||||
},
|
||||
{
|
||||
@@ -659,12 +659,33 @@ class TopicsFilter
|
||||
SQL
|
||||
end
|
||||
|
||||
def filter_created_by_user(usernames:)
|
||||
@scope =
|
||||
@scope.joins(:user).where(
|
||||
"users.username_lower IN (:usernames)",
|
||||
usernames: usernames.map(&:downcase),
|
||||
)
|
||||
def filter_created_by(names:)
|
||||
if names.include?("me") && @guardian.authenticated?
|
||||
names = names.map { |n| n == "me" ? @guardian.user.username_lower : n }
|
||||
end
|
||||
if (user_ids = User.where("username_lower IN (?)", names.map(&:downcase)).pluck(:id)) &&
|
||||
user_ids.any?
|
||||
@scope = @scope.joins(:user).where(user_id: user_ids)
|
||||
return
|
||||
end
|
||||
|
||||
if (
|
||||
group_ids =
|
||||
Group
|
||||
.visible_groups(@guardian.user)
|
||||
.where("lower(name) IN (?)", names.map(&:downcase))
|
||||
.pluck(:id)
|
||||
) && group_ids.any?
|
||||
@scope =
|
||||
@scope
|
||||
.joins(:user)
|
||||
.joins("INNER JOIN group_users ON group_users.user_id = users.id")
|
||||
.where("group_users.group_id IN (?)", group_ids)
|
||||
.distinct(:id)
|
||||
return
|
||||
end
|
||||
|
||||
@scope = @scope.none
|
||||
end
|
||||
|
||||
def apply_custom_filter!(scope:, filter_name:, values:)
|
||||
|
||||
@@ -1699,6 +1699,129 @@ RSpec.describe TopicsFilter do
|
||||
).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:me`" do
|
||||
it "should return the topics created by the current user" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new(user))
|
||||
.filter_from_query_string("created-by:me")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_user.id, topic2_by_user.id)
|
||||
end
|
||||
|
||||
it "should not return any topics when there is no current user" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:me")
|
||||
.pluck(:id),
|
||||
).to eq([])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when filtering by topic creator's group" do
|
||||
fab!(:group1) { Fabricate(:group, name: "group1") }
|
||||
fab!(:group2) { Fabricate(:group, name: "group2") }
|
||||
fab!(:user_in_group1) { Fabricate(:user).tap { |u| group1.add(u) } }
|
||||
fab!(:user_in_group2) { Fabricate(:user).tap { |u| group2.add(u) } }
|
||||
fab!(:user_in_both_groups) do
|
||||
Fabricate(:user).tap do |u|
|
||||
group1.add(u)
|
||||
group2.add(u)
|
||||
end
|
||||
end
|
||||
fab!(:topic_by_group1_user) { Fabricate(:topic, user: user_in_group1) }
|
||||
fab!(:topic_by_group2_user) { Fabricate(:topic, user: user_in_group2) }
|
||||
fab!(:topic_by_both_groups_user) { Fabricate(:topic, user: user_in_both_groups) }
|
||||
|
||||
describe "when query string is `created-by:group1`" do
|
||||
it "should return topics created by users in the specified group" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:group1")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_group1_user.id, topic_by_both_groups_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:group2`" do
|
||||
it "should return topics created by users in the specified group" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:group2")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_group2_user.id, topic_by_both_groups_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when query string is `created-by:group1,group2`" do
|
||||
it "should return topics created by users in any of the specified groups" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:group1,group2")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(
|
||||
topic_by_group1_user.id,
|
||||
topic_by_group2_user.id,
|
||||
topic_by_both_groups_user.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
|
||||
|
||||
describe "when query string is `created-by:group1,invalid`" do
|
||||
it "should only return topics created by users in the valid group" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:group1,invalid")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_group1_user.id, topic_by_both_groups_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with group visibility restrictions" do
|
||||
fab!(:private_group) do
|
||||
Fabricate(:group, visibility_level: Group.visibility_levels[:members])
|
||||
end
|
||||
fab!(:user_in_private_group) { Fabricate(:user).tap { |u| private_group.add(u) } }
|
||||
fab!(:topic_by_private_group_user) { Fabricate(:topic, user: user_in_private_group) }
|
||||
|
||||
it "should not return topics when user cannot see the group" do
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new)
|
||||
.filter_from_query_string("created-by:#{private_group.name}")
|
||||
.pluck(:id),
|
||||
).to eq([])
|
||||
end
|
||||
|
||||
it "should return topics when user is a member of the private group" do
|
||||
private_group.add(user)
|
||||
|
||||
expect(
|
||||
TopicsFilter
|
||||
.new(guardian: Guardian.new(user))
|
||||
.filter_from_query_string("created-by:#{private_group.name}")
|
||||
.pluck(:id),
|
||||
).to contain_exactly(topic_by_private_group_user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "filtering for topics by counts" do |filter|
|
||||
|
||||
Reference in New Issue
Block a user