2024-02-20 17:44:52 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# = ActivityPub =
|
|
|
|
#
|
|
|
|
# El registro de actividades recibidas y su estado. Cuando recibimos
|
|
|
|
# una actividad, puede estar destinada a varies actores dentro de Sutty,
|
|
|
|
# con lo que generamos una cola para cada une.
|
|
|
|
#
|
|
|
|
# @see {https://www.w3.org/TR/activitypub/#client-to-server-interactions}
|
|
|
|
class ActivityPub < ApplicationRecord
|
2024-03-15 17:26:12 +00:00
|
|
|
IGNORED_EVENTS = %i[pause remove].freeze
|
|
|
|
IGNORED_STATES = %i[removed].freeze
|
2024-02-20 17:44:52 +00:00
|
|
|
|
2024-03-12 17:24:38 +00:00
|
|
|
include AASM
|
|
|
|
|
2024-02-26 13:39:00 +00:00
|
|
|
belongs_to :instance
|
2024-02-20 17:44:52 +00:00
|
|
|
belongs_to :site
|
|
|
|
belongs_to :object, polymorphic: true
|
2024-03-04 14:59:29 +00:00
|
|
|
belongs_to :actor
|
2024-03-06 18:36:00 +00:00
|
|
|
belongs_to :remote_flag, optional: true, class_name: 'ActivityPub::RemoteFlag'
|
2024-02-20 17:44:52 +00:00
|
|
|
has_many :activities
|
|
|
|
|
|
|
|
validates :site_id, presence: true
|
|
|
|
validates :object_id, presence: true
|
2024-02-21 20:04:39 +00:00
|
|
|
validates :aasm_state, presence: true, inclusion: { in: %w[paused approved rejected reported removed] }
|
2024-02-20 17:44:52 +00:00
|
|
|
|
2024-03-05 17:18:06 +00:00
|
|
|
accepts_nested_attributes_for :remote_flag
|
|
|
|
|
2024-02-23 15:54:31 +00:00
|
|
|
# Encuentra la URI de un objeto
|
|
|
|
#
|
|
|
|
# @return [String, nil]
|
|
|
|
def self.uri_from_object(object)
|
|
|
|
case object
|
2024-03-01 20:29:08 +00:00
|
|
|
when Array then uri_from_object(object.first)
|
2024-02-23 15:54:31 +00:00
|
|
|
when String then object
|
2024-03-01 20:29:08 +00:00
|
|
|
when Hash then (object['id'] || object[:id])
|
2024-02-23 15:54:31 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-02-20 17:44:52 +00:00
|
|
|
aasm do
|
|
|
|
# Todavía no hay una decisión sobre el objeto
|
|
|
|
state :paused, initial: true
|
|
|
|
# Le usuarie aprobó el objeto
|
|
|
|
state :approved
|
|
|
|
# Le usuarie rechazó el objeto
|
|
|
|
state :rejected
|
|
|
|
# Le usuarie reportó el objeto
|
|
|
|
state :reported
|
|
|
|
# Le actore eliminó el objeto
|
2024-02-21 18:44:41 +00:00
|
|
|
state :removed
|
2024-02-20 20:15:57 +00:00
|
|
|
|
2024-03-14 20:08:38 +00:00
|
|
|
# Se puede volver a pausa en caso de actualización remota, para
|
|
|
|
# revisar los cambios.
|
|
|
|
event :pause do
|
|
|
|
transitions to: :paused
|
|
|
|
end
|
|
|
|
|
2024-02-20 20:15:57 +00:00
|
|
|
# Recibir una acción de eliminación, eliminar el contenido de la
|
|
|
|
# base de datos. Esto elimina el contenido para todos los sitios
|
|
|
|
# porque estamos respetando lo que pidió le actore.
|
2024-02-21 18:44:41 +00:00
|
|
|
event :remove do
|
|
|
|
transitions to: :removed
|
2024-02-20 20:15:57 +00:00
|
|
|
|
2024-02-21 19:42:28 +00:00
|
|
|
before do
|
2024-03-13 18:52:33 +00:00
|
|
|
next if object.blank?
|
|
|
|
|
2024-02-21 20:05:17 +00:00
|
|
|
object.update(content: {}) unless object.content.empty?
|
2024-02-20 20:15:57 +00:00
|
|
|
end
|
|
|
|
end
|
2024-02-20 20:18:15 +00:00
|
|
|
|
2024-03-04 19:46:43 +00:00
|
|
|
# La actividad se aprueba, informándole a la Social Inbox que está
|
|
|
|
# aprobada. También recibimos la aprobación via
|
|
|
|
# webhook a modo de confirmación.
|
2024-02-21 16:04:15 +00:00
|
|
|
event :approve do
|
2024-03-04 19:52:28 +00:00
|
|
|
transitions from: %i[paused], to: :approved
|
2024-03-04 19:46:43 +00:00
|
|
|
|
|
|
|
before do
|
2024-03-08 18:55:01 +00:00
|
|
|
allow_remotely!
|
2024-03-04 19:46:43 +00:00
|
|
|
end
|
2024-02-20 20:18:15 +00:00
|
|
|
end
|
2024-02-21 16:06:06 +00:00
|
|
|
|
|
|
|
# La actividad fue rechazada
|
|
|
|
event :reject do
|
2024-02-22 21:42:20 +00:00
|
|
|
transitions from: %i[paused approved], to: :rejected
|
2024-03-04 19:46:43 +00:00
|
|
|
|
|
|
|
before do
|
2024-03-08 18:55:01 +00:00
|
|
|
reject_remotely!
|
2024-03-04 19:46:43 +00:00
|
|
|
end
|
2024-02-21 16:06:06 +00:00
|
|
|
end
|
2024-02-22 21:42:36 +00:00
|
|
|
|
|
|
|
# Solo podemos reportarla luego de rechazarla
|
|
|
|
event :report do
|
|
|
|
transitions from: :rejected, to: :reported
|
2024-03-05 17:18:06 +00:00
|
|
|
|
|
|
|
before do
|
2024-03-05 19:00:47 +00:00
|
|
|
ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting?
|
2024-03-05 17:18:06 +00:00
|
|
|
end
|
2024-02-22 21:42:36 +00:00
|
|
|
end
|
2024-02-20 17:44:52 +00:00
|
|
|
end
|
2024-03-08 18:55:01 +00:00
|
|
|
|
2024-03-13 14:15:31 +00:00
|
|
|
# Definir eventos en masa
|
|
|
|
include AasmEventsConcern
|
|
|
|
|
2024-03-14 20:08:55 +00:00
|
|
|
# Lo que tenemos que aprobar o rechazar es la última actividad
|
|
|
|
# disponible, que según el scope por defecto, va a ser la primera de
|
|
|
|
# la lista.
|
2024-03-08 18:55:01 +00:00
|
|
|
def reject_remotely!
|
2024-03-14 20:08:55 +00:00
|
|
|
raise unless site.social_inbox.inbox.reject(id: activities.first.uri).ok?
|
2024-03-08 18:55:01 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def allow_remotely!
|
2024-03-14 20:08:55 +00:00
|
|
|
raise unless site.social_inbox.inbox.accept(id: activities.first.uri).ok?
|
2024-03-08 18:55:01 +00:00
|
|
|
end
|
2024-02-20 17:44:52 +00:00
|
|
|
end
|