Skip to content
This repository was archived by the owner on Jul 14, 2025. It is now read-only.

Commit 9306bc2

Browse files
authored
DEV: improve group query access for report PM (#372)
This change updates the report generator script to handle groups first, that way when the option users_from_group: true is used we can determine query access based on the user rather than the whole group.
1 parent f3ecd52 commit 9306bc2

File tree

3 files changed

+85
-24
lines changed

3 files changed

+85
-24
lines changed

lib/discourse_data_explorer/report_generator.rb

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,33 @@ def self.filter_recipients_by_query_access(recipients, query, users_from_group:
125125
emails = recipients - users.pluck(:username) - groups.pluck(:name)
126126
result = []
127127

128-
users.each do |user|
129-
result << [user.username, "username"] if Guardian.new(user).user_can_access_query?(query)
128+
query_group_ids = [Group::AUTO_GROUPS[:admins]].concat(query.groups.pluck(:group_id)).uniq
129+
130+
if users_from_group
131+
result.concat(
132+
User
133+
.joins(:group_users)
134+
.where(group_users: { group_id: groups.ids })
135+
.where(
136+
"users.admin OR EXISTS (
137+
SELECT 1 FROM group_users gu
138+
WHERE gu.user_id = users.id
139+
AND gu.group_id IN (?)
140+
)",
141+
query_group_ids,
142+
)
143+
.distinct
144+
.pluck(:username)
145+
.map { |username| [username, "username"] },
146+
)
147+
else
148+
groups.each do |group|
149+
result << [group.name, "group_name"] if query_group_ids.include?(group.id)
150+
end
130151
end
131152

132-
groups.each do |group|
133-
if group.id == Group::AUTO_GROUPS[:admins] || query.query_groups.exists?(group_id: group.id)
134-
if users_from_group
135-
result.concat(group.users.pluck(:username).map { |username| [username, "username"] })
136-
else
137-
result << [group.name, "group_name"]
138-
end
139-
end
153+
users.each do |user|
154+
result << [user.username, "username"] if Guardian.new(user).user_can_access_query?(query)
140155
end
141156

142157
emails.each { |email| result << [email, "email"] if Email.is_valid?(email) }

spec/automation/recurring_data_explorer_result_pm_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
automation.trigger!
6262
end.to change { Topic.count }.by(3)
6363

64-
user_topics = Topic.first(2)
65-
group_topics = Topic.last(1)
64+
user_topics = Topic.last(2)
65+
group_topics = Topic.first(1)
6666
expect(Topic.last(3).pluck(:archetype)).to eq(
6767
[Archetype.private_message, Archetype.private_message, Archetype.private_message],
6868
)
@@ -83,7 +83,7 @@
8383
automation.update(last_updated_by_id: admin.id)
8484
automation.trigger!
8585

86-
expect(Post.last.raw).to eq(
86+
expect(Post.first.raw).to eq(
8787
I18n.t(
8888
"data_explorer.report_generator.private_message.body",
8989
recipient_name: another_group.name,
@@ -112,7 +112,7 @@
112112
automation.update(last_updated_by_id: admin.id)
113113
automation.trigger!
114114

115-
expect(Post.last.raw).to eq(
115+
expect(Post.first.raw).to eq(
116116
I18n.t(
117117
"data_explorer.report_generator.private_message.body",
118118
recipient_name: another_group.name,

spec/report_generator_spec.rb

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,66 @@
170170
)
171171

172172
expect(result.length).to eq(3)
173-
expect(result[0]["target_usernames"]).to eq([user.username])
174-
expect(result[1]["target_group_names"]).to eq([group.name])
173+
expect(result[0]["target_group_names"]).to eq([group.name])
174+
expect(result[1]["target_usernames"]).to eq([user.username])
175175
expect(result[2]["target_emails"]).to eq(["john@doe.com"])
176176
end
177177

178-
it "extracts users from group when option is selected" do
179-
Fabricate(:query_group, query: query, group: group)
180-
DiscourseDataExplorer::ResultToMarkdown.expects(:convert).returns("le table")
181-
freeze_time
178+
describe "with users_from_group" do
179+
fab!(:valid_group) { Fabricate(:group, users: [user]) }
180+
fab!(:invalid_group) { Fabricate(:group, users: []) }
182181

183-
result =
184-
described_class.generate(query.id, query_params, [group.name], { users_from_group: true })
185-
expect(result.length).to eq(1)
186-
expect(result[0]["target_usernames"]).to eq([user.username])
182+
describe "when true" do
183+
let(:opts) { { users_from_group: true } }
184+
185+
it "does not work when no query groups are set" do
186+
result = described_class.generate(query.id, query_params, [group.name], opts)
187+
expect(result).to eq []
188+
end
189+
190+
it "works when user is a member of automation group and query group" do
191+
Fabricate(:query_group, query: query, group: valid_group)
192+
result = described_class.generate(query.id, query_params, [group.name], opts)
193+
194+
expect(result.length).to eq(1)
195+
expect(result[0]["target_usernames"]).to eq([user.username])
196+
end
197+
198+
it "does not work when user is a member of automation group but not query group" do
199+
Fabricate(:query_group, query: query, group: invalid_group)
200+
result = described_class.generate(query.id, query_params, [group.name], opts)
201+
202+
expect(result).to eq []
203+
end
204+
205+
it "works when user has access to one group in query groups" do
206+
Fabricate(:query_group, query: query, group: valid_group)
207+
Fabricate(:query_group, query: query, group: invalid_group)
208+
209+
result = described_class.generate(query.id, query_params, [group.name], opts)
210+
211+
expect(result.length).to eq(1)
212+
expect(result[0]["target_usernames"]).to eq([user.username])
213+
end
214+
end
215+
216+
describe "when false" do
217+
let(:opts) { { users_from_group: false } }
218+
219+
it "works when group has query access" do
220+
Fabricate(:query_group, query: query, group: group)
221+
result = described_class.generate(query.id, query_params, [group.name], opts)
222+
223+
expect(result.length).to eq(1)
224+
expect(result[0]["target_group_names"]).to eq([group.name])
225+
end
226+
227+
it "doesn't work when group doesn't have query access" do
228+
result = described_class.generate(query.id, query_params, [group.name], opts)
229+
230+
expect(result).to eq []
231+
end
232+
end
187233
end
188234

189235
it "works with attached csv file" do

0 commit comments

Comments
 (0)