5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-19 19:26:21 +00:00

feat: modelo de datos de activitypub #15109

This commit is contained in:
f 2024-02-20 14:44:52 -03:00
parent b4117d7c34
commit 27c0ca655e
No known key found for this signature in database
25 changed files with 435 additions and 1 deletions

View file

@ -0,0 +1,33 @@
# 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
include AASM
belongs_to :site
belongs_to :object, polymorphic: true
has_many :activities
validates :site_id, presence: true
validates :object_id, presence: true
validates :aasm_state, presence: true, inclusion: { in: %w[paused approved rejected reported deleted] }
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
state :deleted
end
end

View file

@ -0,0 +1,24 @@
# frozen_string_literal: true
# = Activity =
#
# Lleva un registro de las actividades que nos piden hacer remotamente.
#
# Las actividades pueden tener distintos destinataries (sitios/actores).
#
# @todo Obtener el contenido del objeto dinámicamente si no existe
# localmente, por ejemplo cuando la actividad crea un objeto pero lo
# envía como referencia en lugar de anidarlo.
#
# @see {https://www.w3.org/TR/activitypub/#client-to-server-interactions}
class ActivityPub::Activity < ApplicationRecord
include ActivityPub::Concerns::JsonLdConcern
belongs_to :activity_pub
has_one :object, through: :activity_pub
validates :activity_pub_id, presence: true
# Siempre en orden descendiente para saber el último estado
default_scope -> { order(created_at: :desc) }
end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class ActivityPub::Activity::Create < ActivityPub::Activity; end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class ActivityPub::Activity::Delete < ActivityPub::Activity; end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class ActivityPub::Activity::Flag < ActivityPub::Activity; end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
# = Follow =
#
# Una actividad de seguimiento se refiere siempre a une actore (el
# sitio) y proviene de otre actore.
class ActivityPub::Activity::Follow < ActivityPub::Activity; end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class ActivityPub::Activity::Generic < ActivityPub::Activity; end

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
# = Undo =
#
# Deshace una actividad, dependiendo de la actividad a la que se
# refiere.
class ActivityPub::Activity::Undo < ActivityPub::Activity
end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class ActivityPub::Activity::Update < ActivityPub::Activity; end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# = Actor =
#
# Actor es la entidad que realiza acciones en ActivityPub
#
# @todo Obtener el perfil dinámicamente
class ActivityPub::Actor < ApplicationRecord
include ActivityPub::Concerns::JsonLdConcern
belongs_to :instance
has_many :activity_pubs, as: :object
has_many :objects
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
class ActivityPub
module Concerns
module JsonLdConcern
extend ActiveSupport::Concern
included do
validates :uri, presence: true, uniqueness: true
# Cuando asignamos contenido, obtener la URI si no lo hicimos ya
before_save :uri_from_content!, unless: :uri?
# Obtiene un tipo de actividad a partir del tipo informado
#
# @param object [Hash]
# @return [Activity]
def self.type_from(object)
"#{self.class.name}::#{object[:type].presence || 'Generic'}".constantize
rescue NameError
self.class::Generic
end
private
def uri_from_content!
self.uri = content[:id]
end
end
end
end
end

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
# = Instance =
#
# Representa cada instancia del fediverso que interactúa con la Social
# Inbox.
class ActivityPub::Instance < ApplicationRecord
include AASM
validates :aasm_state, presence: true, inclusion: { in: %w[paused allowed blocked] }
validates :hostname, uniqueness: true, hostname: true
has_many :activity_pubs
has_many :actors
aasm do
state :paused, initial: true
state :allowed
state :blocked
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
# Almacena objetos de ActivityPub, como Note, Article, etc.
class ActivityPub::Object < ApplicationRecord
include ActivityPub::Concerns::JsonLdConcern
belongs_to :actor
has_many :activity_pubs, as: :object
validates :actor_id, presence: true
end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
# = Application =
#
# Una aplicación o instancia
class ActivityPub::Object::Application < ActivityPub::Object; end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
# = Article =
#
# Representa artículos
class ActivityPub::Object::Article < ActivityPub::Object; end

View file

@ -0,0 +1,4 @@
# frozen_string_literal: true
# = Generic =
class ActivityPub::Object::Generic < ActivityPub::Object; end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
# = Note =
#
# Representa notas, el tipo más común de objeto del Fediverso.
class ActivityPub::Object::Note < ActivityPub::Object; end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
# = Organization =
#
# Una organización
class ActivityPub::Object::Organization < ActivityPub::Object; end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
# = Person =
#
# Una persona, el perfil de une actore
class ActivityPub::Object::Person < ActivityPub::Object; end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Actividades. Se asocian a un objeto y a una cola de moderación
class CreateActivityPubActivities < ActiveRecord::Migration[6.1]
def change
create_table :activity_pub_activities, id: :uuid do |t|
t.timestamps
t.uuid :activity_pub_id, index: true, null: false
t.string :type, null: false
t.string :uri, null: false
t.jsonb :content, default: {}
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
# Almacena actores de ActivityPub y los relaciona con actividades
class CreateActivityPubActors < ActiveRecord::Migration[6.1]
def change
create_table :activity_pub_actors, id: :uuid do |t|
t.timestamps
t.uuid :instance_id, index: true, null: false
t.string :uri, index: true, unique: true, null: false
end
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
# Registro de actividades.
class CreateActivityPubs < ActiveRecord::Migration[6.1]
def change
create_table :activity_pubs, id: :uuid do |t|
t.timestamps
t.bigint :site_id, null: false
t.uuid :object_id, null: false
t.string :object_type, null: false
t.string :aasm_state, null: false
t.index %i[site_id object_id object_type], unique: true
end
end
end

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
# Almacena objetos de ActivityPub. Los objetos pueden estar compartidos
# por toda la instancia.
class CreateActivityPubObjects < ActiveRecord::Migration[6.1]
def change
create_table :activity_pub_objects, id: :uuid do |t|
t.timestamps
t.uuid :actor_id, index: true, null: false
t.string :type, null: false
t.string :uri, null: false, unique: true
t.jsonb :content, default: {}
end
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
# Almacena las instancias
class CreateActivityPubInstances < ActiveRecord::Migration[6.1]
def change
create_table :activity_pub_instances, id: :uuid do |t|
t.timestamps
t.string :hostname, index: true, unique: true, null: false
t.string :aasm_state, null: false
t.jsonb :content, default: {}
end
end
end

View file

@ -473,6 +473,78 @@ CREATE SEQUENCE public.active_storage_variant_records_id_seq
ALTER SEQUENCE public.active_storage_variant_records_id_seq OWNED BY public.active_storage_variant_records.id;
--
-- Name: activity_pub_activities; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pub_activities (
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,
activity_pub_id uuid NOT NULL,
type character varying NOT NULL,
uri character varying NOT NULL,
content jsonb DEFAULT '{}'::jsonb
);
--
-- Name: activity_pub_actors; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pub_actors (
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,
instance_id uuid NOT NULL,
uri character varying NOT NULL
);
--
-- Name: activity_pub_instances; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pub_instances (
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,
hostname character varying NOT NULL,
aasm_state character varying NOT NULL,
content jsonb DEFAULT '{}'::jsonb
);
--
-- Name: activity_pub_objects; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pub_objects (
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,
actor_id uuid NOT NULL,
type character varying NOT NULL,
uri character varying NOT NULL,
content jsonb DEFAULT '{}'::jsonb
);
--
-- Name: activity_pubs; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.activity_pubs (
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 NOT NULL,
object_id uuid NOT NULL,
object_type character varying NOT NULL,
aasm_state character varying NOT NULL
);
--
-- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: -
--
@ -1565,6 +1637,46 @@ ALTER TABLE ONLY public.active_storage_variant_records
ADD CONSTRAINT active_storage_variant_records_pkey PRIMARY KEY (id);
--
-- Name: activity_pub_activities activity_pub_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pub_activities
ADD CONSTRAINT activity_pub_activities_pkey PRIMARY KEY (id);
--
-- Name: activity_pub_actors activity_pub_actors_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pub_actors
ADD CONSTRAINT activity_pub_actors_pkey PRIMARY KEY (id);
--
-- Name: activity_pub_instances activity_pub_instances_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pub_instances
ADD CONSTRAINT activity_pub_instances_pkey PRIMARY KEY (id);
--
-- Name: activity_pub_objects activity_pub_objects_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pub_objects
ADD CONSTRAINT activity_pub_objects_pkey PRIMARY KEY (id);
--
-- Name: activity_pubs activity_pubs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.activity_pubs
ADD CONSTRAINT activity_pubs_pkey PRIMARY KEY (id);
--
-- Name: blazer_audits blazer_audits_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -1865,6 +1977,48 @@ CREATE UNIQUE INDEX index_active_storage_blobs_on_key_and_service_name ON public
CREATE UNIQUE INDEX index_active_storage_variant_records_uniqueness ON public.active_storage_variant_records USING btree (blob_id, variation_digest);
--
-- Name: index_activity_pub_activities_on_activity_pub_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_activities_on_activity_pub_id ON public.activity_pub_activities USING btree (activity_pub_id);
--
-- Name: index_activity_pub_actors_on_instance_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_actors_on_instance_id ON public.activity_pub_actors USING btree (instance_id);
--
-- Name: index_activity_pub_actors_on_uri; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_actors_on_uri ON public.activity_pub_actors USING btree (uri);
--
-- Name: index_activity_pub_instances_on_hostname; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_instances_on_hostname ON public.activity_pub_instances USING btree (hostname);
--
-- Name: index_activity_pub_objects_on_actor_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_activity_pub_objects_on_actor_id ON public.activity_pub_objects USING btree (actor_id);
--
-- Name: index_activity_pubs_on_site_id_and_object_id_and_object_type; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_activity_pubs_on_site_id_and_object_id_and_object_type ON public.activity_pubs USING btree (site_id, object_id, object_type);
--
-- Name: index_blazer_audits_on_query_id; Type: INDEX; Schema: public; Owner: -
--
@ -2320,6 +2474,11 @@ INSERT INTO "schema_migrations" (version) VALUES
('20230829204127'),
('20230921155401'),
('20230927153926'),
('20240216170202');
('20240216170202'),
('20240219153919'),
('20240219175839'),
('20240219204011'),
('20240219204224'),
('20240220161414');