* Hide blocked, muted, and blocked-by users from toot favourite lists * Hide blocked, muted, and blocked-by users from toot reblog lists * Hide blocked, muted, and blocked-by users from followers/following (API) * Fix tests * Hide blocked, muted, and blocked-by users from followers/following on public pagesmaster^2
@@ -21,7 +21,9 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController | |||||
def load_accounts | def load_accounts | ||||
return [] if hide_results? | return [] if hide_results? | ||||
default_accounts.merge(paginated_follows).to_a | |||||
scope = default_accounts | |||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? | |||||
scope.merge(paginated_follows).to_a | |||||
end | end | ||||
def hide_results? | def hide_results? | ||||
@@ -21,7 +21,9 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController | |||||
def load_accounts | def load_accounts | ||||
return [] if hide_results? | return [] if hide_results? | ||||
default_accounts.merge(paginated_follows).to_a | |||||
scope = default_accounts | |||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? | |||||
scope.merge(paginated_follows).to_a | |||||
end | end | ||||
def hide_results? | def hide_results? | ||||
@@ -17,7 +17,9 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController | |||||
private | private | ||||
def load_accounts | def load_accounts | ||||
default_accounts.merge(paginated_favourites).to_a | |||||
scope = default_accounts | |||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? | |||||
scope.merge(paginated_favourites).to_a | |||||
end | end | ||||
def default_accounts | def default_accounts | ||||
@@ -17,7 +17,9 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController | |||||
private | private | ||||
def load_accounts | def load_accounts | ||||
default_accounts.merge(paginated_statuses).to_a | |||||
scope = default_accounts | |||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? | |||||
scope.merge(paginated_statuses).to_a | |||||
end | end | ||||
def default_accounts | def default_accounts | ||||
@@ -36,7 +36,11 @@ class FollowerAccountsController < ApplicationController | |||||
private | private | ||||
def follows | def follows | ||||
@follows ||= Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account) | |||||
return @follows if defined?(@follows) | |||||
scope = Follow.where(target_account: @account) | |||||
scope = scope.where.not(account_id: current_account.excluded_from_timeline_account_ids) if user_signed_in? | |||||
@follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account) | |||||
end | end | ||||
def page_requested? | def page_requested? | ||||
@@ -36,7 +36,11 @@ class FollowingAccountsController < ApplicationController | |||||
private | private | ||||
def follows | def follows | ||||
@follows ||= Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account) | |||||
return @follows if defined?(@follows) | |||||
scope = Follow.where(account: @account) | |||||
scope = scope.where.not(target_account_id: current_account.excluded_from_timeline_account_ids) if user_signed_in? | |||||
@follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account) | |||||
end | end | ||||
def page_requested? | def page_requested? | ||||
@@ -3,19 +3,38 @@ require 'rails_helper' | |||||
describe Api::V1::Accounts::FollowerAccountsController do | describe Api::V1::Accounts::FollowerAccountsController do | ||||
render_views | render_views | ||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | |||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } | |||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | |||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } | |||||
let(:account) { Fabricate(:account) } | |||||
let(:alice) { Fabricate(:account) } | |||||
let(:bob) { Fabricate(:account) } | |||||
before do | before do | ||||
Fabricate(:follow, target_account: user.account) | |||||
alice.follow!(account) | |||||
bob.follow!(account) | |||||
allow(controller).to receive(:doorkeeper_token) { token } | allow(controller).to receive(:doorkeeper_token) { token } | ||||
end | end | ||||
describe 'GET #index' do | describe 'GET #index' do | ||||
it 'returns http success' do | it 'returns http success' do | ||||
get :index, params: { account_id: user.account.id, limit: 1 } | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(response).to have_http_status(200) | expect(response).to have_http_status(200) | ||||
end | end | ||||
it 'returns accounts following the given account' do | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 2 | |||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) | |||||
end | |||||
it 'does not return blocked users' do | |||||
user.account.block!(bob) | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 1 | |||||
expect(body_as_json[0][:id]).to eq alice.id.to_s | |||||
end | |||||
end | end | ||||
end | end |
@@ -3,19 +3,38 @@ require 'rails_helper' | |||||
describe Api::V1::Accounts::FollowingAccountsController do | describe Api::V1::Accounts::FollowingAccountsController do | ||||
render_views | render_views | ||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | |||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } | |||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | |||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } | |||||
let(:account) { Fabricate(:account) } | |||||
let(:alice) { Fabricate(:account) } | |||||
let(:bob) { Fabricate(:account) } | |||||
before do | before do | ||||
Fabricate(:follow, account: user.account) | |||||
account.follow!(alice) | |||||
account.follow!(bob) | |||||
allow(controller).to receive(:doorkeeper_token) { token } | allow(controller).to receive(:doorkeeper_token) { token } | ||||
end | end | ||||
describe 'GET #index' do | describe 'GET #index' do | ||||
it 'returns http success' do | it 'returns http success' do | ||||
get :index, params: { account_id: user.account.id, limit: 1 } | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(response).to have_http_status(200) | expect(response).to have_http_status(200) | ||||
end | end | ||||
it 'returns accounts followed by the given account' do | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 2 | |||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) | |||||
end | |||||
it 'does not return blocked users' do | |||||
user.account.block!(bob) | |||||
get :index, params: { account_id: account.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 1 | |||||
expect(body_as_json[0][:id]).to eq alice.id.to_s | |||||
end | |||||
end | end | ||||
end | end |
@@ -6,6 +6,8 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control | |||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | ||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } | let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } | ||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } | let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } | ||||
let(:alice) { Fabricate(:account) } | |||||
let(:bob) { Fabricate(:account) } | |||||
context 'with an oauth token' do | context 'with an oauth token' do | ||||
before do | before do | ||||
@@ -16,14 +18,28 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control | |||||
let(:status) { Fabricate(:status, account: user.account) } | let(:status) { Fabricate(:status, account: user.account) } | ||||
before do | before do | ||||
Fabricate(:favourite, status: status) | |||||
Favourite.create!(account: alice, status: status) | |||||
Favourite.create!(account: bob, status: status) | |||||
end | end | ||||
it 'returns http success' do | it 'returns http success' do | ||||
get :index, params: { status_id: status.id, limit: 1 } | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(response).to have_http_status(200) | expect(response).to have_http_status(200) | ||||
expect(response.headers['Link'].links.size).to eq(2) | expect(response.headers['Link'].links.size).to eq(2) | ||||
end | end | ||||
it 'returns accounts who favorited the status' do | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 2 | |||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) | |||||
end | |||||
it 'does not return blocked users' do | |||||
user.account.block!(bob) | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 1 | |||||
expect(body_as_json[0][:id]).to eq alice.id.to_s | |||||
end | |||||
end | end | ||||
end | end | ||||
@@ -6,6 +6,8 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll | |||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } | ||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } | let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } | ||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } | let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } | ||||
let(:alice) { Fabricate(:account) } | |||||
let(:bob) { Fabricate(:account) } | |||||
context 'with an oauth token' do | context 'with an oauth token' do | ||||
before do | before do | ||||
@@ -16,14 +18,28 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll | |||||
let(:status) { Fabricate(:status, account: user.account) } | let(:status) { Fabricate(:status, account: user.account) } | ||||
before do | before do | ||||
Fabricate(:status, reblog_of_id: status.id) | |||||
Fabricate(:status, account: alice, reblog_of_id: status.id) | |||||
Fabricate(:status, account: bob, reblog_of_id: status.id) | |||||
end | end | ||||
it 'returns http success' do | it 'returns http success' do | ||||
get :index, params: { status_id: status.id, limit: 1 } | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(response).to have_http_status(200) | expect(response).to have_http_status(200) | ||||
expect(response.headers['Link'].links.size).to eq(2) | expect(response.headers['Link'].links.size).to eq(2) | ||||
end | end | ||||
it 'returns accounts who reblogged the status' do | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 2 | |||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) | |||||
end | |||||
it 'does not return blocked users' do | |||||
user.account.block!(bob) | |||||
get :index, params: { status_id: status.id, limit: 2 } | |||||
expect(body_as_json.size).to eq 1 | |||||
expect(body_as_json[0][:id]).to eq alice.id.to_s | |||||
end | |||||
end | end | ||||
end | end | ||||
@@ -22,6 +22,18 @@ describe FollowerAccountsController do | |||||
expect(assigned[0]).to eq follow1 | expect(assigned[0]).to eq follow1 | ||||
expect(assigned[1]).to eq follow0 | expect(assigned[1]).to eq follow0 | ||||
end | end | ||||
it 'does not assign blocked users' do | |||||
user = Fabricate(:user) | |||||
user.account.block!(follower0) | |||||
sign_in(user) | |||||
expect(response).to have_http_status(200) | |||||
assigned = assigns(:follows).to_a | |||||
expect(assigned.size).to eq 1 | |||||
expect(assigned[0]).to eq follow1 | |||||
end | |||||
end | end | ||||
context 'when format is json' do | context 'when format is json' do | ||||
@@ -22,6 +22,18 @@ describe FollowingAccountsController do | |||||
expect(assigned[0]).to eq follow1 | expect(assigned[0]).to eq follow1 | ||||
expect(assigned[1]).to eq follow0 | expect(assigned[1]).to eq follow0 | ||||
end | end | ||||
it 'does not assign blocked users' do | |||||
user = Fabricate(:user) | |||||
user.account.block!(followee0) | |||||
sign_in(user) | |||||
expect(response).to have_http_status(200) | |||||
assigned = assigns(:follows).to_a | |||||
expect(assigned.size).to eq 1 | |||||
expect(assigned[0]).to eq follow1 | |||||
end | |||||
end | end | ||||
context 'when format is json' do | context 'when format is json' do | ||||