5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-23 04:06:21 +00:00

feat: modificar el estado de moderación en masa #15328 #15327

This commit is contained in:
f 2024-03-12 13:57:31 -03:00
parent 522cef8c9a
commit bf75d50cc3
No known key found for this signature in database
10 changed files with 88 additions and 118 deletions

View file

@ -27,7 +27,7 @@ class ActivityPubsController < ApplicationController
authorize activity_pubs authorize activity_pubs
action = params[:activity_pub_action].to_sym action = params[:activity_pub_action].to_sym
method = :"#{action}!" method = :"#{action}_all!"
may = :"may_#{action}?" may = :"may_#{action}?"
redirect_to_moderation_queue! redirect_to_moderation_queue!
@ -35,6 +35,7 @@ class ActivityPubsController < ApplicationController
return unless ActivityPub.events.include? action return unless ActivityPub.events.include? action
# Crear una sola remote flag por autore # Crear una sola remote flag por autore
ActivityPub.transaction do
if action == :report if action == :report
message = remote_flag_params(activity_pubs.first).dig(:remote_flag_attributes, :message) message = remote_flag_params(activity_pubs.first).dig(:remote_flag_attributes, :message)
@ -50,21 +51,9 @@ class ActivityPubsController < ApplicationController
end end
end end
ActivityPub.transaction do message = activity_pubs.public_send(method) ? :success : :error
activity_pubs.find_each do |activity_pub|
next unless activity_pub.public_send(may)
activity_pub.public_send(method) flash[message] = I18n.t("activity_pubs.action_on_several.#{message}")
flash[:success] = I18n.t('activity_pubs.action_on_several.success')
rescue Exception => e
ExceptionNotifier.notify_exception(e,
data: { site: site.name, params: params.permit!.to_h,
activity_pub: activity_pub.id })
flash.delete(:success)
flash[:error] = I18n.t('activity_pubs.action_on_several.error')
end
end end
end end

View file

@ -37,7 +37,7 @@ class ActorModerationsController < ApplicationController
authorize actor_moderations authorize actor_moderations
action = params[:actor_moderation_action].to_sym action = params[:actor_moderation_action].to_sym
method = :"#{action}!" method = :"#{action}_all!"
may = :"may_#{action}?" may = :"may_#{action}?"
redirect_to_moderation_queue! redirect_to_moderation_queue!
@ -45,21 +45,18 @@ class ActorModerationsController < ApplicationController
return unless ActorModeration.events.include? action return unless ActorModeration.events.include? action
ActorModeration.transaction do ActorModeration.transaction do
if action == :report
actor_moderations.find_each do |actor_moderation| actor_moderations.find_each do |actor_moderation|
next unless actor_moderation.public_send(may) next unless actor_moderation.public_send(may)
actor_moderation.update(actor_moderation_params(actor_moderation)) if action == :report actor_moderation.update(actor_moderation_params(actor_moderation))
actor_moderation.public_send(method)
flash[:success] = I18n.t('actor_moderations.action_on_several.success')
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params.permit!.to_h })
flash.delete(:success)
flash[:error] = I18n.t('actor_moderations.action_on_several.error')
end end
end end
message = actor_moderation.public_send(method) ? :success : :error
flash[message] = I18n.t("actor_moderations.action_on_several.#{message}")
end
end end
private private

View file

@ -10,6 +10,12 @@ class InstanceModerationsController < ApplicationController
instance_moderation.public_send(:"#{event}!") if instance_moderation.public_send(:"may_#{event}?") instance_moderation.public_send(:"#{event}!") if instance_moderation.public_send(:"may_#{event}?")
flash[:success] = I18n.t("instance_moderations.#{event}.success")
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params.permit!.to_h })
flash[:error] = I18n.t("instance_moderations.#{event}.error")
ensure
redirect_to_moderation_queue! redirect_to_moderation_queue!
end end
end end
@ -20,17 +26,16 @@ class InstanceModerationsController < ApplicationController
authorize instance_moderations authorize instance_moderations
action = params[:instance_moderation_action].to_sym action = params[:instance_moderation_action].to_sym
method = :"#{action}!" method = :"#{action}_all!"
may = :"may_#{action}?"
redirect_to_moderation_queue! redirect_to_moderation_queue!
return unless InstanceModeration.events.include? action return unless InstanceModeration.events.include? action
InstanceModeration.transaction do InstanceModeration.transaction do
instance_moderations.find_each do |instance_moderation| message = instance_moderations.public_send(method) ? :success : :error
instance_moderation.public_send(method) if instance_moderation.public_send(may)
end flash[:message] = I18n.t("instance_moderations.action_on_several.#{message}")
end end
end end

View file

@ -14,7 +14,6 @@ class ActivityPub
end end
instances = ActivityPub::Instance.where(hostname: hostnames) instances = ActivityPub::Instance.where(hostname: hostnames)
success = true
Site.transaction do Site.transaction do
# Crea todas las moderaciones de instancia con un estado por # Crea todas las moderaciones de instancia con un estado por
@ -22,17 +21,11 @@ class ActivityPub
instances.find_each do |instance| instances.find_each do |instance|
# Esto bloquea cada una individualmente en la Social Inbox, # Esto bloquea cada una individualmente en la Social Inbox,
# idealmente son pocas instancias las que aparecen. # idealmente son pocas instancias las que aparecen.
site.instance_moderations.find_or_create_by(instance: instance).tap do |instance_moderation| site.instance_moderations.find_or_create_by(instance: instance)
instance_moderation.block! if instance_moderation.may_block?
# Notificar todos los errores sin detener la ejecución
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { site: site.name, instance_moderation: instance_moderation.id })
success = false
end
end
end end
success site.instance_moderations.where(instance_id: instances.ids).block_all!
end
end end
end end
end end

View file

@ -38,28 +38,6 @@ class ActivityPub < ApplicationRecord
end end
end end
# Permite todos los comentarios. No podemos hacer acciones en masa
# sobre comentarios en la Social Inbox, con lo que tenemos que
# comunicarnos individualmente.
def self.allow_all!
self.find_each do |activity_pub|
activity_pub.allow! if activity_pub.may_allow?
rescue Exception => e
notify_exception!(e, activity_pub)
end
end
# Rechaza todos los comentarios. No podemos hacer acciones en masa
# sobre comentarios en la Social Inbox, con lo que tenemos que
# comunicarnos individualmente.
def self.reject_all!
self.find_each do |activity_pub|
activity_pub.reject! if activity_pub.may_reject?
rescue Exception => e
notify_exception!(e, activity_pub)
end
end
aasm do aasm do
# Todavía no hay una decisión sobre el objeto # Todavía no hay una decisión sobre el objeto
state :paused, initial: true state :paused, initial: true

View file

@ -14,19 +14,6 @@ class ActorModeration < ApplicationRecord
accepts_nested_attributes_for :remote_flag accepts_nested_attributes_for :remote_flag
# Bloquea todes les Actores bloqueables
def self.block_all!
self.update_all(aasm_state: 'blocked', updated_at: Time.now)
end
def self.pause_all!
self.update_all(aasm_state: 'paused', updated_at: Time.now)
end
def self.remove_all!
self.update_all(aasm_state: 'removed', updated_at: Time.now)
end
aasm do aasm do
state :paused, initial: true state :paused, initial: true
state :allowed state :allowed

View file

@ -28,6 +28,26 @@ module AasmEventsConcern
aasm.states.map(&:name) - self::IGNORED_STATES aasm.states.map(&:name) - self::IGNORED_STATES
end end
# Define un método que cambia el estado para todos los objetos del
# scope actual.
#
# @return [Bool] Si hubo al menos un error, devuelve false.
self.events.each do |event|
define_singleton_method(:"#{event}_all!") do
success = true
self.find_each do |object|
object.public_send(:"#{event}!") if object.public_send(:"may_#{event}?")
rescue Exception => e
success = false
notify_exception! e, object
end
success
end
end
# Envía notificación de errores # Envía notificación de errores
# #
# @param exception [Exception] # @param exception [Exception]

View file

@ -39,12 +39,6 @@ class FediblockState < ApplicationRecord
# Luego esta tarea crea las que falten e ignora las que ya se # Luego esta tarea crea las que falten e ignora las que ya se
# bloquearon. # bloquearon.
ActivityPub::InstanceModerationJob.perform_now(site: site, hostnames: fediblock.hostnames) ActivityPub::InstanceModerationJob.perform_now(site: site, hostnames: fediblock.hostnames)
# Bloquear a todes les Actores de las instancias bloqueadas para
# indicarle a le usuarie que les tiene que desbloquear
# manualmente.
actor_ids = ActivityPub::Actor.where(instance_id: instance_ids).ids
ActorModeration.where(actor_id: actor_ids).paused.block_all!
end end
end end
@ -66,12 +60,6 @@ class FediblockState < ApplicationRecord
# bloqueadas por otros fediblocks. # bloqueadas por otros fediblocks.
instance_ids = ActivityPub::Instance.where(hostname: unique_hostnames).ids instance_ids = ActivityPub::Instance.where(hostname: unique_hostnames).ids
site.instance_moderations.where(instance_id: instance_ids).pause_all! site.instance_moderations.where(instance_id: instance_ids).pause_all!
# Volver a pausar todes les actores de esta instancia que fueron
# bloqueades, a menos que hayan sido bloqueades por otro
# fediblock.
actor_ids = ActivityPub::Actor.where(instance_id: instance_ids).ids
ActorModeration.where(actor_id: actor_ids).blocked.pause_all!
end end
end end
end end

View file

@ -11,26 +11,13 @@ class InstanceModeration < ApplicationRecord
belongs_to :site belongs_to :site
belongs_to :instance, class_name: 'ActivityPub::Instance' belongs_to :instance, class_name: 'ActivityPub::Instance'
# Traer todas las instancias bloqueables, según la máquina de estados,
# todas las que no estén bloqueadas ya.
scope :may_block, -> { where.not(aasm_state: 'blocked') }
scope :may_pause, -> { where.not(aasm_state: 'paused') }
# Bloquear instancias en masa
def self.block_all!
self.may_block.update_all(aasm_state: 'blocked', updated_at: Time.now)
end
# Pausar instancias en masa
def self.pause_all!
self.may_pause.update_all(aasm_state: 'paused', updated_at: Time.now)
end
aasm do aasm do
state :paused, initial: true state :paused, initial: true
state :allowed state :allowed
state :blocked state :blocked
# Al volver la instancia a pausa no cambiamos el estado de
# moderación de actores pre-existente.
event :pause do event :pause do
transitions from: %i[allowed blocked], to: :paused transitions from: %i[allowed blocked], to: :paused
@ -39,23 +26,36 @@ class InstanceModeration < ApplicationRecord
end end
end end
# Al permitir, también permitimos todes les actores que no hayan
# tenido acciones de moderación.
event :allow do event :allow do
transitions from: %i[paused blocked], to: :allowed transitions from: %i[paused blocked], to: :allowed
before do before do
allow_remotely! allow_remotely!
site.actor_moderations.paused.where(actor_id: actor_ids).allow_all!
end end
end end
# Al bloquear, también bloqueamos a todes les actores que no hayan
# tenido acciones de moderación.
event :block do event :block do
transitions from: %i[paused allowed], to: :blocked transitions from: %i[paused allowed], to: :blocked
before do before do
block_remotely! block_remotely!
site.actor_moderations.paused.where(actor_id: actor_ids).block_all!
end end
end end
end end
# @return [Array<String>]
def actor_ids
ActivityPub::Actor.where(instance_id: self.instance_id).ids
end
# Elimina la instancia de todas las listas # Elimina la instancia de todas las listas
# #
# @return [Boolean] # @return [Boolean]

View file

@ -145,6 +145,19 @@ es:
report: report:
success: "Cuenta reportada a su instancia." success: "Cuenta reportada a su instancia."
error: "No se pudo reportar la cuenta. Hemos recibido el reporte y lo estaremos verificando." error: "No se pudo reportar la cuenta. Hemos recibido el reporte y lo estaremos verificando."
instance_moderations:
action_on_several:
success: "Se ha modificado el estado de moderación de varias instancias. Podés encontrarlas usando los filtros en la sección Instancias."
error: "Hubo un error al modificar el estado de moderación de varias instancias. Hemos recibido el reporte y lo estaremos verificando."
pause:
success: "Instancia pausada. Todos los comentarios y cuentas de esta instancia necesitan ser aprobados manualmente. No se ha modificado el estado de moderación de cuentas y comentarios pre-existentes."
error: "No se pudo pausar la instancia. Hemos recibido el reporte y lo estaremos verificando."
allow:
success: "Instancia permitida. Todos los comentarios y cuentas pendientes de moderación fueron aprobados y los próximos serán aprobados inmediatamente."
error: "No se pudo permitir la instancia. Hemos recibido el reporte y lo estaremos verificando."
block:
success: "Instancia bloqueada. Todos los comentarios y cuentas serán rechazados inmediatamente. Todos los comentarios y cuentas pendientes de moderación fueron rechazados."
error: "No se pudo bloquear la instancia. Hemos recibido el reporte y lo estaremos verificando."
fediblock_states: fediblock_states:
action_on_several: action_on_several:
success: "Se habilitaron las listas de bloqueo, podés encontrar las instancias filtrando por Bloqueadas. Todas las cuentas de estas instancias pendientes de moderación han sido bloqueadas. Podés activarlas individualmente en la sección Cuentas." success: "Se habilitaron las listas de bloqueo, podés encontrar las instancias filtrando por Bloqueadas. Todas las cuentas de estas instancias pendientes de moderación han sido bloqueadas. Podés activarlas individualmente en la sección Cuentas."