mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-22 10:16:22 +00:00
feat: cada sitio tiene un estado de moderación para la instancia
This commit is contained in:
parent
64cef8a13e
commit
dc11e6efc7
14 changed files with 200 additions and 11 deletions
|
@ -142,7 +142,8 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Actor, si no hay instancia, la crea en el momento
|
# Actor, si no hay instancia, la crea en el momento, junto con
|
||||||
|
# su estado de moderación.
|
||||||
#
|
#
|
||||||
# @return [Actor]
|
# @return [Actor]
|
||||||
def actor
|
def actor
|
||||||
|
@ -150,6 +151,8 @@ module Api
|
||||||
unless a.instance
|
unless a.instance
|
||||||
a.instance = ActivityPub::Instance.find_or_create_by(hostname: URI.parse(a.uri).hostname)
|
a.instance = ActivityPub::Instance.find_or_create_by(hostname: URI.parse(a.uri).hostname)
|
||||||
|
|
||||||
|
site.instance_moderations.find_or_create_by(instance: a.instance)
|
||||||
|
|
||||||
ActivityPub::InstanceFetchJob.perform_later(site: site, instance: a.instance)
|
ActivityPub::InstanceFetchJob.perform_later(site: site, instance: a.instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
35
app/controllers/instance_moderations_controller.rb
Normal file
35
app/controllers/instance_moderations_controller.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Actualiza la relación entre un sitio y una instancia
|
||||||
|
class InstanceModerationsController < ApplicationController
|
||||||
|
before_action :authorize_policy
|
||||||
|
|
||||||
|
def pause
|
||||||
|
instance_moderation.pause!
|
||||||
|
|
||||||
|
redirect_to site_moderation_queue_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def allow
|
||||||
|
instance_moderation.allow!
|
||||||
|
|
||||||
|
redirect_to site_moderation_queue_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def block
|
||||||
|
instance_moderation.block!
|
||||||
|
|
||||||
|
redirect_to site_moderation_queue_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# @return [InstanceModeration]
|
||||||
|
def instance_moderation
|
||||||
|
@instance_moderation ||= site.instance_moderations.find(params[:instance_moderation_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_policy
|
||||||
|
authorize instance_moderation
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,7 +8,7 @@ class ModerationQueueController < ApplicationController
|
||||||
|
|
||||||
# @todo cambiar el estado por query
|
# @todo cambiar el estado por query
|
||||||
@activity_pubs = site.activity_pubs
|
@activity_pubs = site.activity_pubs
|
||||||
@instances = ActivityPub::Instance.where(id: @activity_pubs.distinct.pluck(:instance_id))
|
@instance_moderations = site.instance_moderations
|
||||||
end
|
end
|
||||||
|
|
||||||
# Perfil remoto de usuarie
|
# Perfil remoto de usuarie
|
||||||
|
|
|
@ -13,6 +13,7 @@ class ActivityPub
|
||||||
|
|
||||||
has_many :activity_pubs
|
has_many :activity_pubs
|
||||||
has_many :actors
|
has_many :actors
|
||||||
|
has_many :instance_moderations
|
||||||
|
|
||||||
aasm do
|
aasm do
|
||||||
state :paused, initial: true
|
state :paused, initial: true
|
||||||
|
|
27
app/models/instance_moderation.rb
Normal file
27
app/models/instance_moderation.rb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Mantiene el registro de relaciones entre sitios e instancias
|
||||||
|
class InstanceModeration < ApplicationRecord
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
belongs_to :site
|
||||||
|
belongs_to :instance, class_name: 'ActivityPub::Instance'
|
||||||
|
|
||||||
|
aasm do
|
||||||
|
state :paused, initial: true
|
||||||
|
state :allowed
|
||||||
|
state :blocked
|
||||||
|
|
||||||
|
event :pause do
|
||||||
|
transitions from: %i[allowed blocked], to: :paused
|
||||||
|
end
|
||||||
|
|
||||||
|
event :allow do
|
||||||
|
transitions from: %i[paused blocked], to: :allowed
|
||||||
|
end
|
||||||
|
|
||||||
|
event :block do
|
||||||
|
transitions from: %i[paused allowed], to: :blocked
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,6 +11,7 @@ class Site
|
||||||
has_encrypted :private_key_pem
|
has_encrypted :private_key_pem
|
||||||
|
|
||||||
has_many :activity_pubs
|
has_many :activity_pubs
|
||||||
|
has_many :instance_moderations
|
||||||
|
|
||||||
before_save :generate_private_key_pem!, unless: :private_key_pem?
|
before_save :generate_private_key_pem!, unless: :private_key_pem?
|
||||||
|
|
||||||
|
|
16
app/policies/instance_moderation_policy.rb
Normal file
16
app/policies/instance_moderation_policy.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Solo les usuaries pueden moderar instancias
|
||||||
|
InstanceModerationPolicy = Struct.new(:usuarie, :instance_moderation) do
|
||||||
|
def pause?
|
||||||
|
instance_moderation.site.usuarie? usuarie
|
||||||
|
end
|
||||||
|
|
||||||
|
def allow?
|
||||||
|
pause?
|
||||||
|
end
|
||||||
|
|
||||||
|
def block?
|
||||||
|
pause?
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,7 @@
|
||||||
-# Componente Botón general Moderación
|
-# Componente Botón general Moderación
|
||||||
|
|
||||||
%button.btn{ href: href, class: local_assigns[:class] }= text
|
- local_assigns[:method] ||= 'patch'
|
||||||
|
- local_assigns[:class] = "btn #{local_assigns[:class]}"
|
||||||
|
|
||||||
|
-# @todo path es obligatorio
|
||||||
|
= button_to text, local_assigns[:path], **local_assigns
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
-# Componente botonera de moderación de Instancias
|
-# Componente botonera de moderación de Instancias
|
||||||
|
|
||||||
- btn_class = 'btn btn-secondary'
|
- btn_class = 'btn btn-secondary'
|
||||||
= render 'components/btn_base', text: t('.text_check'), class: btn_class, href: ''
|
= render 'components/btn_base', path: site_instance_moderation_pause_path(instance_moderation_id: instance_moderation), text: t('.text_check'), class: btn_class, disabled: !instance_moderation.may_pause?
|
||||||
= render 'components/btn_base', text: t('.text_allow'), class: btn_class, href: ''
|
= render 'components/btn_base', path: site_instance_moderation_allow_path(instance_moderation_id: instance_moderation), text: t('.text_allow'), class: btn_class, disabled: !instance_moderation.may_allow?
|
||||||
= render 'components/btn_base', text: t('.text_deny'), class: btn_class, href: ''
|
= render 'components/btn_base', path: site_instance_moderation_block_path(instance_moderation_id: instance_moderation), text: t('.text_deny'), class: btn_class, disabled: !instance_moderation.may_block?
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
-# Filtros
|
-# Filtros
|
||||||
= render 'components/instances_filters'
|
= render 'components/instances_filters'
|
||||||
|
|
||||||
- @instances.each do |instance|
|
- instance_moderations.each do |instance_moderation|
|
||||||
%hr
|
%hr
|
||||||
= render 'moderation_queue/instance', instance: instance
|
= render 'moderation_queue/instance', instance: instance_moderation.instance
|
||||||
|
|
||||||
-# Botones moderación
|
-# Botones moderación
|
||||||
.d-flex.pb-4
|
.d-flex.pb-4
|
||||||
= render 'components/instances_btn_box', instance: instance
|
= render 'components/instances_btn_box', site: site, instance_moderation: instance_moderation
|
||||||
|
|
||||||
%hr
|
%hr
|
||||||
%h3.mt-5= t('moderation_queue.instances.title')
|
%h3.mt-5= t('moderation_queue.instances.title')
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
.col
|
.col
|
||||||
- summary = t('.instances')
|
- summary = t('.instances')
|
||||||
= render 'layouts/details', summary: summary do
|
= render 'layouts/details', summary: summary do
|
||||||
= render 'moderation_queue/instances', site: @site, post: @post, moderation_queue: @moderation_queue
|
= render 'moderation_queue/instances', site: @site, instance_moderations: @instance_moderations
|
||||||
%hr
|
%hr
|
||||||
- summary = t('.accounts')
|
- summary = t('.accounts')
|
||||||
= render 'layouts/details', summary: summary do
|
= render 'layouts/details', summary: summary do
|
||||||
|
|
|
@ -62,6 +62,12 @@ Rails.application.routes.draw do
|
||||||
get 'remote_profile', to: 'moderation_queue#remote_profile'
|
get 'remote_profile', to: 'moderation_queue#remote_profile'
|
||||||
get 'instances', to: 'moderation_queue#instances'
|
get 'instances', to: 'moderation_queue#instances'
|
||||||
|
|
||||||
|
resources :instance_moderations, only: [] do
|
||||||
|
patch :pause, to: 'instance_moderations#pause'
|
||||||
|
patch :allow, to: 'instance_moderations#allow'
|
||||||
|
patch :block, to: 'instance_moderations#block'
|
||||||
|
end
|
||||||
|
|
||||||
# Gestionar artículos según idioma
|
# Gestionar artículos según idioma
|
||||||
nested do
|
nested do
|
||||||
scope '/(:locale)', constraint: /[a-z]{2}(-[A-Z]{2})?/ do
|
scope '/(:locale)', constraint: /[a-z]{2}(-[A-Z]{2})?/ do
|
||||||
|
|
26
db/migrate/20240226134335_create_instance_moderation.rb
Normal file
26
db/migrate/20240226134335_create_instance_moderation.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Como la instancia es única para todo el panel, necesitamos llevar
|
||||||
|
# registro de su relación con cada sitio por separado.
|
||||||
|
class CreateInstanceModeration < ActiveRecord::Migration[6.1]
|
||||||
|
def up
|
||||||
|
create_table :instance_moderations do |t|
|
||||||
|
t.timestamps
|
||||||
|
|
||||||
|
t.belongs_to :site
|
||||||
|
t.uuid :instance_id, index: true
|
||||||
|
|
||||||
|
t.string :aasm_state, null: false, default: 'paused'
|
||||||
|
|
||||||
|
t.index %i[site_id instance_id], unique: true
|
||||||
|
end
|
||||||
|
|
||||||
|
ActivityPub.all.find_each do |activity_pub|
|
||||||
|
InstanceModeration.find_or_create_by(site: activity_pub.site, instance: activity_pub.instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
drop_table :instance_moderations
|
||||||
|
end
|
||||||
|
end
|
|
@ -950,6 +950,39 @@ CREATE TABLE public.indexed_posts (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: instance_moderations; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.instance_moderations (
|
||||||
|
id bigint NOT NULL,
|
||||||
|
created_at timestamp(6) without time zone NOT NULL,
|
||||||
|
updated_at timestamp(6) without time zone NOT NULL,
|
||||||
|
site_id bigint,
|
||||||
|
instance_id uuid,
|
||||||
|
aasm_state character varying DEFAULT 'paused'::character varying NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: instance_moderations_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.instance_moderations_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: instance_moderations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public.instance_moderations_id_seq OWNED BY public.instance_moderations.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: licencias; Type: TABLE; Schema: public; Owner: -
|
-- Name: licencias; Type: TABLE; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -1514,6 +1547,13 @@ ALTER TABLE ONLY public.designs ALTER COLUMN id SET DEFAULT nextval('public.desi
|
||||||
ALTER TABLE ONLY public.distributed_press_publishers ALTER COLUMN id SET DEFAULT nextval('public.distributed_press_publishers_id_seq'::regclass);
|
ALTER TABLE ONLY public.distributed_press_publishers ALTER COLUMN id SET DEFAULT nextval('public.distributed_press_publishers_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: instance_moderations id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.instance_moderations ALTER COLUMN id SET DEFAULT nextval('public.instance_moderations_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: licencias id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: licencias id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -1774,6 +1814,14 @@ ALTER TABLE ONLY public.indexed_posts
|
||||||
ADD CONSTRAINT indexed_posts_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT indexed_posts_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: instance_moderations instance_moderations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.instance_moderations
|
||||||
|
ADD CONSTRAINT instance_moderations_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: licencias licencias_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: licencias licencias_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -2139,6 +2187,27 @@ CREATE INDEX index_indexed_posts_on_locale ON public.indexed_posts USING btree (
|
||||||
CREATE INDEX index_indexed_posts_on_site_id ON public.indexed_posts USING btree (site_id);
|
CREATE INDEX index_indexed_posts_on_site_id ON public.indexed_posts USING btree (site_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_instance_moderations_on_instance_id; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_instance_moderations_on_instance_id ON public.instance_moderations USING btree (instance_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_instance_moderations_on_site_id; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_instance_moderations_on_site_id ON public.instance_moderations USING btree (site_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_instance_moderations_on_site_id_and_instance_id; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX index_instance_moderations_on_site_id_and_instance_id ON public.instance_moderations USING btree (site_id, instance_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_licencias_on_name; Type: INDEX; Schema: public; Owner: -
|
-- Name: index_licencias_on_name; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -2476,6 +2545,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||||
('20240220161414'),
|
('20240220161414'),
|
||||||
('20240221184007'),
|
('20240221184007'),
|
||||||
('20240223170317'),
|
('20240223170317'),
|
||||||
('20240226133022');
|
('20240226133022'),
|
||||||
|
('20240226134335');
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue