mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-06 01:41:08 +00:00
Merge 4fa462a9f8
into 14cb5ff881
This commit is contained in:
commit
0669e2a843
|
@ -7,14 +7,14 @@ module Admin
|
||||||
def show
|
def show
|
||||||
authorize :follow_recommendation, :show?
|
authorize :follow_recommendation, :show?
|
||||||
|
|
||||||
@form = Form::AccountBatch.new
|
@form = Form::FollowRecommendationBatch.new
|
||||||
@accounts = filtered_follow_recommendations.page(params[:page])
|
@accounts = filtered_follow_recommendations.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
authorize :follow_recommendation, :show?
|
authorize :follow_recommendation, :show?
|
||||||
|
|
||||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::FollowRecommendationBatch.new(form_follow_recommendation_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
@ -36,9 +36,9 @@ module Admin
|
||||||
@follow_recommendation_filter ||= FollowRecommendationFilter.new(filter_params)
|
@follow_recommendation_filter ||= FollowRecommendationFilter.new(filter_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_follow_recommendation_batch_params
|
||||||
params
|
params
|
||||||
.expect(form_account_batch: [:action, account_ids: []])
|
.expect(form_follow_recommendation_batch: [:action, account_ids: []])
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_params
|
def filter_params
|
||||||
|
|
|
@ -10,11 +10,11 @@ class RelationshipsController < ApplicationController
|
||||||
helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
|
helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@form = Form::AccountBatch.new
|
@form = Form::RelationshipBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::RelationshipBatch.new(form_relationship_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
@ -34,8 +34,8 @@ class RelationshipsController < ApplicationController
|
||||||
@relationships = AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
|
@relationships = AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_relationship_batch_params
|
||||||
params.expect(form_account_batch: [:action, account_ids: []])
|
params.expect(form_relationship_batch: [:action, account_ids: []])
|
||||||
end
|
end
|
||||||
|
|
||||||
def following_relationship?
|
def following_relationship?
|
||||||
|
|
|
@ -9,22 +9,10 @@ class Form::AccountBatch < Form::BaseBatch
|
||||||
|
|
||||||
def save
|
def save
|
||||||
case action
|
case action
|
||||||
when 'follow'
|
|
||||||
follow!
|
|
||||||
when 'unfollow'
|
|
||||||
unfollow!
|
|
||||||
when 'remove_from_followers'
|
|
||||||
remove_from_followers!
|
|
||||||
when 'remove_domains_from_followers'
|
|
||||||
remove_domains_from_followers!
|
|
||||||
when 'approve'
|
when 'approve'
|
||||||
approve!
|
approve!
|
||||||
when 'reject'
|
when 'reject'
|
||||||
reject!
|
reject!
|
||||||
when 'suppress_follow_recommendation'
|
|
||||||
suppress_follow_recommendation!
|
|
||||||
when 'unsuppress_follow_recommendation'
|
|
||||||
unsuppress_follow_recommendation!
|
|
||||||
when 'suspend'
|
when 'suspend'
|
||||||
suspend!
|
suspend!
|
||||||
end
|
end
|
||||||
|
@ -32,36 +20,6 @@ class Form::AccountBatch < Form::BaseBatch
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def follow!
|
|
||||||
error = nil
|
|
||||||
|
|
||||||
accounts.each do |target_account|
|
|
||||||
FollowService.new.call(current_account, target_account)
|
|
||||||
rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound => e
|
|
||||||
error ||= e
|
|
||||||
end
|
|
||||||
|
|
||||||
raise error if error.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
def unfollow!
|
|
||||||
accounts.each do |target_account|
|
|
||||||
UnfollowService.new.call(current_account, target_account)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_from_followers!
|
|
||||||
RemoveFromFollowersService.new.call(current_account, account_ids)
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_domains_from_followers!
|
|
||||||
RemoveDomainsFromFollowersService.new.call(current_account, account_domains)
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_domains
|
|
||||||
accounts.group(:domain).pluck(:domain).compact
|
|
||||||
end
|
|
||||||
|
|
||||||
def accounts
|
def accounts
|
||||||
if select_all_matching?
|
if select_all_matching?
|
||||||
query
|
query
|
||||||
|
@ -92,20 +50,6 @@ class Form::AccountBatch < Form::BaseBatch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def suppress_follow_recommendation!
|
|
||||||
authorize(:follow_recommendation, :suppress?)
|
|
||||||
|
|
||||||
accounts.find_each do |account|
|
|
||||||
FollowRecommendationSuppression.create(account: account)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unsuppress_follow_recommendation!
|
|
||||||
authorize(:follow_recommendation, :unsuppress?)
|
|
||||||
|
|
||||||
FollowRecommendationSuppression.where(account_id: account_ids).destroy_all
|
|
||||||
end
|
|
||||||
|
|
||||||
def reject_account(account)
|
def reject_account(account)
|
||||||
authorize(account.user, :reject?)
|
authorize(account.user, :reject?)
|
||||||
log_action(:reject, account.user)
|
log_action(:reject, account.user)
|
||||||
|
|
38
app/models/form/follow_recommendation_batch.rb
Normal file
38
app/models/form/follow_recommendation_batch.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Form::FollowRecommendationBatch < Form::BaseBatch
|
||||||
|
attr_accessor :account_ids
|
||||||
|
|
||||||
|
def save
|
||||||
|
case action
|
||||||
|
when 'suppress_follow_recommendation'
|
||||||
|
suppress!
|
||||||
|
when 'unsuppress_follow_recommendation'
|
||||||
|
unsuppress!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def persisted?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def suppress!
|
||||||
|
authorize(:follow_recommendation, :suppress?)
|
||||||
|
|
||||||
|
accounts.find_each do |account|
|
||||||
|
FollowRecommendationSuppression.create(account: account)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsuppress!
|
||||||
|
authorize(:follow_recommendation, :unsuppress?)
|
||||||
|
|
||||||
|
FollowRecommendationSuppression.where(account_id: account_ids).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
def accounts
|
||||||
|
Account.where(id: account_ids)
|
||||||
|
end
|
||||||
|
end
|
58
app/models/form/relationship_batch.rb
Normal file
58
app/models/form/relationship_batch.rb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Form::RelationshipBatch < Form::BaseBatch
|
||||||
|
attr_accessor :account_ids
|
||||||
|
|
||||||
|
def save
|
||||||
|
case action
|
||||||
|
when 'follow'
|
||||||
|
follow!
|
||||||
|
when 'unfollow'
|
||||||
|
unfollow!
|
||||||
|
when 'remove_from_followers'
|
||||||
|
remove_from_followers!
|
||||||
|
when 'remove_domains_from_followers'
|
||||||
|
remove_domains_from_followers!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def persisted?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def follow!
|
||||||
|
error = nil
|
||||||
|
|
||||||
|
accounts.each do |target_account|
|
||||||
|
FollowService.new.call(current_account, target_account)
|
||||||
|
rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound => e
|
||||||
|
error ||= e
|
||||||
|
end
|
||||||
|
|
||||||
|
raise error if error.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfollow!
|
||||||
|
accounts.each do |target_account|
|
||||||
|
UnfollowService.new.call(current_account, target_account)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_from_followers!
|
||||||
|
RemoveFromFollowersService.new.call(current_account, account_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_domains_from_followers!
|
||||||
|
RemoveDomainsFromFollowersService.new.call(current_account, account_domains)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_domains
|
||||||
|
accounts.group(:domain).pluck(:domain).compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def accounts
|
||||||
|
Account.where(id: account_ids)
|
||||||
|
end
|
||||||
|
end
|
|
@ -21,7 +21,7 @@
|
||||||
%li= filter_link_to t('admin.accounts.moderation.active'), status: nil
|
%li= filter_link_to t('admin.accounts.moderation.active'), status: nil
|
||||||
%li= filter_link_to t('admin.follow_recommendations.suppressed'), status: 'suppressed'
|
%li= filter_link_to t('admin.follow_recommendations.suppressed'), status: 'suppressed'
|
||||||
|
|
||||||
= form_with model: @form, url: admin_follow_recommendations_path, method: :patch do |f|
|
= form_with model: @form, url: admin_follow_recommendations_path do |f|
|
||||||
- RelationshipFilter::KEYS.each do |key|
|
- RelationshipFilter::KEYS.each do |key|
|
||||||
= hidden_field_tag key, params[key] if params[key].present?
|
= hidden_field_tag key, params[key] if params[key].present?
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
%li= filter_link_to t('relationships.most_recent'), order: nil
|
%li= filter_link_to t('relationships.most_recent'), order: nil
|
||||||
%li= filter_link_to t('relationships.last_active'), order: 'active'
|
%li= filter_link_to t('relationships.last_active'), order: 'active'
|
||||||
|
|
||||||
= form_with model: @form, url: relationships_path, method: :patch do |f|
|
= form_with model: @form, url: relationships_path do |f|
|
||||||
= hidden_field_tag :page, params[:page] || 1
|
= hidden_field_tag :page, params[:page] || 1
|
||||||
|
|
||||||
- RelationshipFilter::KEYS.each do |key|
|
- RelationshipFilter::KEYS.each do |key|
|
||||||
|
|
|
@ -53,7 +53,7 @@ RSpec.describe RelationshipsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when select parameter is provided' do
|
context 'when select parameter is provided' do
|
||||||
subject { patch :update, params: { form_account_batch: { account_ids: [alice.id] }, remove_domains_from_followers: '' } }
|
subject { patch :update, params: { form_relationship_batch: { account_ids: [alice.id] }, remove_domains_from_followers: '' } }
|
||||||
|
|
||||||
it 'soft-blocks followers from selected domains' do
|
it 'soft-blocks followers from selected domains' do
|
||||||
alice.follow!(user.account)
|
alice.follow!(user.account)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
Fabricator(:follow_recommendation_suppression) do
|
||||||
|
account { Fabricate.build(:account) }
|
||||||
|
end
|
|
@ -11,6 +11,7 @@ RSpec.describe Form::AccountBatch do
|
||||||
let(:account) { Fabricate(:admin_user).account }
|
let(:account) { Fabricate(:admin_user).account }
|
||||||
let(:account_ids) { [] }
|
let(:account_ids) { [] }
|
||||||
let(:query) { Account.none }
|
let(:query) { Account.none }
|
||||||
|
let(:select_all_matching) { false }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
account_batch.assign_attributes(
|
account_batch.assign_attributes(
|
||||||
|
@ -77,5 +78,37 @@ RSpec.describe Form::AccountBatch do
|
||||||
[target_account.reload, target_account2.reload].map(&:suspended?)
|
[target_account.reload, target_account2.reload].map(&:suspended?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when action is "approve"' do
|
||||||
|
let(:action) { 'approve' }
|
||||||
|
let(:account_ids) { [unapproved_user_account.id] }
|
||||||
|
let(:unapproved_user_account) { Fabricate :account }
|
||||||
|
|
||||||
|
before { unapproved_user_account.user.update!(approved: false) }
|
||||||
|
|
||||||
|
it 'approves the user of the supplied accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change { unapproved_user_account.reload.user.approved? }.to(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is "reject"' do
|
||||||
|
let(:action) { 'reject' }
|
||||||
|
let(:account_ids) { [reject_user_account.id] }
|
||||||
|
let(:reject_user_account) { Fabricate :account }
|
||||||
|
|
||||||
|
before { reject_user_account.user.update!(approved: false) }
|
||||||
|
|
||||||
|
it 'rejects the user of the supplied accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change { reject_user_account.reload.suspended? }.to(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is "unknown"' do
|
||||||
|
let(:action) { 'unknown' }
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
45
spec/models/form/follow_recommendation_batch_spec.rb
Normal file
45
spec/models/form/follow_recommendation_batch_spec.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Form::FollowRecommendationBatch do
|
||||||
|
describe '#persisted?' do
|
||||||
|
it { is_expected.to be_persisted }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#save' do
|
||||||
|
subject { described_class.new(action:, account_ids:, current_account: admin).save }
|
||||||
|
|
||||||
|
let(:account_ids) { [account.id] }
|
||||||
|
let(:account) { Fabricate :account }
|
||||||
|
let(:admin) { Fabricate :account, user: Fabricate(:admin_user) }
|
||||||
|
|
||||||
|
context 'when action is suppress_follow_recommendation' do
|
||||||
|
let(:action) { 'suppress_follow_recommendation' }
|
||||||
|
|
||||||
|
it 'adds a suppression for the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(FollowRecommendationSuppression, :count).by(1)
|
||||||
|
.and change { account.reload.follow_recommendation_suppression }.from(be_nil).to(be_present)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is unsuppress_follow_recommendation' do
|
||||||
|
let(:action) { 'unsuppress_follow_recommendation' }
|
||||||
|
|
||||||
|
before { Fabricate :follow_recommendation_suppression, account: }
|
||||||
|
|
||||||
|
it 'removes a suppression for the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(FollowRecommendationSuppression, :count).by(-1)
|
||||||
|
.and change { account.reload.follow_recommendation_suppression }.from(be_present).to(be_nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is unknown' do
|
||||||
|
let(:action) { 'unknown' }
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
87
spec/models/form/relationship_batch_spec.rb
Normal file
87
spec/models/form/relationship_batch_spec.rb
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Form::RelationshipBatch do
|
||||||
|
describe '#persisted?' do
|
||||||
|
it { is_expected.to be_persisted }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#save' do
|
||||||
|
subject { described_class.new(action:, account_ids:, current_account:).save }
|
||||||
|
|
||||||
|
let(:account_ids) { [account.id] }
|
||||||
|
let(:account) { Fabricate :account }
|
||||||
|
let(:current_account) { Fabricate :account }
|
||||||
|
|
||||||
|
context 'when action is follow' do
|
||||||
|
let(:action) { 'follow' }
|
||||||
|
let(:account_ids) { [account.id] }
|
||||||
|
|
||||||
|
it 'adds a follow for the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(Follow, :count).by(1)
|
||||||
|
.and change { current_account.reload.active_relationships.exists?(target_account: account) }.from(false).to(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when account cannot be followed' do
|
||||||
|
let(:account) { Fabricate :account, domain: 'test.example' }
|
||||||
|
|
||||||
|
it 'does not save follows and re-raises error' do
|
||||||
|
expect { subject }
|
||||||
|
.to raise_error(Mastodon::NotPermittedError)
|
||||||
|
.and not_change(Follow, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is unfollow' do
|
||||||
|
let(:action) { 'unfollow' }
|
||||||
|
|
||||||
|
before { Fabricate :follow, account: current_account, target_account: account }
|
||||||
|
|
||||||
|
it 'removes a follow for the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(Follow, :count).by(-1)
|
||||||
|
.and change { current_account.reload.active_relationships.exists?(target_account: account) }.from(true).to(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is remove_from_followers' do
|
||||||
|
let(:action) { 'remove_from_followers' }
|
||||||
|
|
||||||
|
before { Fabricate :follow, account: account, target_account: current_account }
|
||||||
|
|
||||||
|
it 'removes followers from the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(Follow, :count).by(-1)
|
||||||
|
.and change { current_account.reload.passive_relationships.exists?(account: account) }.from(true).to(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is remove_domains_from_followers' do
|
||||||
|
let(:action) { 'remove_domains_from_followers' }
|
||||||
|
|
||||||
|
let(:account) { Fabricate :account, domain: 'host.example' }
|
||||||
|
let(:account_other) { Fabricate :account, domain: 'host.example' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Fabricate :follow, account: account, target_account: current_account
|
||||||
|
Fabricate :follow, account: account_other, target_account: current_account
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'removes all followers from domains of the accounts' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(Follow, :count).by(-2)
|
||||||
|
.and change { current_account.reload.passive_relationships.exists?(account: account) }.from(true).to(false)
|
||||||
|
.and change { current_account.reload.passive_relationships.exists?(account: account_other) }.from(true).to(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when action is unknown' do
|
||||||
|
let(:action) { 'unknown' }
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,7 +7,7 @@ RSpec.describe 'Admin Follow Recommendations' do
|
||||||
before { sign_in Fabricate(:admin_user) }
|
before { sign_in Fabricate(:admin_user) }
|
||||||
|
|
||||||
it 'gracefully handles invalid nested params' do
|
it 'gracefully handles invalid nested params' do
|
||||||
put admin_follow_recommendations_path(form_account_batch: 'invalid')
|
put admin_follow_recommendations_path(form_follow_recommendation_batch: 'invalid')
|
||||||
|
|
||||||
expect(response)
|
expect(response)
|
||||||
.to redirect_to(admin_follow_recommendations_path)
|
.to redirect_to(admin_follow_recommendations_path)
|
||||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe 'Relationships' do
|
||||||
before { sign_in Fabricate(:user) }
|
before { sign_in Fabricate(:user) }
|
||||||
|
|
||||||
it 'gracefully handles invalid nested params' do
|
it 'gracefully handles invalid nested params' do
|
||||||
put relationships_path(form_account_batch: 'invalid')
|
put relationships_path(form_relationship_batch: 'invalid')
|
||||||
|
|
||||||
expect(response)
|
expect(response)
|
||||||
.to redirect_to(relationships_path)
|
.to redirect_to(relationships_path)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user