mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-26 07:06:22 +00:00
feat: no permitir entrar al evento si falla la request
This commit is contained in:
parent
8f91b748ff
commit
8ff5626e99
8 changed files with 88 additions and 110 deletions
|
@ -9,14 +9,16 @@ class ActivityPubsController < ApplicationController
|
||||||
authorize activity_pub
|
authorize activity_pub
|
||||||
|
|
||||||
activity_pub.update(remote_flag_params(activity_pub)) if event == :report
|
activity_pub.update(remote_flag_params(activity_pub)) if event == :report
|
||||||
activity_pub.public_send(:"#{event}!") if activity_pub.public_send(:"may_#{event}?")
|
|
||||||
|
|
||||||
flash[:success] = I18n.t("activity_pubs.#{event}.success")
|
message =
|
||||||
rescue Exception => e
|
if activity_pub.public_send(:"may_#{event}?") && activity_pub.public_send(:"#{event}!")
|
||||||
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params.permit!.to_h })
|
:success
|
||||||
|
else
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
|
||||||
|
flash[message] = I18n.t("activity_pubs.#{event}.#{message}")
|
||||||
|
|
||||||
flash[:error] = I18n.t("activity_pubs.#{event}.error")
|
|
||||||
ensure
|
|
||||||
redirect_to_moderation_queue!
|
redirect_to_moderation_queue!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,14 +17,15 @@ class ActorModerationsController < ApplicationController
|
||||||
# Crea una RemoteFlag si se envían los parámetros adecuados
|
# Crea una RemoteFlag si se envían los parámetros adecuados
|
||||||
actor_moderation.update(remote_flag_params(actor_moderation)) if actor_event == :report
|
actor_moderation.update(remote_flag_params(actor_moderation)) if actor_event == :report
|
||||||
|
|
||||||
actor_moderation.public_send(:"#{actor_event}!") if actor_moderation.public_send(:"may_#{actor_event}?")
|
message =
|
||||||
|
if actor_moderation.public_send(:"may_#{actor_event}?") && actor_moderation.public_send(:"#{actor_event}!")
|
||||||
|
:success
|
||||||
|
else
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
|
||||||
flash[:success] = I18n.t("actor_moderations.#{actor_event}.success")
|
flash[message] = I18n.t("actor_moderations.#{actor_event}.#{message}")
|
||||||
rescue Exception => e
|
|
||||||
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params.permit!.to_h })
|
|
||||||
|
|
||||||
flash[:error] = I18n.t("actor_moderations.#{actor_event}.error")
|
|
||||||
ensure
|
|
||||||
redirect_to_moderation_queue!
|
redirect_to_moderation_queue!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,14 +8,15 @@ class InstanceModerationsController < ApplicationController
|
||||||
define_method(event) do
|
define_method(event) do
|
||||||
authorize instance_moderation
|
authorize instance_moderation
|
||||||
|
|
||||||
instance_moderation.public_send(:"#{event}!") if instance_moderation.public_send(:"may_#{event}?")
|
message =
|
||||||
|
if instance_moderation.public_send(:"may_#{event}?") && instance_moderation.public_send(:"#{event}!")
|
||||||
|
:success
|
||||||
|
else
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
|
||||||
flash[:success] = I18n.t("instance_moderations.#{event}.success")
|
flash[message] = I18n.t("instance_moderations.#{event}.#{message}")
|
||||||
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
|
||||||
|
|
|
@ -47,14 +47,19 @@ class ActivityPub < ApplicationRecord
|
||||||
# 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
|
||||||
# Le usuarie aprobó el objeto
|
# Le usuarie aprobó el objeto
|
||||||
state :approved
|
state :approved, before_enter: :allow_remotely!
|
||||||
# Le usuarie rechazó el objeto
|
# Le usuarie rechazó el objeto
|
||||||
state :rejected
|
state :rejected, before_enter: :reject_remotely!
|
||||||
# Le usuarie reportó el objeto
|
# Le usuarie reportó el objeto
|
||||||
state :reported
|
state :reported
|
||||||
# Le actore eliminó el objeto
|
# Le actore eliminó el objeto
|
||||||
state :removed
|
state :removed
|
||||||
|
|
||||||
|
# Gestionar todos los errores
|
||||||
|
error_on_all_events do |e|
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, activity_pub: self.id, activity: activities.first.uri })
|
||||||
|
end
|
||||||
|
|
||||||
# Se puede volver a pausa en caso de actualización remota, para
|
# Se puede volver a pausa en caso de actualización remota, para
|
||||||
# revisar los cambios.
|
# revisar los cambios.
|
||||||
event :pause do
|
event :pause do
|
||||||
|
@ -67,7 +72,7 @@ class ActivityPub < ApplicationRecord
|
||||||
event :remove do
|
event :remove do
|
||||||
transitions to: :removed
|
transitions to: :removed
|
||||||
|
|
||||||
before do
|
after do
|
||||||
next if object.blank?
|
next if object.blank?
|
||||||
|
|
||||||
object.update(content: {}) unless object.content.empty?
|
object.update(content: {}) unless object.content.empty?
|
||||||
|
@ -79,26 +84,18 @@ class ActivityPub < ApplicationRecord
|
||||||
# webhook a modo de confirmación.
|
# webhook a modo de confirmación.
|
||||||
event :approve do
|
event :approve do
|
||||||
transitions from: %i[paused], to: :approved
|
transitions from: %i[paused], to: :approved
|
||||||
|
|
||||||
before do
|
|
||||||
allow_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# La actividad fue rechazada
|
# La actividad fue rechazada
|
||||||
event :reject do
|
event :reject do
|
||||||
transitions from: %i[paused], to: :rejected
|
transitions from: %i[paused], to: :rejected
|
||||||
|
|
||||||
before do
|
|
||||||
reject_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Solo podemos reportarla luego de rechazarla
|
# Solo podemos reportarla luego de rechazarla
|
||||||
event :report do
|
event :report do
|
||||||
transitions from: :rejected, to: :reported
|
transitions from: :rejected, to: :reported
|
||||||
|
|
||||||
before do
|
after do
|
||||||
ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting?
|
ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
# Mantiene la relación entre Site y Actor
|
# Mantiene la relación entre Site y Actor
|
||||||
class ActorModeration < ApplicationRecord
|
class ActorModeration < ApplicationRecord
|
||||||
IGNORED_EVENTS = %i[remove]
|
IGNORED_EVENTS = %i[remove].freeze
|
||||||
IGNORED_STATES = %i[removed]
|
IGNORED_STATES = %i[removed].freeze
|
||||||
|
|
||||||
include AASM
|
include AASM
|
||||||
|
|
||||||
|
@ -14,38 +14,30 @@ class ActorModeration < ApplicationRecord
|
||||||
accepts_nested_attributes_for :remote_flag
|
accepts_nested_attributes_for :remote_flag
|
||||||
|
|
||||||
aasm do
|
aasm do
|
||||||
state :paused, initial: true
|
state :paused, initial: true, before_enter: :pause_remotely!
|
||||||
state :allowed
|
state :allowed, before_enter: :allow_remotely!
|
||||||
state :blocked
|
state :blocked, before_enter: :block_remotely!
|
||||||
state :reported
|
state :reported
|
||||||
state :removed
|
state :removed
|
||||||
|
|
||||||
|
error_on_all_events do |e|
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, actor: actor.uri, actor_moderation: id })
|
||||||
|
end
|
||||||
|
|
||||||
event :pause do
|
event :pause do
|
||||||
transitions from: %i[allowed blocked reported], to: :paused
|
transitions from: %i[allowed blocked reported], to: :paused
|
||||||
|
|
||||||
before do
|
|
||||||
pause_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al permitir una cuenta no se permiten todos los comentarios
|
# Al permitir una cuenta no se permiten todos los comentarios
|
||||||
# pendientes de moderación que ya hizo.
|
# pendientes de moderación que ya hizo.
|
||||||
event :allow do
|
event :allow do
|
||||||
transitions from: %i[paused blocked reported], to: :allowed
|
transitions from: %i[paused blocked reported], to: :allowed
|
||||||
|
|
||||||
before do
|
|
||||||
allow_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al bloquear una cuenta no se bloquean todos los comentarios
|
# Al bloquear una cuenta no se bloquean todos los comentarios
|
||||||
# pendientes de moderación que hizo.
|
# pendientes de moderación que hizo.
|
||||||
event :block do
|
event :block do
|
||||||
transitions from: %i[paused allowed], to: :blocked
|
transitions from: %i[paused allowed], to: :blocked
|
||||||
|
|
||||||
before do
|
|
||||||
block_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al reportar, necesitamos asociar una RemoteFlag para poder
|
# Al reportar, necesitamos asociar una RemoteFlag para poder
|
||||||
|
@ -53,7 +45,7 @@ class ActorModeration < ApplicationRecord
|
||||||
event :report do
|
event :report do
|
||||||
transitions from: %i[blocked], to: :reported
|
transitions from: %i[blocked], to: :reported
|
||||||
|
|
||||||
before do
|
after do
|
||||||
ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting?
|
ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -63,8 +55,8 @@ class ActorModeration < ApplicationRecord
|
||||||
event :remove do
|
event :remove do
|
||||||
transitions to: :removed
|
transitions to: :removed
|
||||||
|
|
||||||
before do
|
after do
|
||||||
site.activity_pubs.where(actor_id: self.actor_id).remove_all!
|
site.activity_pubs.where(actor_id: actor_id).remove_all!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ module AasmEventsConcern
|
||||||
#
|
#
|
||||||
# @return [Array<Symbol>]
|
# @return [Array<Symbol>]
|
||||||
def self.transitionable_events(current_state)
|
def self.transitionable_events(current_state)
|
||||||
self.events.select do |event|
|
events.select do |event|
|
||||||
aasm.events.find { |x| x.name == event }.transitions_from_state? current_state
|
aasm.events.find { |x| x.name == event }.transitions_from_state? current_state
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -32,19 +32,15 @@ module AasmEventsConcern
|
||||||
# scope actual.
|
# scope actual.
|
||||||
#
|
#
|
||||||
# @return [Bool] Si hubo al menos un error, devuelve false.
|
# @return [Bool] Si hubo al menos un error, devuelve false.
|
||||||
self.aasm.events.map(&:name).each do |event|
|
aasm.events.map(&:name).each do |event|
|
||||||
define_singleton_method(:"#{event}_all!") do
|
define_singleton_method(:"#{event}_all!") do
|
||||||
success = true
|
successes = []
|
||||||
|
|
||||||
self.find_each do |object|
|
find_each do |object|
|
||||||
object.public_send(:"#{event}!") if object.public_send(:"may_#{event}?")
|
successes << (object.public_send(:"may_#{event}?") && object.public_send(:"#{event}!"))
|
||||||
rescue Exception => e
|
|
||||||
success = false
|
|
||||||
|
|
||||||
notify_exception! e, object
|
|
||||||
end
|
end
|
||||||
|
|
||||||
success
|
successes.all?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ejecuta la transición del evento en la base de datos sin
|
# Ejecuta la transición del evento en la base de datos sin
|
||||||
|
@ -53,20 +49,13 @@ module AasmEventsConcern
|
||||||
#
|
#
|
||||||
# @return [Integer] Registros modificados
|
# @return [Integer] Registros modificados
|
||||||
define_singleton_method(:"#{event}_all_without_callbacks!") do
|
define_singleton_method(:"#{event}_all_without_callbacks!") do
|
||||||
aasm_event = self.aasm.events.find { |e| e.name == event }
|
aasm_event = aasm.events.find { |e| e.name == event }
|
||||||
to_state = aasm_event.transitions.map(&:to).first
|
to_state = aasm_event.transitions.map(&:to).first
|
||||||
from_states = aasm_event.transitions.map(&:from)
|
from_states = aasm_event.transitions.map(&:from)
|
||||||
|
|
||||||
self.unscope(where: :aasm_state).where(aasm_state: from_states).update_all(aasm_state: to_state, updated_at: Time.now)
|
unscope(where: :aasm_state).where(aasm_state: from_states).update_all(aasm_state: to_state,
|
||||||
|
updated_at: Time.now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Envía notificación de errores
|
|
||||||
#
|
|
||||||
# @param exception [Exception]
|
|
||||||
# @param record [ApplicationRecord]
|
|
||||||
def self.notify_exception!(exception, record)
|
|
||||||
ExceptionNotifier.notify_exception(exception, data: { record_type: record.class.name, record_id: record.id })
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,20 +20,15 @@ class FediblockState < ApplicationRecord
|
||||||
# Aunque queramos las listas habilitadas por defecto, tenemos que
|
# Aunque queramos las listas habilitadas por defecto, tenemos que
|
||||||
# habilitarlas luego de crearlas para poder generar la lista de
|
# habilitarlas luego de crearlas para poder generar la lista de
|
||||||
# bloqueo en la Social Inbox.
|
# bloqueo en la Social Inbox.
|
||||||
state :disabled, initial: true
|
state :disabled, initial: true, before_enter: :disable_remotely_and_pause_instances!
|
||||||
state :enabled
|
state :enabled, before_enter: :enable_remotely_and_block_instances!
|
||||||
|
|
||||||
|
error_on_all_events do |e|
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, fediblock: id })
|
||||||
|
end
|
||||||
|
|
||||||
event :enable do
|
event :enable do
|
||||||
transitions from: :disabled, to: :enabled
|
transitions from: :disabled, to: :enabled
|
||||||
|
|
||||||
before do
|
|
||||||
# Bloquear todos las instancias de este Fediblock
|
|
||||||
enable_remotely! list_names(fediblock.hostnames)
|
|
||||||
|
|
||||||
# Luego esta tarea crea las que falten e ignora las que ya se
|
|
||||||
# bloquearon.
|
|
||||||
ActivityPub::InstanceModerationJob.perform_now(site: site, hostnames: fediblock.hostnames, perform_remotely: false)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al deshabilitar, las listas pasan a modo pausa, a menos que estén
|
# Al deshabilitar, las listas pasan a modo pausa, a menos que estén
|
||||||
|
@ -44,22 +39,31 @@ class FediblockState < ApplicationRecord
|
||||||
# de list_names
|
# de list_names
|
||||||
event :disable do
|
event :disable do
|
||||||
transitions from: :enabled, to: :disabled
|
transitions from: :enabled, to: :disabled
|
||||||
|
|
||||||
before do
|
|
||||||
# Deshabilitar todas las instancias que no estén habilitadas por
|
|
||||||
# otros fediblocks
|
|
||||||
disable_remotely! list_names(unique_hostnames)
|
|
||||||
|
|
||||||
# Pausar todas las moderaciones de las instancias que no estén
|
|
||||||
# bloqueadas por otros fediblocks.
|
|
||||||
instance_ids = ActivityPub::Instance.where(hostname: unique_hostnames).ids
|
|
||||||
site.instance_moderations.where(instance_id: instance_ids).pause_all_without_callbacks!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def enable_remotely_and_block_instances!
|
||||||
|
# Bloquear todos las instancias de este Fediblock
|
||||||
|
enable_remotely! list_names(fediblock.hostnames)
|
||||||
|
|
||||||
|
# Luego esta tarea crea las que falten e ignora las que ya se
|
||||||
|
# bloquearon.
|
||||||
|
ActivityPub::InstanceModerationJob.perform_now(site: site, hostnames: fediblock.hostnames, perform_remotely: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable_remotely_and_pause_instances!
|
||||||
|
# Deshabilitar todas las instancias que no estén habilitadas por
|
||||||
|
# otros fediblocks
|
||||||
|
disable_remotely! list_names(unique_hostnames)
|
||||||
|
|
||||||
|
# Pausar todas las moderaciones de las instancias que no estén
|
||||||
|
# bloqueadas por otros fediblocks.
|
||||||
|
instance_ids = ActivityPub::Instance.where(hostname: unique_hostnames).ids
|
||||||
|
site.instance_moderations.where(instance_id: instance_ids).pause_all_without_callbacks!
|
||||||
|
end
|
||||||
|
|
||||||
# Devuelve los hostnames únicos a esta instancia.
|
# Devuelve los hostnames únicos a esta instancia.
|
||||||
#
|
#
|
||||||
# @return [Array<String>]
|
# @return [Array<String>]
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
# Mantiene el registro de relaciones entre sitios e instancias
|
# Mantiene el registro de relaciones entre sitios e instancias
|
||||||
class InstanceModeration < ApplicationRecord
|
class InstanceModeration < ApplicationRecord
|
||||||
IGNORED_EVENTS = []
|
IGNORED_EVENTS = [].freeze
|
||||||
IGNORED_STATES = []
|
IGNORED_STATES = [].freeze
|
||||||
|
|
||||||
include AASM
|
include AASM
|
||||||
|
|
||||||
|
@ -11,38 +11,30 @@ class InstanceModeration < ApplicationRecord
|
||||||
belongs_to :instance, class_name: 'ActivityPub::Instance'
|
belongs_to :instance, class_name: 'ActivityPub::Instance'
|
||||||
|
|
||||||
aasm do
|
aasm do
|
||||||
state :paused, initial: true
|
state :paused, initial: true, before_enter: :pause_remotely!
|
||||||
state :allowed
|
state :allowed, before_enter: :allow_remotely!
|
||||||
state :blocked
|
state :blocked, before_enter: :block_remotely!
|
||||||
|
|
||||||
|
error_on_all_events do |e|
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, instance: instance.hostname, instance_moderation: id })
|
||||||
|
end
|
||||||
|
|
||||||
# Al volver la instancia a pausa no cambiamos el estado de
|
# Al volver la instancia a pausa no cambiamos el estado de
|
||||||
# moderación de actores pre-existente.
|
# 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
|
||||||
|
|
||||||
before do
|
|
||||||
pause_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al permitir, solo bloqueamos la instancia, sin modificar el estado
|
# Al permitir, solo bloqueamos la instancia, sin modificar el estado
|
||||||
# de les actores y comentarios retroactivamente.
|
# de les actores y comentarios retroactivamente.
|
||||||
event :allow do
|
event :allow do
|
||||||
transitions from: %i[paused blocked], to: :allowed
|
transitions from: %i[paused blocked], to: :allowed
|
||||||
|
|
||||||
before do
|
|
||||||
allow_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Al bloquear, solo bloqueamos la instancia, sin modificar el estado
|
# Al bloquear, solo bloqueamos la instancia, sin modificar el estado
|
||||||
# de les actores y comentarios retroactivamente.
|
# de les actores y comentarios retroactivamente.
|
||||||
event :block do
|
event :block do
|
||||||
transitions from: %i[paused allowed], to: :blocked
|
transitions from: %i[paused allowed], to: :blocked
|
||||||
|
|
||||||
before do
|
|
||||||
block_remotely!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -51,7 +43,7 @@ class InstanceModeration < ApplicationRecord
|
||||||
|
|
||||||
# @return [Array<String>]
|
# @return [Array<String>]
|
||||||
def actor_ids
|
def actor_ids
|
||||||
ActivityPub::Actor.where(instance_id: self.instance_id).ids
|
ActivityPub::Actor.where(instance_id: instance_id).ids
|
||||||
end
|
end
|
||||||
|
|
||||||
# Elimina la instancia de todas las listas
|
# Elimina la instancia de todas las listas
|
||||||
|
|
Loading…
Reference in a new issue