diff --git a/app/models/fediblock_state.rb b/app/models/fediblock_state.rb index b5258fb6..e50abaef 100644 --- a/app/models/fediblock_state.rb +++ b/app/models/fediblock_state.rb @@ -27,12 +27,14 @@ class FediblockState < ApplicationRecord transitions from: :disabled, to: :enabled before do - enable_remotely! + # Bloquear todos las instancias de este Fediblock + enable_remotely! list_names(fediblock.hostnames) # Al actualizar el estado en masa garantizamos que las # instancias que ya existen queden sincronizadas con el bloqueo # en masa que acabamos de hacer. - instance_moderations.block_all! + instance_ids = fediblock.instances.ids + site.instance_moderations.where(instance_id: instance_ids).block_all! # Luego esta tarea crea las que falten e ignora las que ya se # bloquearon. @@ -41,11 +43,13 @@ class FediblockState < ApplicationRecord # Bloquear a todes les Actores de las instancias bloqueadas para # indicarle a le usuarie que les tiene que desbloquear # manualmente. + actor_ids = ActivityPub::Actor.where(instance_id: instance_ids).ids ActorModeration.where(actor_id: actor_ids).paused.block_all! end end - # Al deshabilitar, las listas pasan a modo pausa. + # Al deshabilitar, las listas pasan a modo pausa, a menos que estén + # activas en otros listados. # # @todo No cambiar el estado si se habían habilitado manualmente, # pero esto implica que tenemos que encontrar las que sí y quitarlas @@ -54,12 +58,19 @@ class FediblockState < ApplicationRecord transitions from: :enabled, to: :disabled before do - disable_remotely! + # Deshabilitar todas las instancias que no estén habilitadas por + # otros fediblocks + disable_remotely! list_names(unique_hostnames) - instance_moderations.pause_all! + # 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! # Volver a pausar todes les actores de esta instancia que fueron - # bloqueades. + # bloqueades, a menos que hayan sido bloqueades por otro + # fediblock. + actor_ids = ActivityPub::Actor.where(instance_id: instance_ids).ids ActorModeration.where(actor_id: actor_ids).blocked.pause_all! end end @@ -67,37 +78,48 @@ class FediblockState < ApplicationRecord private - def actor_ids - ActivityPub::Actor.where(instance_id: instance_ids).pluck(:id) - end - - def instance_ids - fediblock.instances.pluck(:id) - end - - # Todas las instancias de moderación de este sitio - def instance_moderations - site.instance_moderations.where(instance_id: instance_ids) - end - + # Devuelve los hostnames únicos a esta instancia. + # # @return [Array] - def list_names - @list_names ||= fediblock.hostnames.map do |hostname| + def unique_hostnames + @unique_hostnames ||= + begin + other_enabled_fediblock_ids = + site.fediblock_states.enabled.where.not(id: id).pluck(:fediblock_id) + other_enabled_hostnames = + ActivityPub::Fediblock + .where(id: other_enabled_fediblock_ids) + .pluck(:hostnames) + .flatten + .uniq + + fediblock.hostnames - other_enabled_hostnames + end + end + + # @param hostnames [Array] + # @return [Array] + def list_names(hostnames) + hostnames.map do |hostname| "@*@#{hostname}" end end # Al deshabilitar, las instancias pasan a ser analizadas caso por caso - def disable_remotely! + # + # @param list [Array] + def disable_remotely!(list) raise unless - site.social_inbox.blocklist.delete(list: list_names).ok? && - site.social_inbox.allowlist.delete(list: list_names).ok? + site.social_inbox.blocklist.delete(list: list).ok? && + site.social_inbox.allowlist.delete(list: list).ok? end # Al habilitar, se bloquean todas las instancias de la lista - def enable_remotely! + # + # @param list [Array] + def enable_remotely!(list) raise unless - site.social_inbox.blocklist.post(list: list_names).ok? && - site.social_inbox.allowlist.delete(list: list_names).ok? + site.social_inbox.blocklist.post(list: list).ok? && + site.social_inbox.allowlist.delete(list: list).ok? end end