From 521922c131db7a82f0b0cb9fdb03ff86a05f3395 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 20 May 2023 14:46:09 -0300 Subject: [PATCH 01/10] fix: no compilar assets en 3.17 --- .woodpecker.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index a140f93f..b5806bf3 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -63,7 +63,6 @@ pipeline: branch: - "rails" - "panel.sutty.nl" - - "17.3.alpine.panel.sutty.nl" path: include: - "app/assets/**/*" From dd75a16335bdc0c7b095424bab44e94deb6d7da3 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 23 Aug 2023 11:22:09 -0300 Subject: [PATCH 02/10] fix: faltaron archivos en el merge --- .gitattributes | 2 ++ .../serializers/exception_serializer.rb | 22 +++++++++++++++++++ .../20230328231029_create_que_tables.rb | 12 ++++++++++ 3 files changed, 36 insertions(+) create mode 100644 .gitattributes create mode 100644 app/lib/active_job/serializers/exception_serializer.rb create mode 100644 db/migrate/20230328231029_create_que_tables.rb diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..0ede410e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +public/assets/** filter=lfs diff=lfs merge=lfs -text +public/packs/** filter=lfs diff=lfs merge=lfs -text diff --git a/app/lib/active_job/serializers/exception_serializer.rb b/app/lib/active_job/serializers/exception_serializer.rb new file mode 100644 index 00000000..42b55835 --- /dev/null +++ b/app/lib/active_job/serializers/exception_serializer.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'json/add/exception' + +module ActiveJob + module Serializers + class ExceptionSerializer < ObjectSerializer # :nodoc: + def serialize(ex) + super('value' => { 'class' => ex.class.name, 'exception' => ex.as_json }) + end + + def deserialize(hash) + hash.dig('value', 'class').constantize.json_create(hash.dig('value', 'exception')) + end + + private + def klass + Exception + end + end + end +end diff --git a/db/migrate/20230328231029_create_que_tables.rb b/db/migrate/20230328231029_create_que_tables.rb new file mode 100644 index 00000000..1ed929f7 --- /dev/null +++ b/db/migrate/20230328231029_create_que_tables.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Que +class CreateQueTables < ActiveRecord::Migration[6.1] + def up + Que.migrate! version: 7 + end + + def down + Que.migrate! version: 0 + end +end From c09dfc3b67fb19a80971aee6e1f36fa5bde0dbae Mon Sep 17 00:00:00 2001 From: f Date: Fri, 25 Aug 2023 10:11:36 -0300 Subject: [PATCH 03/10] ci: force ci to rebuild assets --- app/assets/stylesheets/application.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 65a207fa..eb953c30 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -525,5 +525,3 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1); } } } - -// force ci From d96de873a719b5d6d1645f42f702b492ea4142bb Mon Sep 17 00:00:00 2001 From: f Date: Tue, 29 Aug 2023 17:43:19 -0300 Subject: [PATCH 04/10] feat: almacenar la llave privada --- app/models/site.rb | 1 + app/models/site/social_distributed_press.rb | 12 ++++++++++++ ...204127_add_private_key_pem_ciphertext_to_sites.rb | 9 +++++++++ 3 files changed, 22 insertions(+) create mode 100644 app/models/site/social_distributed_press.rb create mode 100644 db/migrate/20230829204127_add_private_key_pem_ciphertext_to_sites.rb diff --git a/app/models/site.rb b/app/models/site.rb index 24644b9c..9ec21561 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -10,6 +10,7 @@ class Site < ApplicationRecord include Site::DeployDependencies include Site::BuildStats include Site::LayoutOrdering + include Site::SocialDistributedPress include Tienda # Cifrar la llave privada que cifra y decifra campos ocultos. Sutty diff --git a/app/models/site/social_distributed_press.rb b/app/models/site/social_distributed_press.rb new file mode 100644 index 00000000..9d283103 --- /dev/null +++ b/app/models/site/social_distributed_press.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class Site + # Agrega soporte para Social Distributed Press en los sitios + module SocialDistributedPress + extend ActiveSupport::Concern + + included do + encrypts :private_key_pem + end + end +end diff --git a/db/migrate/20230829204127_add_private_key_pem_ciphertext_to_sites.rb b/db/migrate/20230829204127_add_private_key_pem_ciphertext_to_sites.rb new file mode 100644 index 00000000..9f26f21a --- /dev/null +++ b/db/migrate/20230829204127_add_private_key_pem_ciphertext_to_sites.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# Almacena las llaves privadas de cada sitio +class AddPrivateKeyPemCiphertextToSites < ActiveRecord::Migration[6.1] + # Agrega la columna cifrada + def change + add_column :sites, :private_key_pem_ciphertext, :text + end +end From 99f8947c43a1debad41c5e18750d39b160ffe182 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 29 Aug 2023 17:49:25 -0300 Subject: [PATCH 05/10] feat: generar la llave privada #14169 --- app/models/site/social_distributed_press.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/models/site/social_distributed_press.rb b/app/models/site/social_distributed_press.rb index 9d283103..5d469f03 100644 --- a/app/models/site/social_distributed_press.rb +++ b/app/models/site/social_distributed_press.rb @@ -7,6 +7,17 @@ class Site included do encrypts :private_key_pem + + before_save :generate_private_key_pem!, unless: :private_key_pem? + + private + + # Genera la llave privada y la almacena + # + # @return [nil] + def generate_private_key_pem! + self.private_key_pem ||= DistributedPress::V1::Social::Client.new(public_key_url: nil, key_size: 2048).private_key.export + end end end end From f266de8bedecfbf775ae9516ae987f37adec2db7 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 29 Aug 2023 18:26:03 -0300 Subject: [PATCH 06/10] feat: correr un comando obteniendo la llave dentro de un archivo temporal --- app/models/deploy.rb | 15 +++++++++++++++ app/models/deploy_local.rb | 6 +++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index a92708c0..77e5b8d8 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -109,6 +109,21 @@ class Deploy < ApplicationRecord private + # Escribe el contenido en un archivo temporal y ejecuta el bloque + # provisto con el archivo como parámetro + # + # @param :content [String] + def with_tempfile(content, &block) + Tempfile.create(SecureRandom.hex) do |file| + file.write content.to_s + file.rewind + file.close + + # @yieldparam :file [File] + yield file + end + end + # @param [String] # @return [String] def readable_cmd(cmd) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 75ea8b1c..e66bb003 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -141,8 +141,12 @@ class DeployLocal < Deploy run %(bundle install --deployment --no-cache --path="#{gems_dir}" --clean --without test development), output: output end + # TODO: Esto significa que todos los sitios van a tener activity pub + # activado def jekyll_build(output: false) - run %(bundle exec jekyll build --trace --profile --destination "#{escaped_destination}"), output: output + with_tempfile(site.private_key_pem) do |file| + run %(bundle exec jekyll build --trace --profile --key #{file.path} --destination "#{escaped_destination}"), output: output + end end # no debería haber espacios ni caracteres especiales, pero por si From 53aa3886eafeb0778e8bbb8dd92a120aa0a16f72 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 30 Aug 2023 10:47:08 -0300 Subject: [PATCH 07/10] feat: habilitar/deshabilitar activity pub --- .../_deploy_social_distributed_press.haml | 21 +++++++++++++++++++ config/locales/en.yml | 12 +++++++++++ config/locales/es.yml | 12 +++++++++++ 3 files changed, 45 insertions(+) create mode 100644 app/views/deploy_mailer/_deploy_social_distributed_press.haml diff --git a/app/views/deploy_mailer/_deploy_social_distributed_press.haml b/app/views/deploy_mailer/_deploy_social_distributed_press.haml new file mode 100644 index 00000000..5c73b262 --- /dev/null +++ b/app/views/deploy_mailer/_deploy_social_distributed_press.haml @@ -0,0 +1,21 @@ +-# Publicar a la web distribuida + +.row + .col + = deploy.hidden_field :id + = deploy.hidden_field :type + .custom-control.custom-switch + -# + El checkbox invierte la lógica de destrucción porque queremos + crear el deploy si está activado y destruirlo si está + desactivado. + = deploy.check_box :_destroy, + { checked: deploy.object.persisted?, class: 'custom-control-input' }, + '0', '1' + = deploy.label :_destroy, class: 'custom-control-label' do + %h3= t('.title') + = sanitize_markdown t('.help'), + tags: %w[p strong em a] + + +%hr/ diff --git a/config/locales/en.yml b/config/locales/en.yml index 5f97a8b9..0dad2e68 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -123,6 +123,10 @@ en: title: Distributed Web success: Success! error: Error + deploy_social_distributed_press: + title: Fediverse + success: Success! + error: Error deploy_reindex: title: Reindex success: Success! @@ -307,6 +311,14 @@ en: indefinitely. [Learn more](https://sutty.nl/learn-more-about-publish-to-dweb-functionality/) + deploy_social_distributed_press: + title: 'Publish on the Fediverse' + help: | + By using the ActivityPub protocol, people on the Fediverse + ([Mastodon](https://joinmastodon.org/servers), + [Pixelfed](https://pixelfed.social/site/about), and + [others](https://fediverse.party/)) can follow your site, + receive news and interact with them. stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index 9e0b8945..d899b99c 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -123,6 +123,10 @@ es: title: Web distribuida success: ¡Éxito! error: Hubo un error + deploy_social_distributed_press: + title: Fediverso + success: ¡Éxito! + error: Hubo un error deploy_reindex: title: Reindexación success: ¡Éxito! @@ -312,6 +316,14 @@ es: copias de tu contenido indefinidamente. [Saber más](https://sutty.nl/saber-mas-sobre-publicar-a-la-web-distribuida/) + deploy_social_distributed_press: + title: 'Publicar al Fediverso' + help: | + Utilizando el protocolo ActivityPub, otras personas en el + Fediverso ([Mastodon](https://joinmastodon.org/servers), + [Pixelfed](https://pixelfed.social/site/about) y + [otros](https://fediverse.party/)) pueden seguir a tu sitio, + recibir novedades e interactuar con ellas. stats: index: title: Estadísticas From 66d567733fd4fd13a7039997062836f048a9afe3 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 30 Aug 2023 10:47:27 -0300 Subject: [PATCH 08/10] =?UTF-8?q?fix:=20generar=20todos=20los=20deploys=20?= =?UTF-8?q?autom=C3=A1ticamente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/site.rb | 4 ---- app/services/site_service.rb | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 9ec21561..961831d5 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -19,10 +19,6 @@ class Site < ApplicationRecord # protege de acceso al panel de Sutty! encrypts :private_key - # TODO: Hacer que los diferentes tipos de deploy se auto registren - # @see app/services/site_service.rb - DEPLOYS = %i[local private www zip hidden_service distributed_press].freeze - validates :name, uniqueness: true, hostname: { allow_root_label: true } diff --git a/app/services/site_service.rb b/app/services/site_service.rb index b1df3d10..5bd89888 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -54,9 +54,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Genera los Deploy necesarios para el sitio a menos que ya los tenga. def build_deploys - Site::DEPLOYS.map { |deploy| "Deploy#{deploy.to_s.camelcase}" } - .each do |deploy| - next if site.deploys.find_by type: deploy + Deploy.subclasses.each do |deploy| + next if site.deploys.find_by type: deploy.name site.deploys.build type: deploy end From 8ed88a31831c43557a71ec3a5d450a3bb9b307cf Mon Sep 17 00:00:00 2001 From: f Date: Wed, 30 Aug 2023 10:58:52 -0300 Subject: [PATCH 09/10] =?UTF-8?q?feat:=20los=20deploys=20pueden=20pasar=20?= =?UTF-8?q?opciones=20de=20compilaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy.rb | 5 ++++ app/models/deploy_local.rb | 16 ++++++++++--- app/models/deploy_social_distributed_press.rb | 24 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 app/models/deploy_social_distributed_press.rb diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 77e5b8d8..abf5591f 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -100,6 +100,11 @@ class Deploy < ApplicationRecord @local_env ||= {} end + # Devuelve opciones para jekyll build + # + # @return [String,nil] + def flags_for_build(**args); end + # Trae todas las dependencias # # @return [Array] diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index e66bb003..9228581f 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -141,11 +141,11 @@ class DeployLocal < Deploy run %(bundle install --deployment --no-cache --path="#{gems_dir}" --clean --without test development), output: output end - # TODO: Esto significa que todos los sitios van a tener activity pub - # activado def jekyll_build(output: false) with_tempfile(site.private_key_pem) do |file| - run %(bundle exec jekyll build --trace --profile --key #{file.path} --destination "#{escaped_destination}"), output: output + flags = extra_flags(private_key: file) + + run %(bundle exec jekyll build --trace --profile #{flags} --destination "#{escaped_destination}"), output: output end end @@ -173,4 +173,14 @@ class DeployLocal < Deploy end end end + + # Genera opciones extra desde los otros deploys + # + # @param :args [Hash] + # @return [String] + def extra_flags(**args) + non_local_deploys.map do |deploy| + deploy.flags_for_build(**args) + end.compact.join(' ') + end end diff --git a/app/models/deploy_social_distributed_press.rb b/app/models/deploy_social_distributed_press.rb new file mode 100644 index 00000000..47464ea9 --- /dev/null +++ b/app/models/deploy_social_distributed_press.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'distributed_press/v1/social/client' + +# Publicar novedades al Fediverso +class DeploySocialDistributedPress < Deploy + # Solo luego de publicar remotamente + DEPENDENCIES = %i[deploy_distributed_press deploy_rsync deploy_full_rsync] + + # Envía las notificaciones + def deploy(output: false) + with_tempfile(site.private_key_pem) do |file| + run %(bundle exec jekyll notify --trace --key #{file.path} --destination "#{escaped_destination}"), output: output + end + end + + # Genera la opción de llave privada para jekyll build + # + # @params :args [Hash] + # @return [String] + def flags_for_build(**args) + "--key #{Shellwords.escape args[:private_key].path}" + end +end From 3cf29ebd5208fc8341b282f7eb5964abd98a9768 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 30 Aug 2023 11:09:08 -0300 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20m=C3=A9todos=20de=20deploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_social_distributed_press.rb | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_social_distributed_press.rb b/app/models/deploy_social_distributed_press.rb index 47464ea9..db555ab7 100644 --- a/app/models/deploy_social_distributed_press.rb +++ b/app/models/deploy_social_distributed_press.rb @@ -10,10 +10,41 @@ class DeploySocialDistributedPress < Deploy # Envía las notificaciones def deploy(output: false) with_tempfile(site.private_key_pem) do |file| - run %(bundle exec jekyll notify --trace --key #{file.path} --destination "#{escaped_destination}"), output: output + key = Shellwords.escape file.path + dest = Shellwords.escape destination + + run %(bundle exec jekyll notify --trace --key #{key} --destination "#{dest}"), output: output end end + # Igual que DeployLocal + # + # @return [String] + def destination + File.join(Rails.root, '_deploy', site.hostname) + end + + # Solo uno + # + # @return [Integer] + def limit + 1 + end + + # Espacio ocupado, pero no podemos calcularlo + # + # @return [Integer] + def size + 0 + end + + # El perfil de actor + # + # @return [String,nil] + def url + site.data.dig('activity_pub', 'actor') + end + # Genera la opción de llave privada para jekyll build # # @params :args [Hash]