mirror of
https://github.com/discourse/discourse.git
synced 2026-08-11 01:57:29 +08:00
## Summary Align private-message read receipts with recipient-group visibility settings. `PostReadersController#ensure_can_see_readers!` (`app/controllers/post_readers_controller.rb:42`) now returns reader details only when the requester can view the membership of every recipient group and belongs to a group with read-state publishing enabled. `TopicView#show_read_indicator?` (`lib/topic_view.rb:297`) applies the same visibility rule to the UI. Realtime `:read` events from `TopicTrackingState.trigger_post_read_count_update` (`app/models/topic_tracking_state.rb:600`) continue to publish `readers_count`, but no longer include `reader_id`. Reader identities remain available through the authorized `/post_readers.json` endpoint. Tests cover group private messages with restricted member visibility. ## Source - Patch Triage: https://patch.discourse.org/patch-triage/1151 Co-authored-by: discourse-patch-triage <272280883+discourse-patch-triage[bot]@users.noreply.github.com>
174 lines
5.7 KiB
Ruby
Vendored
174 lines
5.7 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe PostReadersController do
|
|
describe "#index" do
|
|
fab!(:admin)
|
|
fab!(:reader, :user)
|
|
|
|
before { sign_in(admin) }
|
|
|
|
before do
|
|
@group = Fabricate(:group)
|
|
@group_message = Fabricate(:private_message_topic, allowed_groups: [@group])
|
|
@post = Fabricate(:post, topic: @group_message, post_number: 3)
|
|
end
|
|
|
|
context "when the user has access to readers data" do
|
|
before do
|
|
@group.update!(publish_read_state: true)
|
|
@group.add(admin)
|
|
@group.add(reader)
|
|
end
|
|
|
|
it "returns an empty list when nobody has read the topic" do
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
|
|
it "returns an user who read until that post" do
|
|
TopicUser.create!(user: reader, topic: @group_message, last_read_post_number: 3)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
reader_data = response.parsed_body["post_readers"].first
|
|
|
|
assert_reader_is_correctly_serialized(reader_data, reader, @post)
|
|
end
|
|
|
|
it "returns an user who read pass that post" do
|
|
TopicUser.create!(user: reader, topic: @group_message, last_read_post_number: 4)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
reader_data = response.parsed_body["post_readers"].first
|
|
|
|
assert_reader_is_correctly_serialized(reader_data, reader, @post)
|
|
end
|
|
|
|
it "return an empty list when nodobody read until that post" do
|
|
TopicUser.create!(user: reader, topic: @group_message, last_read_post_number: 1)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
|
|
it "doesn't include users without reading progress on first post" do
|
|
@post.update(post_number: 1)
|
|
TopicUser.create!(user: reader, topic: @group_message, last_read_post_number: nil)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
|
|
it "doesn't include staged users" do
|
|
TopicUser.create!(user: reader, topic: @group_message, last_read_post_number: 4)
|
|
reader.update(staged: true)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
|
|
it "doesn't include non-staff users when the post is a whisper" do
|
|
@post.update(post_type: Post.types[:whisper])
|
|
non_staff_user = Fabricate(:user)
|
|
TopicUser.create!(user: non_staff_user, topic: @group_message, last_read_post_number: 4)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
|
|
it "includes staff users when the post is a whisper" do
|
|
@post.update(post_type: Post.types[:whisper])
|
|
admin = Fabricate(:admin)
|
|
TopicUser.create!(user: admin, topic: @group_message, last_read_post_number: 4)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
reader_data = response.parsed_body["post_readers"].first
|
|
|
|
assert_reader_is_correctly_serialized(reader_data, admin, @post)
|
|
end
|
|
|
|
it "doesn't include bots" do
|
|
TopicUser.create!(
|
|
user: Discourse.system_user,
|
|
topic: @group_message,
|
|
last_read_post_number: 4,
|
|
)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
readers = response.parsed_body["post_readers"]
|
|
|
|
expect(readers).to be_empty
|
|
end
|
|
end
|
|
|
|
def assert_reader_is_correctly_serialized(reader_data, reader, post)
|
|
expect(reader_data["avatar_template"]).to eq reader.avatar_template
|
|
expect(reader_data["username"]).to eq reader.username
|
|
expect(reader_data["username_lower"]).to eq reader.username_lower
|
|
end
|
|
|
|
it "returns forbidden if current_user cannot see members of the read state group" do
|
|
member = Fabricate(:user)
|
|
hidden_member = Fabricate(:user)
|
|
|
|
@group.update!(
|
|
visibility_level: Group.visibility_levels[:members],
|
|
members_visibility_level: Group.visibility_levels[:staff],
|
|
publish_read_state: true,
|
|
)
|
|
@group.add(member)
|
|
@group.add(hidden_member)
|
|
TopicUser.create!(
|
|
user: hidden_member,
|
|
topic: @group_message,
|
|
last_read_post_number: @post.post_number,
|
|
)
|
|
|
|
sign_in(member)
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
|
|
expect(response).to be_forbidden
|
|
expect(response.parsed_body["error_type"]).to eq("invalid_access")
|
|
end
|
|
|
|
it "returns forbidden if no group has publish_read_state enabled" do
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
|
|
expect(response).to be_forbidden
|
|
end
|
|
|
|
it "returns forbidden if current_user is not a member of a group with publish_read_state enabled" do
|
|
@group.update!(publish_read_state: true)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
|
|
expect(response).to be_forbidden
|
|
end
|
|
|
|
it "returns forbidden when a non-staff group member requests readers for a whisper post" do
|
|
regular_user = Fabricate(:user)
|
|
@group.update!(publish_read_state: true)
|
|
@group.add(regular_user)
|
|
sign_in(regular_user)
|
|
|
|
@post.update!(post_type: Post.types[:whisper])
|
|
staff_reader = Fabricate(:admin)
|
|
@group.add(staff_reader)
|
|
TopicUser.create!(user: staff_reader, topic: @group_message, last_read_post_number: 4)
|
|
|
|
get "/post_readers.json", params: { id: @post.id }
|
|
|
|
expect(response).to be_forbidden
|
|
end
|
|
end
|
|
end
|