filter out non-anon questions from blocked/muted users in public timeline
This commit is contained in:
parent
f1a1321a25
commit
920187bc88
|
@ -16,7 +16,7 @@ class TimelineController < ApplicationController
|
||||||
|
|
||||||
def public
|
def public
|
||||||
@title = generate_title(t(".title"))
|
@title = generate_title(t(".title"))
|
||||||
paginate_timeline { |args| Answer.cursored_public_timeline(**args) }
|
paginate_timeline { |args| Answer.cursored_public_timeline(**args, current_user:) }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -5,8 +5,21 @@ module Answer::TimelineMethods
|
||||||
|
|
||||||
define_cursor_paginator :cursored_public_timeline, :public_timeline
|
define_cursor_paginator :cursored_public_timeline, :public_timeline
|
||||||
|
|
||||||
def public_timeline
|
def public_timeline(current_user: nil)
|
||||||
joins(:user)
|
joins(:user)
|
||||||
|
.then do |query|
|
||||||
|
next query unless current_user
|
||||||
|
|
||||||
|
blocked_and_muted_user_ids = current_user.blocked_user_ids_cached + current_user.muted_user_ids_cached
|
||||||
|
next query if blocked_and_muted_user_ids.empty?
|
||||||
|
|
||||||
|
# build a more complex query if we block or mute someone
|
||||||
|
# otherwise the query ends up as "anon OR (NOT anon AND user_id NOT IN (NULL))" which will only return anonymous questions
|
||||||
|
query
|
||||||
|
.joins(:question)
|
||||||
|
.where("questions.author_is_anonymous OR (NOT questions.author_is_anonymous AND questions.user_id NOT IN (?))", blocked_and_muted_user_ids)
|
||||||
|
.where.not(answers: { user_id: blocked_and_muted_user_ids })
|
||||||
|
end
|
||||||
.where(users: { privacy_allow_public_timeline: true })
|
.where(users: { privacy_allow_public_timeline: true })
|
||||||
.order(:created_at)
|
.order(:created_at)
|
||||||
.reverse_order
|
.reverse_order
|
||||||
|
|
|
@ -23,7 +23,7 @@ describe Answer, type: :model do
|
||||||
|
|
||||||
context "user has the question in their inbox" do
|
context "user has the question in their inbox" do
|
||||||
before do
|
before do
|
||||||
Inbox.create(user: user, question: question, new: true)
|
Inbox.create(user:, question:, new: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should remove the question from the user's inbox" do
|
it "should remove the question from the user's inbox" do
|
||||||
|
@ -91,4 +91,147 @@ describe Answer, type: :model do
|
||||||
expect { subject.destroy }.to change { question.answer_count }.by(-1)
|
expect { subject.destroy }.to change { question.answer_count }.by(-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".public_timeline" do
|
||||||
|
let(:user) { FactoryBot.create(:user) }
|
||||||
|
let(:user1) { FactoryBot.create(:user) }
|
||||||
|
let(:user2) { FactoryBot.create(:user) }
|
||||||
|
|
||||||
|
let(:blocked_user) { FactoryBot.create(:user) }
|
||||||
|
let(:muted_user) { FactoryBot.create(:user) }
|
||||||
|
let!(:answer_to_anonymous) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user1,
|
||||||
|
content: "answer to a true anonymous coward",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
author_is_anonymous: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_normal_user) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user2,
|
||||||
|
content: "answer to a normal user",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: user1,
|
||||||
|
author_is_anonymous: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_normal_user_anonymous) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user2,
|
||||||
|
content: "answer to a cowardly user",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: user1,
|
||||||
|
author_is_anonymous: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_from_blocked_user) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: blocked_user,
|
||||||
|
content: "answer from a blocked user",
|
||||||
|
question: FactoryBot.create(:question)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_blocked_user) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user1,
|
||||||
|
content: "answer to a blocked user",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: blocked_user,
|
||||||
|
author_is_anonymous: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_blocked_user_anonymous) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user1,
|
||||||
|
content: "answer to a blocked user who's a coward",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: blocked_user,
|
||||||
|
author_is_anonymous: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_from_muted_user) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: muted_user,
|
||||||
|
content: "answer from a muted user",
|
||||||
|
question: FactoryBot.create(:question)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_muted_user) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user2,
|
||||||
|
content: "answer to a muted user",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: muted_user,
|
||||||
|
author_is_anonymous: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let!(:answer_to_muted_user_anonymous) do
|
||||||
|
FactoryBot.create(
|
||||||
|
:answer,
|
||||||
|
user: user2,
|
||||||
|
content: "answer to a muted user who's a coward",
|
||||||
|
question: FactoryBot.create(
|
||||||
|
:question,
|
||||||
|
user: muted_user,
|
||||||
|
author_is_anonymous: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { Answer.public_timeline }
|
||||||
|
|
||||||
|
it "includes all answers to questions from all the users" do
|
||||||
|
expect(subject).to include(answer_to_anonymous)
|
||||||
|
expect(subject).to include(answer_to_normal_user)
|
||||||
|
expect(subject).to include(answer_to_normal_user_anonymous)
|
||||||
|
expect(subject).to include(answer_to_blocked_user_anonymous)
|
||||||
|
expect(subject).to include(answer_to_muted_user_anonymous)
|
||||||
|
expect(subject).to include(answer_to_blocked_user)
|
||||||
|
expect(subject).to include(answer_to_muted_user)
|
||||||
|
expect(subject).to include(answer_from_blocked_user)
|
||||||
|
expect(subject).to include(answer_from_muted_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when given a current user who blocks and mutes some users" do
|
||||||
|
before do
|
||||||
|
user.block blocked_user
|
||||||
|
user.mute muted_user
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { Answer.public_timeline current_user: user }
|
||||||
|
|
||||||
|
it "only includes answers to questions from users the user doesn't block or mute" do
|
||||||
|
expect(subject).to include(answer_to_anonymous)
|
||||||
|
expect(subject).to include(answer_to_normal_user)
|
||||||
|
expect(subject).to include(answer_to_normal_user_anonymous)
|
||||||
|
expect(subject).to include(answer_to_blocked_user_anonymous)
|
||||||
|
expect(subject).to include(answer_to_muted_user_anonymous)
|
||||||
|
expect(subject).not_to include(answer_to_blocked_user)
|
||||||
|
expect(subject).not_to include(answer_from_blocked_user)
|
||||||
|
expect(subject).not_to include(answer_to_muted_user)
|
||||||
|
expect(subject).not_to include(answer_from_muted_user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue