mirror of
https://github.com/mastodon/mastodon.git
synced 2026-03-14 22:44:08 +00:00
Add moderation consequences for collections (#37974)
This commit is contained in:
parent
ea34d35b32
commit
f9326efef6
|
|
@ -19,7 +19,7 @@ module Admin::ActionLogsHelper
|
|||
link_to "##{log.human_identifier.presence || log.target_id}", admin_report_path(log.target_id)
|
||||
when 'Instance', 'DomainBlock', 'DomainAllow', 'UnavailableDomain'
|
||||
log.human_identifier.present? ? link_to(log.human_identifier, admin_instance_path(log.human_identifier)) : I18n.t('admin.action_logs.unavailable_instance')
|
||||
when 'Status'
|
||||
when 'Status', 'Collection'
|
||||
link_to log.human_identifier, log.permalink
|
||||
when 'AccountWarning'
|
||||
link_to log.human_identifier, disputes_strike_path(log.target_id)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ class Admin::ModerationAction < Admin::BaseAction
|
|||
@statuses ||= Status.with_discarded.where(id: status_ids).reorder(nil)
|
||||
end
|
||||
|
||||
def collections
|
||||
report.collections
|
||||
end
|
||||
|
||||
def process_action!
|
||||
case type
|
||||
when 'delete'
|
||||
|
|
@ -29,19 +33,16 @@ class Admin::ModerationAction < Admin::BaseAction
|
|||
|
||||
def handle_delete!
|
||||
statuses.each { |status| authorize([:admin, status], :destroy?) }
|
||||
collections.each { |collection| authorize([:admin, collection], :destroy?) }
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
statuses.each do |status|
|
||||
status.discard_with_reblogs
|
||||
log_action(:destroy, status)
|
||||
end
|
||||
|
||||
report.resolve!(current_account)
|
||||
log_action(:resolve, report)
|
||||
delete_statuses!
|
||||
delete_collections!
|
||||
|
||||
resolve_report!
|
||||
process_strike!(:delete_statuses)
|
||||
|
||||
statuses.each { |status| Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) } unless target_account.local?
|
||||
create_tombstones! unless target_account.local?
|
||||
end
|
||||
|
||||
process_notification!
|
||||
|
|
@ -50,10 +51,39 @@ class Admin::ModerationAction < Admin::BaseAction
|
|||
end
|
||||
|
||||
def handle_mark_as_sensitive!
|
||||
representative_account = Account.representative
|
||||
collections.each { |collection| authorize([:admin, collection], :update?) }
|
||||
|
||||
# Can't use a transaction here because UpdateStatusService queues
|
||||
# Sidekiq jobs
|
||||
mark_statuses_as_sensitive!
|
||||
mark_collections_as_sensitive!
|
||||
|
||||
resolve_report!
|
||||
process_strike!(:mark_statuses_as_sensitive)
|
||||
process_notification!
|
||||
end
|
||||
|
||||
def delete_statuses!
|
||||
statuses.each do |status|
|
||||
status.discard_with_reblogs
|
||||
log_action(:destroy, status)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_collections!
|
||||
collections.each do |collection|
|
||||
collection.destroy!
|
||||
log_action(:destroy, collection)
|
||||
end
|
||||
end
|
||||
|
||||
def create_tombstones!
|
||||
(statuses + collections).each { |record| Tombstone.find_or_create_by(uri: record.uri, account: target_account, by_moderator: true) }
|
||||
end
|
||||
|
||||
def mark_statuses_as_sensitive!
|
||||
representative_account = Account.representative
|
||||
|
||||
statuses.includes(:media_attachments, preview_cards_status: :preview_card).find_each do |status|
|
||||
next if status.discarded? || !(status.with_media? || status.with_preview_card?)
|
||||
|
||||
|
|
@ -66,14 +96,20 @@ class Admin::ModerationAction < Admin::BaseAction
|
|||
end
|
||||
|
||||
log_action(:update, status)
|
||||
|
||||
report.resolve!(current_account)
|
||||
log_action(:resolve, report)
|
||||
end
|
||||
end
|
||||
|
||||
process_strike!(:mark_statuses_as_sensitive)
|
||||
def mark_collections_as_sensitive!
|
||||
collections.each do |collection|
|
||||
UpdateCollectionService.new.call(collection, sensitive: true)
|
||||
|
||||
process_notification!
|
||||
log_action(:update, collection)
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_report!
|
||||
report.resolve!(current_account)
|
||||
log_action(:resolve, report)
|
||||
end
|
||||
|
||||
def target_account
|
||||
|
|
|
|||
|
|
@ -69,6 +69,14 @@ class Collection < ApplicationRecord
|
|||
:featured_collection
|
||||
end
|
||||
|
||||
def to_log_human_identifier
|
||||
account.acct
|
||||
end
|
||||
|
||||
def to_log_permalink
|
||||
ActivityPub::TagManager.instance.uri_for(self)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag_is_usable
|
||||
|
|
|
|||
19
app/policies/admin/collection_policy.rb
Normal file
19
app/policies/admin/collection_policy.rb
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::CollectionPolicy < ApplicationPolicy
|
||||
def index?
|
||||
role.can?(:manage_reports, :manage_users)
|
||||
end
|
||||
|
||||
def show?
|
||||
role.can?(:manage_reports, :manage_users)
|
||||
end
|
||||
|
||||
def destroy?
|
||||
role.can?(:manage_reports)
|
||||
end
|
||||
|
||||
def update?
|
||||
role.can?(:manage_reports)
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
= link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(report), method: :post, class: 'button'
|
||||
.report-actions__item__description
|
||||
= t('admin.reports.actions.resolve_description_html')
|
||||
- if statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? }
|
||||
- if report.collections.any? || statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? }
|
||||
.report-actions__item
|
||||
.report-actions__item__button
|
||||
= form.button t('admin.reports.mark_as_sensitive'),
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
= form.button t('admin.reports.delete_and_resolve'),
|
||||
name: :delete,
|
||||
class: 'button button--destructive',
|
||||
disabled: statuses.empty?,
|
||||
title: statuses.empty? ? t('admin.reports.actions_no_posts') : ''
|
||||
disabled: (report.collections + statuses).empty?,
|
||||
title: (report.collections + statuses).empty? ? t('admin.reports.actions_no_posts') : ''
|
||||
.report-actions__item__description
|
||||
= t('admin.reports.actions.delete_description_html')
|
||||
.report-actions__item
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ en:
|
|||
demote_user_html: "%{name} demoted user %{target}"
|
||||
destroy_announcement_html: "%{name} deleted announcement %{target}"
|
||||
destroy_canonical_email_block_html: "%{name} unblocked email with the hash %{target}"
|
||||
destroy_collection_html: "%{name} removed collection by %{target}"
|
||||
destroy_custom_emoji_html: "%{name} deleted emoji %{target}"
|
||||
destroy_domain_allow_html: "%{name} disallowed federation with domain %{target}"
|
||||
destroy_domain_block_html: "%{name} unblocked domain %{target}"
|
||||
|
|
@ -306,6 +307,7 @@ en:
|
|||
unsilence_account_html: "%{name} undid limit of %{target}'s account"
|
||||
unsuspend_account_html: "%{name} unsuspended %{target}'s account"
|
||||
update_announcement_html: "%{name} updated announcement %{target}"
|
||||
update_collection_html: "%{name} updated collection by %{target}"
|
||||
update_custom_emoji_html: "%{name} updated emoji %{target}"
|
||||
update_domain_block_html: "%{name} updated domain block for %{target}"
|
||||
update_ip_block_html: "%{name} changed rule for IP %{target}"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,36 @@ RSpec.describe Admin::ModerationAction do
|
|||
end
|
||||
expect(report.reload).to be_action_taken
|
||||
end
|
||||
|
||||
context 'with attached collections', feature: :collections do
|
||||
let(:status_ids) { [] }
|
||||
let(:collections) { Fabricate.times(2, :collection, account: target_account) }
|
||||
|
||||
before do
|
||||
report.collections = collections
|
||||
end
|
||||
|
||||
it 'deletes the collections and creates an action log' do
|
||||
expect { subject.save! }.to change(Collection, :count).by(-2)
|
||||
.and change(Admin::ActionLog, :count).by(3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a remote collection', feature: :collections do
|
||||
let(:status_ids) { [] }
|
||||
let(:collection) { Fabricate(:remote_collection) }
|
||||
let(:target_account) { collection.account }
|
||||
|
||||
before do
|
||||
report.collections << collection
|
||||
end
|
||||
|
||||
it 'creates a tombstone' do
|
||||
expect { subject.save! }.to change(Tombstone, :count).by(1)
|
||||
|
||||
expect(Tombstone.last.uri).to eq collection.uri
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when `type` is `mark_as_sensitive`' do
|
||||
|
|
@ -52,6 +82,24 @@ RSpec.describe Admin::ModerationAction do
|
|||
end
|
||||
expect(report.reload).to be_action_taken
|
||||
end
|
||||
|
||||
context 'with attached collections', feature: :collections do
|
||||
let(:status_ids) { [] }
|
||||
let(:collections) { Fabricate.times(2, :collection, account: target_account) }
|
||||
|
||||
before do
|
||||
report.collections = collections
|
||||
end
|
||||
|
||||
it 'marks the collections as sensitive' do
|
||||
subject.save!
|
||||
|
||||
collections.each do |collection|
|
||||
expect(collection.reload).to be_sensitive
|
||||
end
|
||||
expect(report.reload).to be_action_taken
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -138,4 +138,18 @@ RSpec.describe Collection do
|
|||
expect(subject.object_type).to eq :featured_collection
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_log_human_identifier' do
|
||||
subject { Fabricate(:collection) }
|
||||
|
||||
it 'returns the account name' do
|
||||
expect(subject.to_log_human_identifier).to eq subject.account.acct
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_log_permalink' do
|
||||
it 'includes the URI of the collection' do
|
||||
expect(subject.to_log_permalink).to eq ActivityPub::TagManager.instance.uri_for(subject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
24
spec/policies/admin/collection_policy_spec.rb
Normal file
24
spec/policies/admin/collection_policy_spec.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::CollectionPolicy do
|
||||
let(:policy) { described_class }
|
||||
let(:admin) { Fabricate(:admin_user).account }
|
||||
let(:john) { Fabricate(:account) }
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
|
||||
permissions :index?, :show?, :update?, :destroy? do
|
||||
context 'with an admin' do
|
||||
it 'permits' do
|
||||
expect(policy).to permit(admin, Collection)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-admin' do
|
||||
it 'denies' do
|
||||
expect(policy).to_not permit(john, Collection)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user