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

feat: enviar reportes remotos

This commit is contained in:
f 2024-03-01 15:04:07 -03:00
parent 6c61aec60e
commit 67d9731b1e
No known key found for this signature in database
9 changed files with 146 additions and 16 deletions

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Api
module V1
module ActivityPub
# Devuelve los reportes remotos hechos
#
# @todo Verificar la firma. Por ahora no es necesario porque no es
# posible obtener remotamente todos los reportes y se identifican por
# UUIDv4.
class RemoteFlagsController < BaseController
skip_forgery_protection
def show
render json: (remote_flag&.content || {}), content_type: 'application/activity+json'
end
private
# @return [ActivityPub::RemoteFlag,nil]
def remote_flag
@remote_flag ||= ::ActivityPub::RemoteFlag.find(params[:id])
end
end
end
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
# Envía un reporte directamente a la instancia remota
#
# @todo El panel debería ser su propia instancia y firmar sus propios
# mensajes.
# @todo Como la Social Inbox no soporta enviar actividades
# a destinataries que no sean seguidores, enviamos el reporte
# directamente a la instancia.
# @see {https://github.com/hyphacoop/social.distributed.press/issues/14}
class ActivityPub
class RemoteFlagJob < ApplicationJob
self.priority = 30
def perform(remote_flag:)
client = remote_flag.site.social_inbox.client_for(remote_flag.actor.content['inbox'])
response = client.post(endpoint: '', body: remote_flag.content)
raise 'No se pudo enviar el reporte' unless response.ok?
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { remote_flag: remote_flag.id, response: response.parsed_response })
raise
end
end
end

View file

@ -13,6 +13,7 @@ class ActivityPub
has_many :actor_moderation has_many :actor_moderation
has_many :activity_pubs, as: :object has_many :activity_pubs, as: :object
has_many :activities has_many :activities
has_many :remote_flags
# Obtiene el nombre de la Actor como mención, solo si obtuvimos el # Obtiene el nombre de la Actor como mención, solo si obtuvimos el
# contenido de antemano. # contenido de antemano.

View file

@ -58,13 +58,6 @@ class DeploySocialDistributedPress < Deploy
private private
# Obtiene el hostname de la API de Sutty
#
# @return [String]
def api_hostname
Rails.application.routes.default_url_options[:host].sub('panel', 'api')
end
# Crea los hooks en la Social Inbox para que nos avise de actividades # Crea los hooks en la Social Inbox para que nos avise de actividades
# nuevas # nuevas
# #
@ -80,7 +73,7 @@ class DeploySocialDistributedPress < Deploy
webhook_class.new.call({ webhook_class.new.call({
method: 'POST', method: 'POST',
url: Rails.application.routes.url_helpers.public_send( url: Rails.application.routes.url_helpers.public_send(
event_url, site_id: site.name, host: api_hostname event_url, site_id: site.name, host: site.social_inbox_hostname
), ),
headers: { headers: {
'X-Social-Inbox': rol.token 'X-Social-Inbox': rol.token

View file

@ -15,6 +15,7 @@ class Site
has_many :actor_moderations has_many :actor_moderations
has_many :fediblock_states has_many :fediblock_states
has_many :instances, through: :instance_moderations has_many :instances, through: :instance_moderations
has_many :remote_flags, class_name: 'ActivityPub::RemoteFlag'
before_save :generate_private_key_pem!, unless: :private_key_pem? before_save :generate_private_key_pem!, unless: :private_key_pem?
@ -23,6 +24,13 @@ class Site
@social_inbox ||= SocialInbox.new(site: self) @social_inbox ||= SocialInbox.new(site: self)
end end
# Obtiene el hostname de la API de Sutty
#
# @return [String]
def social_inbox_hostname
Rails.application.routes.default_url_options[:host].sub('panel', 'api')
end
private private
# Genera la llave privada y la almacena # Genera la llave privada y la almacena

View file

@ -37,8 +37,20 @@ class SocialInbox
# @return [DistributedPress::V1::Social::Client] # @return [DistributedPress::V1::Social::Client]
def client def client
@client ||= DistributedPress::V1::Social::Client.new( @client ||= client_for site.config.dig('activity_pub', 'url')
url: site.config.dig('activity_pub', 'url'), end
# Permite enviar mensajes directo a otro servidor
#
# @param url [String]
# @return [DistributedPress::V1::Social::Client]
def client_for(url)
raise "Falló generar un cliente" if url.blank?
@client_for ||= {}
@client_for[url] ||=
DistributedPress::V1::Social::Client.new(
url: url,
public_key_url: public_key_url, public_key_url: public_key_url,
private_key_pem: site.private_key_pem, private_key_pem: site.private_key_pem,
logger: Rails.logger, logger: Rails.logger,

View file

@ -11,6 +11,10 @@ Rails.application.routes.draw do
namespace :v1 do namespace :v1 do
resources :csp_reports, only: %i[create] resources :csp_reports, only: %i[create]
namespace :activity_pub do
resources :remote_flags, only: %i[show]
end
resources :sites, only: %i[index], constraints: { site_id: /[a-z0-9\-.]+/, id: /[a-z0-9\-.]+/ } do resources :sites, only: %i[index], constraints: { site_id: /[a-z0-9\-.]+/, id: /[a-z0-9\-.]+/ } do
get :'invitades/cookie', to: 'invitades#cookie' get :'invitades/cookie', to: 'invitades#cookie'
post :'posts/:layout', to: 'posts#create', as: :posts post :'posts/:layout', to: 'posts#create', as: :posts

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Lleva el registro de reportes remotos
class CreateActivityPubRemoteFlags < ActiveRecord::Migration[6.1]
def change
create_table :activity_pub_remote_flags, id: :uuid do |t|
t.timestamps
t.belongs_to :site
t.uuid :actor_id, index: true
t.text :message
t.index %i[site_id actor_id], unique: true
end
end
end

View file

@ -546,6 +546,20 @@ CREATE TABLE public.activity_pub_objects (
); );
--
-- Name: activity_pub_remote_flags; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pub_remote_flags (
id uuid DEFAULT gen_random_uuid() NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
site_id bigint,
actor_id uuid,
message text
);
-- --
-- Name: activity_pubs; Type: TABLE; Schema: public; Owner: - -- Name: activity_pubs; Type: TABLE; Schema: public; Owner: -
-- --
@ -1762,6 +1776,14 @@ ALTER TABLE ONLY public.activity_pub_objects
ADD CONSTRAINT activity_pub_objects_pkey PRIMARY KEY (id); ADD CONSTRAINT activity_pub_objects_pkey PRIMARY KEY (id);
--
-- Name: activity_pub_remote_flags activity_pub_remote_flags_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pub_remote_flags
ADD CONSTRAINT activity_pub_remote_flags_pkey PRIMARY KEY (id);
-- --
-- Name: activity_pubs activity_pubs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: activity_pubs activity_pubs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -2122,6 +2144,27 @@ CREATE INDEX index_activity_pub_actors_on_uri ON public.activity_pub_actors USIN
CREATE INDEX index_activity_pub_instances_on_hostname ON public.activity_pub_instances USING btree (hostname); CREATE INDEX index_activity_pub_instances_on_hostname ON public.activity_pub_instances USING btree (hostname);
--
-- Name: index_activity_pub_remote_flags_on_actor_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_remote_flags_on_actor_id ON public.activity_pub_remote_flags USING btree (actor_id);
--
-- Name: index_activity_pub_remote_flags_on_site_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_remote_flags_on_site_id ON public.activity_pub_remote_flags USING btree (site_id);
--
-- Name: index_activity_pub_remote_flags_on_site_id_and_actor_id; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_activity_pub_remote_flags_on_site_id_and_actor_id ON public.activity_pub_remote_flags USING btree (site_id, actor_id);
-- --
-- Name: index_activity_pubs_on_site_id_and_object_id_and_object_type; Type: INDEX; Schema: public; Owner: - -- Name: index_activity_pubs_on_site_id_and_object_id_and_object_type; Type: INDEX; Schema: public; Owner: -
-- --
@ -2653,6 +2696,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20240227134845'), ('20240227134845'),
('20240227142019'), ('20240227142019'),
('20240228171335'), ('20240228171335'),
('20240228202830'); ('20240228202830'),
('20240229201155');