From dd32a5a0c1838e3e464e8fdbe80a4d1a9c2f8235 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 13 Apr 2022 12:31:36 -0300 Subject: [PATCH 001/235] woodpecker --- .woodpecker.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .woodpecker.yml diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 00000000..81af8efb --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,26 @@ +pipeline: + publish: + image: plugins/docker + settings: + registry: registry.nulo.in + username: sutty + repo: registry.nulo.in/sutty/panel + tags: + - ${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH} + - latest + build_args: + - RUBY_VERSION=${RUBY_VERSION} + - RUBY_PATCH=${RUBY_PATCH} + - ALPINE_VERSION=${ALPINE_VERSION} + - BASE_IMAGE=registry.nulo.in/sutty/rails + purge: false + secrets: + - docker_password + when: + branch: antifascista + event: push +matrix: + include: + - ALPINE_VERSION: 3.13.10 + RUBY_VERSION: 2.7 + RUBY_PATCH: 6 From d9a5f7ff238b10795022b160dfbabb1716ce4c29 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 13 Apr 2022 12:34:42 -0300 Subject: [PATCH 002/235] actualizar pandoc --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ecf43cbc..68ec6188 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 -ARG PANDOC_VERSION=2.17.1.1 +ARG PANDOC_VERSION=2.18 ENV RAILS_ENV production # Instalar las dependencias, separamos la librería de base de datos para From 244a8de406b6afaf471da8934e4ce9bec300701c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 13 Apr 2022 12:37:13 -0300 Subject: [PATCH 003/235] ramas que provocan deploys --- .woodpecker.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 81af8efb..db2b307d 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -17,7 +17,9 @@ pipeline: secrets: - docker_password when: - branch: antifascista + branch: + - rails + - panel.sutty.nl event: push matrix: include: From d9e2291f264b273b53ecfe579d7b7d610045752a Mon Sep 17 00:00:00 2001 From: f Date: Wed, 13 Apr 2022 16:44:52 -0300 Subject: [PATCH 004/235] usar argumentos --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 68ec6188..ac90a548 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,8 @@ -FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 +ARG RUBY_VERSION=2.7 +ARG RUBY_PATCH=6 +ARG ALPINE_VERSION=3.13.10 +ARG BASE_IMAGE=registry.nulo.in/sutty/rails +FROM ${BASE_IMAGE}:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH} ARG PANDOC_VERSION=2.18 ENV RAILS_ENV production From 44de5227646c3ae0549e863bb5b2c0a9b0918c94 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 5 Oct 2022 18:44:23 -0300 Subject: [PATCH 005/235] soportar distributed press apiv0 #7839 --- app/models/deploy.rb | 15 ++++++++++ app/models/deploy_distributed_press.rb | 34 +++++++++++++++++++++++ app/models/deploy_local.rb | 38 ++++++++++++++++++-------- 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 app/models/deploy_distributed_press.rb diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 3f034ad5..c7e83539 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -75,6 +75,13 @@ class Deploy < ApplicationRecord r&.success? end + # Variables de entorno + # + # @return [Hash] + def local_env + @local_env ||= {} + end + private # @param [String] @@ -82,4 +89,12 @@ class Deploy < ApplicationRecord def readable_cmd(cmd) cmd.split(' -', 2).first.tr(' ', '_') end + + def deploy_local + @deploy_local ||= site.deploys.find_by(type: 'DeployLocal') + end + + def non_local_deploys + @non_local_deploys ||= site.deploys.where.not(type: 'DeployLocal') + end end diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb new file mode 100644 index 00000000..51788865 --- /dev/null +++ b/app/models/deploy_distributed_press.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Soportar Distributed Press APIv0 +# +# No se realiza ninguna acción porque el deploy se hace desde el plugin +# local. +class DeployDistributedPress < Deploy + store :values, accessors: %i[api_key hostname], coder: JSON + + def deploy; end + + def limit; end + + def size + deploy_local.size + end + + # TODO: Devolver hyper:// y otras + def url + "ipfs://#{hostname}/" + end + + # Devuelve variables de entorno para enviarle a DeployLocal + # + # @return [Hash] + def local_env + { + 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, + 'DISTRIBUTED_PRESS_API_KEY' => api_key + } + end + + def destination; end +end diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 4fa588f5..4b22d728 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -50,21 +50,24 @@ class DeployLocal < Deploy end # Un entorno que solo tiene lo que necesitamos + # + # @return [Hash] def env # XXX: This doesn't support Windows paths :B paths = [File.dirname(`which bundle`), '/usr/bin', '/bin'] - { - 'HOME' => home_dir, - 'PATH' => paths.join(':'), - 'SPREE_API_KEY' => site.tienda_api_key, - 'SPREE_URL' => site.tienda_url, - 'AIRBRAKE_PROJECT_ID' => site.id.to_s, - 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, - 'JEKYLL_ENV' => Rails.env, - 'LANG' => ENV['LANG'], - 'YARN_CACHE_FOLDER' => yarn_cache_dir - } + # Las variables de entorno extra no pueden superponerse al local. + extra_env.merge({ + 'HOME' => home_dir, + 'PATH' => paths.join(':'), + 'SPREE_API_KEY' => site.tienda_api_key, + 'SPREE_URL' => site.tienda_url, + 'AIRBRAKE_PROJECT_ID' => site.id.to_s, + 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, + 'JEKYLL_ENV' => Rails.env, + 'LANG' => ENV['LANG'], + 'YARN_CACHE_FOLDER' => yarn_cache_dir + }) end def yarn_cache_dir @@ -112,4 +115,17 @@ class DeployLocal < Deploy def remove_destination! FileUtils.rm_rf destination end + + # Consigue todas las variables de entorno configuradas por otros + # deploys. + # + # @return [Hash] + def extra_env + @extra_env ||= + non_local_deploys.reduce({}) do |extra_env, deploy| + extra_env.tap do |e| + e.merge! deploy.local_env + end + end + end end From 2dc01cef9c1aedc27a46e4f898fabd216da4e1d1 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Nov 2022 14:13:44 -0300 Subject: [PATCH 006/235] fix: actualizar contenedor a alpine 3.14 #8369 --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index db2b307d..087b2e90 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -23,6 +23,6 @@ pipeline: event: push matrix: include: - - ALPINE_VERSION: 3.13.10 + - ALPINE_VERSION: 3.14.8 RUBY_VERSION: 2.7 RUBY_PATCH: 6 From d05b93d85ef3830e51131a6c09f48f47e2fd164b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 18 Nov 2022 15:56:59 -0300 Subject: [PATCH 007/235] feat: poder modificar la url de distributed press --- app/models/deploy_distributed_press.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 51788865..a24ae62c 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -5,7 +5,7 @@ # No se realiza ninguna acción porque el deploy se hace desde el plugin # local. class DeployDistributedPress < Deploy - store :values, accessors: %i[api_key hostname], coder: JSON + store :values, accessors: %i[api_url api_key hostname], coder: JSON def deploy; end @@ -26,7 +26,8 @@ class DeployDistributedPress < Deploy def local_env { 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, - 'DISTRIBUTED_PRESS_API_KEY' => api_key + 'DISTRIBUTED_PRESS_API_KEY' => api_key, + 'DISTRIBUTED_PRESS_API_URL' => api_url } end From 3ec546eb82890490ad761014a23c6ea157c9fe1d Mon Sep 17 00:00:00 2001 From: f Date: Thu, 29 Dec 2022 14:55:30 -0300 Subject: [PATCH 008/235] fix: dependencias faltantes --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ac90a548..871e6fb0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ ENV RAILS_ENV production # principal RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 \ rsync git jpegoptim vips tectonic oxipng git-lfs openssh-client \ - yarn daemonize ruby-webrick + yarn daemonize ruby-webrick postgresql-client dateutils file RUN gem install --no-document --no-user-install foreman RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz -O - | tar --strip-components 1 -xvzf - pandoc-${PANDOC_VERSION}/bin/pandoc && mv /bin/pandoc /usr/bin/pandoc From 5da4c796e0e9fc3afe0767822e4ed6b78d5feb7c Mon Sep 17 00:00:00 2001 From: Maki Date: Tue, 17 Jan 2023 18:31:54 -0300 Subject: [PATCH 009/235] agrego toggler para distributed press --- app/models/site.rb | 2 +- .../deploys/_deploy_distributed_press.haml | 21 +++++++++++++++++++ config/locales/en.yml | 4 ++++ config/locales/es.yml | 4 ++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 app/views/deploys/_deploy_distributed_press.haml diff --git a/app/models/site.rb b/app/models/site.rb index 638b3f47..fc012d7d 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -17,7 +17,7 @@ class Site < ApplicationRecord # 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].freeze + DEPLOYS = %i[local private www zip hidden_service distributed_press].freeze validates :name, uniqueness: true, hostname: { allow_root_label: true diff --git a/app/views/deploys/_deploy_distributed_press.haml b/app/views/deploys/_deploy_distributed_press.haml new file mode 100644 index 00000000..d7d54db0 --- /dev/null +++ b/app/views/deploys/_deploy_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', public_url: deploy.object.site.url), + tags: %w[p strong em a] + + +%hr/ diff --git a/config/locales/en.yml b/config/locales/en.yml index 530a9381..e7fb4f76 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -248,6 +248,10 @@ en: Only accessible through [Tor Browser](https://www.torproject.org/download/) + deploy_distributed_press: + title: 'Publish on Distributed Press' + help: | + ipfs stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index eaa23137..18cf5326 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -253,6 +253,10 @@ es: Sólo será accesible a través del [Navegador Tor](https://www.torproject.org/es/download/). + deploy_distributed_press: + title: 'Alojar en la web distribuida' + help: | + Es para que esté en la web distribuida stats: index: title: Estadísticas From 67c0b29029d5f8731f0eb82c6b2c8c7d02e333e7 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 18:22:08 -0300 Subject: [PATCH 010/235] feat: almacenar y renovar tokens de distributed press --- Gemfile | 1 + Gemfile.lock | 40 ++++++++++- Procfile | 1 + .../renew_distributed_press_tokens_job.rb | 17 +++++ app/models/distributed_press_publisher.rb | 68 +++++++++++++++++++ ...5420_create_distributed_press_publisher.rb | 14 ++++ lib/tasks/distributed_press.rake | 10 +++ monit.conf | 5 ++ 8 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 app/jobs/renew_distributed_press_tokens_job.rb create mode 100644 app/models/distributed_press_publisher.rb create mode 100644 db/migrate/20230119165420_create_distributed_press_publisher.rb create mode 100644 lib/tasks/distributed_press.rake diff --git a/Gemfile b/Gemfile index 2b304ee0..f317487b 100644 --- a/Gemfile +++ b/Gemfile @@ -38,6 +38,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' +gem 'distributed-press-api-client', '~> 0.2.0' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 8df2d77e..cdfe7183 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,6 +124,7 @@ GEM xpath (>= 2.0, < 4.0) chartkick (4.1.2) childprocess (4.1.0) + climate_control (1.2.0) coderay (1.1.3) colorator (1.1.0) commonmarker (0.21.2-x86_64-linux-musl) @@ -162,12 +163,45 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) + distributed-press-api-client (0.2.0) + addressable (~> 2.3, >= 2.3.0) + climate_control + dry-schema + httparty (~> 0.18) + json (~> 2.1, >= 2.1.0) + jwt (~> 2.6.0) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) down (5.2.4) addressable (~> 2.8) + dry-configurable (1.0.1) + dry-core (~> 1.0, < 2) + zeitwerk (~> 2.6) + dry-core (1.0.0) + concurrent-ruby (~> 1.0) + zeitwerk (~> 2.6) + dry-inflector (1.0.0) + dry-initializer (3.1.1) + dry-logic (1.5.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0, < 2) + zeitwerk (~> 2.6) + dry-schema (1.13.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 1.0, >= 1.0.1) + dry-core (~> 1.0, < 2) + dry-initializer (~> 3.0) + dry-logic (>= 1.5, < 2) + dry-types (>= 1.7, < 2) + zeitwerk (~> 2.6) + dry-types (1.7.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0, < 2) + dry-inflector (~> 1.0, < 2) + dry-logic (>= 1.4, < 2) + zeitwerk (~> 2.6) ed25519 (1.2.4-x86_64-linux-musl) editorial-autogestiva-jekyll-theme (0.3.4) jekyll (~> 4) @@ -244,8 +278,8 @@ GEM thor hiredis (0.6.3-x86_64-linux-musl) http_parser.rb (0.8.0-x86_64-linux-musl) - httparty (0.18.1) - mime-types (~> 3.0) + httparty (0.21.0) + mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) i18n (1.8.11) concurrent-ruby (~> 1.0) @@ -320,6 +354,7 @@ GEM jekyll-write-and-commit-changes (0.2.1) jekyll (~> 4) rugged (~> 1) + jwt (2.6.0) kaminari (1.2.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.1) @@ -669,6 +704,7 @@ DEPENDENCIES devise devise-i18n devise_invitable + distributed-press-api-client (~> 0.2.0) dotenv-rails down ed25519 diff --git a/Procfile b/Procfile index b308ffd5..1a4580d3 100644 --- a/Procfile +++ b/Procfile @@ -5,3 +5,4 @@ blazer_1h: bundle exec rake blazer:run_checks SCHEDULE="1 hour" blazer_1d: bundle exec rake blazer:run_checks SCHEDULE="1 day" blazer: bundle exec rake blazer:send_failing_checks prometheus: bundle exec prometheus_exporter -b 0.0.0.0 --prefix "sutty_" +distributed_press_renew_tokens: bundle exec rake distributed_press:tokens:renew diff --git a/app/jobs/renew_distributed_press_tokens_job.rb b/app/jobs/renew_distributed_press_tokens_job.rb new file mode 100644 index 00000000..5664d9fa --- /dev/null +++ b/app/jobs/renew_distributed_press_tokens_job.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Renueva los tokens de Distributed Press antes que se venzan, +# activando los callbacks que hacen que se refresque el token. +class RenewDistributedPressTokensJob < ApplicationJob + # Renueva todos los tokens a punto de vencer o informa el error sin + # detener la tarea si algo pasa. + def perform + DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher| + publisher.touch + rescue DistributedPress::V1::Error => e + data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at } + + ExceptionNotifier.notify_exception(e, data: data) + end + end +end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb new file mode 100644 index 00000000..c120811e --- /dev/null +++ b/app/models/distributed_press_publisher.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'distributed_press/v1' + +# Almacena el token de autenticación y la URL, por ahora solo vamos +# a tener uno, pero queda abierta la posibilidad de agregar más. +class DistributedPressPublisher < ApplicationRecord + # Cifrar la información del token en la base de datos + has_encrypted :token + + # La instancia es única + validates_uniqueness_of :instance + + # El token es necesario + validates_presence_of :token + + # Mantener la fecha de vencimiento actualizada + before_save :update_expires_at_from_token!, :update_token_from_client! + + # Devuelve todos los tokens que vencen en una hora + scope :with_about_to_expire_tokens, -> do + where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour) + end + + # Al cambiar el token genera un cliente nuevo + # + # @return [String] + def token=(new_token) + @client = nil + super + end + + # Al cambiar la instancia genera un cliente nuevo + # + # @return [String] + def instance=(new_instance) + @client = nil + super + end + + # Instancia un cliente de Distributed Press a partir del token. Al + # cargar un token a punto de vencer se renueva automáticamente. + # + # @return [DistributedPress::V1::Client] + def client + @client ||= DistributedPress::V1::Client.new(url: instance, token: token) + end + + private + + # Actualiza o desactiva la fecha de vencimiento a partir de la + # información del token. + # + # @return [nil] + def update_expires_at_from_token! + self.expires_at = client.token.forever? ? nil : client.token.expires_at + nil + end + + # Actualiza el token a partir del cliente, que ya actualiza el token + # automáticamente. + # + # @return [nil] + def update_token_from_client! + self.token = client.token.to_s + nil + end +end diff --git a/db/migrate/20230119165420_create_distributed_press_publisher.rb b/db/migrate/20230119165420_create_distributed_press_publisher.rb new file mode 100644 index 00000000..8d8de37a --- /dev/null +++ b/db/migrate/20230119165420_create_distributed_press_publisher.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Crea la tabla de publishers de Distributed Press que contiene las +# instancias y tokens +class CreateDistributedPressPublisher < ActiveRecord::Migration[6.1] + def change + create_table :distributed_press_publishers do |t| + t.timestamps + t.string :instance, unique: true + t.text :token_ciphertext, null: false + t.datetime :expires_at, null: true + end + end +end diff --git a/lib/tasks/distributed_press.rake b/lib/tasks/distributed_press.rake new file mode 100644 index 00000000..8ba270ec --- /dev/null +++ b/lib/tasks/distributed_press.rake @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +namespace :distributed_press do + namespace :tokens do + desc 'Renew tokens' + task renew: :environment do + RenewDistributedPressTokensJob.perform_now + end + end +end diff --git a/monit.conf b/monit.conf index 96c08d8a..b785964d 100644 --- a/monit.conf +++ b/monit.conf @@ -25,3 +25,8 @@ check program blazer with path "/usr/local/bin/sutty blazer" every 61 cycles if status != 0 then alert + +check program distributed_press_tokens_renew + with path "/usr/bin/foreman run -f /srv/Procfile -d /srv distributed_press_tokens_renew" as uid "rails" gid "www-data" + every "0 3 * * *" + if status != 0 then alert From cbf7b5892746b544668c6043915da783a13b00d0 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 18:28:29 -0300 Subject: [PATCH 011/235] fixup! feat: almacenar y renovar tokens de distributed press --- app/models/distributed_press_publisher.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index c120811e..610d698d 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -18,9 +18,9 @@ class DistributedPressPublisher < ApplicationRecord before_save :update_expires_at_from_token!, :update_token_from_client! # Devuelve todos los tokens que vencen en una hora - scope :with_about_to_expire_tokens, -> do + scope :with_about_to_expire_tokens, lambda { where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour) - end + } # Al cambiar el token genera un cliente nuevo # From 932355fa2e331ac7e4bf142e21b1b879aa161a39 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 20:34:27 -0300 Subject: [PATCH 012/235] feat: crear y publicar el sitio en distributed press v1 --- app/models/deploy_distributed_press.rb | 143 ++++++++++++++++++---- app/models/distributed_press_publisher.rb | 5 + 2 files changed, 125 insertions(+), 23 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index a24ae62c..09ba0364 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,13 +1,43 @@ # frozen_string_literal: true -# Soportar Distributed Press APIv0 -# -# No se realiza ninguna acción porque el deploy se hace desde el plugin -# local. -class DeployDistributedPress < Deploy - store :values, accessors: %i[api_url api_key hostname], coder: JSON +require 'distributed_press/v1/client/auth' +require 'distributed_press/v1/client/site' - def deploy; end +# Soportar Distributed Press APIv1 +# +# Usa tokens de publicación efímeros para todas las acciones. +# +# Al ser creado, genera el sitio en la instancia de Distributed Press +# configurada y almacena el ID. +# +# Al ser publicado, envía los archivos en un tarball y actualiza la +# información. +class DeployDistributedPress < Deploy + store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON + + before_create :create_remote_site! + + # Actualiza la información y luego envía los cambios + # + # @param :output [Bool] + # @return [Bool] + def deploy + time_start + + status = false + + site_client.tap do |c| + update remote_info: c.show(publishing_site).to_h + + status = c.publish(publishing_site, deploy_local.destination) + end + + time_stop + + create_stat! status + + status + end def limit; end @@ -15,21 +45,88 @@ class DeployDistributedPress < Deploy deploy_local.size end - # TODO: Devolver hyper:// y otras - def url - "ipfs://#{hostname}/" - end - - # Devuelve variables de entorno para enviarle a DeployLocal - # - # @return [Hash] - def local_env - { - 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, - 'DISTRIBUTED_PRESS_API_KEY' => api_key, - 'DISTRIBUTED_PRESS_API_URL' => api_url - } - end - def destination; end + + private + + # El cliente de la API + # + # TODO: cuando soportemos más, tiene que haber una relación entre + # DeployDistributedPress y DistributedPressPublisher. + # + # @return [DistributedPressPublisher] + def publisher + @publisher ||= DistributedPressPublisher.first + end + + # El cliente de autenticación se encarga de intercambiar un token por + # otro + # + # @return [DistributedPress::V1::Client::Auth] + def auth_client + DistributedPress::V1::Client::Auth.new(publisher.client) + end + + # Genera un token con permisos de publicación + # + # @return [DistributedPress::V1::Schemas::NewTokenPayload] + def publishing_token_payload + DistributedPress::V1::Schemas::NewTokenPayload.new.call(capabilities: %w[publisher]) + end + + # Genera un token efímero para publicar el sitio + # + # @return [DistributedPress::V1::Token] + def publishing_token + auth_client.exchange(publishing_token_payload) + end + + # Genera un cliente para publicar el sitio + # + # @return [DistributedPress::V1::Client] + def publishing_client + DistributedPress::V1::Client.new(url: publisher.instance, token: publishing_token) + end + + # El cliente para actualizar el sitio + # + # @return [DistributedPress::V1::Client::Site] + def site_client + DistributedPress::V1::Client::Site.new(publishing_client) + end + + # Genera el esquema de datos para poder publicar el sitio + # + # @return [DistributedPress::V1::Schemas::PublishingSite] + def publishing_site + DistributedPress::V1::Schemas::PublishingSite.new.call(id: remote_site_id) + end + + # Genera el esquema de datos para crear el sitio + # + # @return [DistributedPressPublisher::V1::Schemas::NewSite] + def create_site + DistributedPress::V1::Schemas::NewSite.new.call(domain: hostname, protocols: { http: true, ipfs: true, hyper: true }) + end + + # Crea el sitio en la instancia con el hostname especificado + # + # @return [nil] + def create_remote_site! + created_site = site_client.create(create_site) + + self.remote_site_id = created_site[:id] + self.remote_info = created_site.to_h + + nil + end + + # Registra lo que sucedió + # + # @param status [Bool] + # @return [nil] + def create_stat!(status) + build_stats.create action: publisher.to_s, seconds: time_spent_in_seconds, bytes: size, status: status + nil + end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 610d698d..5358e738 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -46,6 +46,11 @@ class DistributedPressPublisher < ApplicationRecord @client ||= DistributedPress::V1::Client.new(url: instance, token: token) end + # @return [String] + def to_s + "Distributed Press <#{instance}>" + end + private # Actualiza o desactiva la fecha de vencimiento a partir de la From 8006bd03538dee1285ef7746db382958b6cabce7 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 20:35:39 -0300 Subject: [PATCH 013/235] fix: permitir modificar el token estos parches hacian que no se pueda modificar el token --- app/models/distributed_press_publisher.rb | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 5358e738..acfc4226 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -22,22 +22,6 @@ class DistributedPressPublisher < ApplicationRecord where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour) } - # Al cambiar el token genera un cliente nuevo - # - # @return [String] - def token=(new_token) - @client = nil - super - end - - # Al cambiar la instancia genera un cliente nuevo - # - # @return [String] - def instance=(new_instance) - @client = nil - super - end - # Instancia un cliente de Distributed Press a partir del token. Al # cargar un token a punto de vencer se renueva automáticamente. # From b28d7946460d8bed6400a6f13d6f0911a12a8f53 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 23 Jan 2023 18:39:10 -0300 Subject: [PATCH 014/235] =?UTF-8?q?feat:=20no=20vamos=20a=20expedir=20toke?= =?UTF-8?q?ns=20ef=C3=ADmeros=20por=20ahora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 31 +------------------------- 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 09ba0364..38cb59e3 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -59,40 +59,11 @@ class DeployDistributedPress < Deploy @publisher ||= DistributedPressPublisher.first end - # El cliente de autenticación se encarga de intercambiar un token por - # otro - # - # @return [DistributedPress::V1::Client::Auth] - def auth_client - DistributedPress::V1::Client::Auth.new(publisher.client) - end - - # Genera un token con permisos de publicación - # - # @return [DistributedPress::V1::Schemas::NewTokenPayload] - def publishing_token_payload - DistributedPress::V1::Schemas::NewTokenPayload.new.call(capabilities: %w[publisher]) - end - - # Genera un token efímero para publicar el sitio - # - # @return [DistributedPress::V1::Token] - def publishing_token - auth_client.exchange(publishing_token_payload) - end - - # Genera un cliente para publicar el sitio - # - # @return [DistributedPress::V1::Client] - def publishing_client - DistributedPress::V1::Client.new(url: publisher.instance, token: publishing_token) - end - # El cliente para actualizar el sitio # # @return [DistributedPress::V1::Client::Site] def site_client - DistributedPress::V1::Client::Site.new(publishing_client) + DistributedPress::V1::Client::Site.new(publisher.client) end # Genera el esquema de datos para poder publicar el sitio From ebf1390bdf962c49f2fab7a914a3944060c0c461 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Jan 2023 15:41:54 -0300 Subject: [PATCH 015/235] fix: actualizar api --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index cdfe7183..534ad298 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -163,7 +163,7 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) - distributed-press-api-client (0.2.0) + distributed-press-api-client (0.2.1) addressable (~> 2.3, >= 2.3.0) climate_control dry-schema From 928bc45920cfbf10a46e088ccbbcece043d24dd5 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 6 Feb 2023 16:09:51 -0300 Subject: [PATCH 016/235] feat: usar pnpm si existe relacionado con sutty/jekyll/sutty-base-jekyll-theme#53 --- Dockerfile | 2 ++ app/models/deploy_local.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Dockerfile b/Dockerfile index ecf43cbc..b2f96612 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,8 @@ RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 \ RUN gem install --no-document --no-user-install foreman RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz -O - | tar --strip-components 1 -xvzf - pandoc-${PANDOC_VERSION}/bin/pandoc && mv /bin/pandoc /usr/bin/pandoc +RUN apk add npm && npm install -g pnpm && apk del npm + VOLUME "/srv" EXPOSE 3000 diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 4b22d728..51baf492 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -15,6 +15,7 @@ class DeployLocal < Deploy def deploy return false unless mkdir return false unless yarn + return false unless pnpm return false unless bundle jekyll_build @@ -74,6 +75,10 @@ class DeployLocal < Deploy Rails.root.join('_yarn_cache').to_s end + def pnpm_cache_dir + Rails.root.join('_pnpm_cache').to_s + end + def yarn_lock File.join(site.path, 'yarn.lock') end @@ -82,6 +87,14 @@ class DeployLocal < Deploy File.exist? yarn_lock end + def pnpm_lock + File.join(site.path, 'pnpm-lock.yaml') + end + + def pnpm_lock? + File.exist? pnpm_lock + end + def gem run %(gem install bundler --no-document) end @@ -93,6 +106,13 @@ class DeployLocal < Deploy run 'yarn install --production' end + def pnpm + return true unless pnpm_lock? + + run %(pnpm config set store-dir "#{pnpm_cache_dir}") + run 'pnpm install --production' + end + def bundle if Rails.env.production? run %(bundle install --no-cache --path="#{gems_dir}") From a73100a436a283533236989c58f162c0fe8dbd4f Mon Sep 17 00:00:00 2001 From: f Date: Mon, 6 Feb 2023 16:16:27 -0300 Subject: [PATCH 017/235] fix: pnpm se instala localmente --- app/models/deploy_local.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 51baf492..e4845d7c 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -55,7 +55,7 @@ class DeployLocal < Deploy # @return [Hash] def env # XXX: This doesn't support Windows paths :B - paths = [File.dirname(`which bundle`), '/usr/bin', '/bin'] + paths = [File.dirname(`which bundle`), '/usr/local/bin', '/usr/bin', '/bin'] # Las variables de entorno extra no pueden superponerse al local. extra_env.merge({ From 464ff4841b68affaa694ab0e8e348035cf565a38 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 7 Feb 2023 18:15:25 -0300 Subject: [PATCH 018/235] feat: textos para el panel --- config/locales/en.yml | 16 ++++++++++++++-- config/locales/es.yml | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index e7fb4f76..2bbf58ea 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -249,9 +249,21 @@ en: Only accessible through [Tor Browser](https://www.torproject.org/download/) deploy_distributed_press: - title: 'Publish on Distributed Press' + title: 'Publish to the distributed Web' help: | - ipfs + Make your site available through peer-to-peer protocols, + Inter-Planetary File System (IPFS), Hypercore, and via + BitTorrent, so your site is more resilient and can be available + offline, including in community mesh networks. + + **Important:** Only use this option if you would like your data + to be permanently available. If you decide to undo this + selection, a cleared version of the site will be shared in its + place. However, it is possible that nodes on the distributed + storage network may continue retaining copies of the data + indefinitely. + + [Learn more](#) stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index 18cf5326..e3b24957 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -254,9 +254,21 @@ es: Sólo será accesible a través del [Navegador Tor](https://www.torproject.org/es/download/). deploy_distributed_press: - title: 'Alojar en la web distribuida' + title: 'Publicar a la Web distribuida' help: | - Es para que esté en la web distribuida + Utiliza protocolos de pares, Inter-Planetary File System (IPFS), + Hypercore y torrents, para que tu sitio sea más resiliente y + esté disponible _offline_, inclusive en redes _mesh_ + comunitarias. + + **Importante:** Sólo usa esta opción si te parece correcto que + tu contenido esté disponible permanentemente. Cuando elijas + des-hacer esta acción, una versión "vacía" del sitio será + compartida en su lugar. Sin embargo, es posible que algunos + nodos en la red de almacenamiento distribuida puedan retener + copias de tu contenido indefinidamente. + + [Saber más](#) stats: index: title: Estadísticas From 9661a34a04396c647f5ad1fe5d6ea75fc3b513ac Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 09:38:36 -0300 Subject: [PATCH 019/235] fix: faltaban algunos require --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index f317487b..694358a6 100644 --- a/Gemfile +++ b/Gemfile @@ -38,7 +38,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' -gem 'distributed-press-api-client', '~> 0.2.0' +gem 'distributed-press-api-client', '~> 0.2.1' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 534ad298..5c074a7b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -704,7 +704,7 @@ DEPENDENCIES devise devise-i18n devise_invitable - distributed-press-api-client (~> 0.2.0) + distributed-press-api-client (~> 0.2.1) dotenv-rails down ed25519 From 6683f80aba504c2edca9bcb4ca5f3ce4f24eba9c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 11:55:07 -0300 Subject: [PATCH 020/235] fix: no fallar si tarda mucho dp --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 694358a6..7f4cc6ca 100644 --- a/Gemfile +++ b/Gemfile @@ -38,7 +38,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' -gem 'distributed-press-api-client', '~> 0.2.1' +gem 'distributed-press-api-client', '~> 0.2.2' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 5c074a7b..b5b6fd18 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -163,7 +163,7 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) - distributed-press-api-client (0.2.1) + distributed-press-api-client (0.2.2) addressable (~> 2.3, >= 2.3.0) climate_control dry-schema @@ -704,7 +704,7 @@ DEPENDENCIES devise devise-i18n devise_invitable - distributed-press-api-client (~> 0.2.1) + distributed-press-api-client (~> 0.2.2) dotenv-rails down ed25519 From ccfd77d9568dce55ea8ce29ea114b2487f7bc0b9 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 17:08:02 -0300 Subject: [PATCH 021/235] =?UTF-8?q?feat:=20guardar=20un=20log=20y=20mostra?= =?UTF-8?q?rlo=20en=20output=20tambi=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 24 ++++++++++++++++++----- app/models/distributed_press_publisher.rb | 22 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 38cb59e3..d805e923 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -22,19 +22,32 @@ class DeployDistributedPress < Deploy # @param :output [Bool] # @return [Bool] def deploy + status = false + log = [] + time_start - status = false - site_client.tap do |c| + stdout = Thread.new(publisher.logger_out) do |io| + until io.eof? + line = io.gets + + puts line if output + log << line + end + end + update remote_info: c.show(publishing_site).to_h status = c.publish(publishing_site, deploy_local.destination) + + publisher.logger.close + stdout.join end time_stop - create_stat! status + create_stat! status, log.join status end @@ -95,9 +108,10 @@ class DeployDistributedPress < Deploy # Registra lo que sucedió # # @param status [Bool] + # @param log [String] # @return [nil] - def create_stat!(status) - build_stats.create action: publisher.to_s, seconds: time_spent_in_seconds, bytes: size, status: status + def create_stat!(status, log) + build_stats.create action: publisher.to_s,log: log, seconds: time_spent_in_seconds, bytes: size, status: status nil end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index acfc4226..089f63c6 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -8,6 +8,11 @@ class DistributedPressPublisher < ApplicationRecord # Cifrar la información del token en la base de datos has_encrypted :token + # La salida del log + # + # @return [IO] + attr_reader :logger_out + # La instancia es única validates_uniqueness_of :instance @@ -27,7 +32,7 @@ class DistributedPressPublisher < ApplicationRecord # # @return [DistributedPress::V1::Client] def client - @client ||= DistributedPress::V1::Client.new(url: instance, token: token) + @client ||= DistributedPress::V1::Client.new(url: instance, token: token, logger: logger) end # @return [String] @@ -35,8 +40,23 @@ class DistributedPressPublisher < ApplicationRecord "Distributed Press <#{instance}>" end + # @return [Logger] + def logger + @logger ||= + begin + @logger_out, @logger_in = IO.pipe + ::Logger.new @logger_in, formatter: formatter + end + end + private + def formatter + @formatter ||= lambda do |_, _, _, msg| + "#{msg}\n" + end + end + # Actualiza o desactiva la fecha de vencimiento a partir de la # información del token. # From 89f5ed90ebe60b2b9132c8bdad1e9ee3a310e970 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 17:44:35 -0300 Subject: [PATCH 022/235] =?UTF-8?q?fix:=20link=20a=20saber=20m=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 2 +- config/locales/es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 2bbf58ea..f37afa7c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -263,7 +263,7 @@ en: storage network may continue retaining copies of the data indefinitely. - [Learn more](#) + [Learn more](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/) stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index e3b24957..fef3b6eb 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -268,7 +268,7 @@ es: nodos en la red de almacenamiento distribuida puedan retener copias de tu contenido indefinidamente. - [Saber más](#) + [Saber más (en inglés)](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/) stats: index: title: Estadísticas From 15e6696bcf7b645b59a246c8fcd908db9671ad74 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 18:49:37 -0300 Subject: [PATCH 023/235] feat: un deploy puede tener varias urls --- app/models/deploy_distributed_press.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index d805e923..d3474d50 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -60,6 +60,15 @@ class DeployDistributedPress < Deploy def destination; end + # Devuelve las URLs de todos los protocolos + def urls + remote_info[:links].values.map do |protocol| + [ protocol[:link], protocol[:gateway] ] + end.flatten.compact.select do |link| + link.include? '://' + end + end + private # El cliente de la API From 7ff284d547cd8e0ce8f0f30d4172db182e439430 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 18:52:48 -0300 Subject: [PATCH 024/235] =?UTF-8?q?feat:=20texto=20para=20el=20correo=20de?= =?UTF-8?q?=20notificaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 4 ++++ config/locales/es.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index f37afa7c..ac8d7289 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -102,6 +102,10 @@ en: title: Alternative domain name success: Success! error: Error + deploy_distributed_press: + title: Distributed Web + success: Success! + error: Error help: You can contact us by replying to this e-mail maintenance_mailer: notice: diff --git a/config/locales/es.yml b/config/locales/es.yml index fef3b6eb..335fca66 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -102,6 +102,10 @@ es: title: Dominio alternativo success: ¡Éxito! error: Hubo un error + deploy_distributed_press: + title: Web distribuida + success: ¡Éxito! + error: Hubo un error help: Por cualquier duda, responde este correo para contactarte con nosotres. maintenance_mailer: notice: From 3f7b2484d04bee63bff7877f746721703043e217 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:01:22 -0300 Subject: [PATCH 025/235] feat: crear temporalmente los dominios en njalla el problema es que no podemos delegar `_dnslink.*.sutty.nl` hacia distributed press, con lo que es necesario crear un subdominio por cada sitio que lo active. --- Gemfile | 1 + Gemfile.lock | 4 ++++ app/models/deploy_distributed_press.rb | 18 ++++++++++++++++++ app/models/distributed_press_publisher.rb | 7 +++++++ 4 files changed, 30 insertions(+) diff --git a/Gemfile b/Gemfile index 7f4cc6ca..8f742348 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,7 @@ gem 'devise' gem 'devise-i18n' gem 'devise_invitable' gem 'distributed-press-api-client', '~> 0.2.2' +gem 'njalla-api-client' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index b5b6fd18..6469b2db 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -419,6 +419,9 @@ GEM nokogiri (1.12.5-x86_64-linux-musl) mini_portile2 (~> 2.6.1) racc (~> 1.4) + njalla-api-client (0.1.0) + dry-schema + httparty (~> 0.18) orm_adapter (0.5.0) parallel (1.21.0) parser (3.0.2.0) @@ -741,6 +744,7 @@ DEPENDENCIES minima mobility net-ssh + njalla-api-client nokogiri pg pg_search diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index d3474d50..6f2b2c78 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -111,6 +111,12 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h + # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay + # que eliminarlo. + self.remote_info['njalla'] = {} + self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + nil end @@ -123,4 +129,16 @@ class DeployDistributedPress < Deploy build_stats.create action: publisher.to_s,log: log, seconds: time_spent_in_seconds, bytes: size, status: status nil end + + # Actualizar registros en Njalla + # + # @return [Njalla::V1::Domain] + def njalla + @njalla ||= + begin + client = Njalla::V1::Client.new(token: ENV['NJALLA_TOKEN']) + + Njalla::V1::Domain.new(domain: Site.domain, client: client) + end + end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 089f63c6..6139db93 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -40,6 +40,13 @@ class DistributedPressPublisher < ApplicationRecord "Distributed Press <#{instance}>" end + # Devuelve el hostname de la instancia + # + # @return [String] + def hostname + @hostname ||= URI.parse(instance).hostname + end + # @return [Logger] def logger @logger ||= From a849eac17962a645a70b8fd5b5546aa8d285a46e Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:08:56 -0300 Subject: [PATCH 026/235] fix: no crear subdominios para dominios personalizados esto es por retrocompatibilidad para sitios que no usan DeployAlternativeDomain --- app/models/deploy_distributed_press.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 6f2b2c78..1ae7a2f2 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -113,9 +113,11 @@ class DeployDistributedPress < Deploy # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay # que eliminarlo. - self.remote_info['njalla'] = {} - self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + unless site.name.end_with? '.' + self.remote_info['njalla'] = {} + self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + end nil end From a3c1d7193f8112006cffa60f830e38d9e8d669f2 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:11:17 -0300 Subject: [PATCH 027/235] fix: requires --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 1ae7a2f2..41054b99 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'distributed_press/v1/client/auth' require 'distributed_press/v1/client/site' +require 'njalla/v1' # Soportar Distributed Press APIv1 # From 8a5ecd98f75a9fcffefa68f8d0f9cb7516aa13c3 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:31:16 -0300 Subject: [PATCH 028/235] fix: legible data, remove log section --- app/jobs/gitlab_notifier_job.rb | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 701c6789..5d9baa9e 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -112,7 +112,6 @@ class GitlabNotifierJob < ApplicationJob # @return [String] def description @description ||= ''.dup.tap do |d| - d << log_section d << request_section d << javascript_section d << javascript_footer @@ -160,19 +159,6 @@ class GitlabNotifierJob < ApplicationJob @client ||= GitlabApiClient.new end - # @return [String] - def log_section - return '' unless options[:log] - - <<~LOG - # Log - - ``` - #{options[:log]} - ``` - LOG - end - # Muestra información de la petición # # @return [String] @@ -257,8 +243,8 @@ class GitlabNotifierJob < ApplicationJob ## Data - ``` - #{pp options[:data]} + ```yaml + #{options[:data].to_yaml} ``` DATA From df3faba784dd47542101175a0d9aacc8606e31a8 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:31:39 -0300 Subject: [PATCH 029/235] fix: send sucker punch args --- config/initializers/sucker_punch.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/initializers/sucker_punch.rb b/config/initializers/sucker_punch.rb index 865af32d..19506c2d 100644 --- a/config/initializers/sucker_punch.rb +++ b/config/initializers/sucker_punch.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true # Enviar una notificación cuando falla una tarea -SuckerPunch.exception_handler = lambda { |ex, _klass, _args| - ExceptionNotifier.notify_exception(ex) +SuckerPunch.exception_handler = lambda { |ex, _, args| + ExceptionNotifier.notify_exception(ex, data: args) } From 72f982ee7646b211e16a50d04fc41a0e1346efae Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:42:40 -0300 Subject: [PATCH 030/235] fix: no fallar la segunda vez que se reporta el issue --- app/jobs/gitlab_notifier_job.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 5d9baa9e..d84ecda2 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -37,7 +37,7 @@ class GitlabNotifierJob < ApplicationJob } end - unless @issue['iid'] + if @issue['iid'].blank? && issue_data[:issue].blank? Rails.cache.delete(cache_key) raise GitlabNotifierError, @issue.dig('message', 'title')&.join(', ') end @@ -62,7 +62,7 @@ class GitlabNotifierJob < ApplicationJob # Si este trabajo genera una excepción va a entrar en un loop, así que # la notificamos por correo rescue Exception => e - email_notification.call(e) + email_notification.call(e, data: @issue) email_notification.call(exception, options) end From 347aba67287fedae424c0d52c2728e84a1dec2c2 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:47:54 -0300 Subject: [PATCH 031/235] feat: seccion de log --- app/jobs/gitlab_notifier_job.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index d84ecda2..a127beaf 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -112,6 +112,7 @@ class GitlabNotifierJob < ApplicationJob # @return [String] def description @description ||= ''.dup.tap do |d| + d << log_section d << request_section d << javascript_section d << javascript_footer @@ -159,6 +160,21 @@ class GitlabNotifierJob < ApplicationJob @client ||= GitlabApiClient.new end + # @return [String] + def log_section + return if unless options.dig(:data, :log) + + <<~LOG + + # Build log + + ``` + #{option[:data].delete(:log)} + ``` + + LOG + end + # Muestra información de la petición # # @return [String] From 3764e14812309863a194a38efb17013414c3f88d Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:49:00 -0300 Subject: [PATCH 032/235] fixup! feat: seccion de log --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index a127beaf..7c785126 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -162,7 +162,7 @@ class GitlabNotifierJob < ApplicationJob # @return [String] def log_section - return if unless options.dig(:data, :log) + return '' unless options.dig(:data, :log) <<~LOG From 5fe0efeccd7dd1fb9a16f8d89f0d448528934cb0 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:50:14 -0300 Subject: [PATCH 033/235] fixup! fixup! feat: seccion de log --- app/jobs/gitlab_notifier_job.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 7c785126..64caf977 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -126,6 +126,7 @@ class GitlabNotifierJob < ApplicationJob # @return [String] def body @body ||= ''.dup.tap do |b| + d << log_section b << request_section b << javascript_footer b << data_section From d166e669b7ce0e32ce9a0da07900f1dc675d992d Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:51:28 -0300 Subject: [PATCH 034/235] fixup! fixup! fixup! feat: seccion de log --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 64caf977..edc6cf63 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -126,7 +126,7 @@ class GitlabNotifierJob < ApplicationJob # @return [String] def body @body ||= ''.dup.tap do |b| - d << log_section + b << log_section b << request_section b << javascript_footer b << data_section From b552b0fecd8be260f06cc9c5e6a300cc87a557fe Mon Sep 17 00:00:00 2001 From: f Date: Mon, 13 Mar 2023 20:52:30 -0300 Subject: [PATCH 035/235] fixup! fixup! fixup! fixup! feat: seccion de log --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index edc6cf63..c8daf220 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -170,7 +170,7 @@ class GitlabNotifierJob < ApplicationJob # Build log ``` - #{option[:data].delete(:log)} + #{options[:data].delete(:log)} ``` LOG From 5822a9b661eecc331f422fb22c5b8365516522d2 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 16:10:59 -0300 Subject: [PATCH 036/235] =?UTF-8?q?fix:=20enviar=20m=C3=A1s=20informaci?= =?UTF-8?q?=C3=B3n=20con=20el=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #10064 closes #10065 closes #10066 closes #10067 closes #10068 closes #10069 closes #10070 closes #10071 closes #10072 closes #10073 closes #10074 closes #10075 closes #10076 closes #10077 closes #10078 closes #10079 closes #10080 closes #10081 closes #10082 closes #10083 closes #10084 closes #10085 closes #10086 closes #10087 closes #10088 closes #10089 closes #10090 closes #10091 closes #10092 closes #10093 closes #10094 closes #10095 closes #10096 closes #10097 closes #10098 closes #10099 closes #10100 closes #10101 closes #10102 closes #10103 closes #10104 closes #10105 closes #10106 closes #10107 closes #10108 closes #10109 closes #10110 closes #10111 closes #10112 closes #10113 closes #10114 closes #10115 closes #10116 closes #10117 closes #10118 closes #10119 closes #10120 closes #10121 closes #10122 closes #10123 closes #10124 closes #10125 closes #10126 closes #10127 closes #10128 closes #10129 closes #10130 closes #10131 closes #10132 closes #10133 closes #10134 closes #10135 closes #10136 closes #10137 closes #10138 closes #10139 closes #10140 closes #10141 closes #10142 closes #10143 closes #10144 closes #10145 closes #10146 closes #10147 closes #10148 closes #10149 closes #10150 closes #10151 closes #10152 closes #10153 closes #10154 closes #10155 closes #10156 closes #10157 closes #10158 closes #10159 closes #10160 closes #10161 closes #10162 closes #10163 closes #10164 closes #10165 closes #10166 closes #10167 closes #10168 closes #10169 closes #10170 closes #10171 closes #10172 closes #10173 closes #10174 closes #10175 closes #10176 closes #10177 closes #10178 closes #10179 closes #10180 closes #10181 closes #10182 closes #10183 closes #10184 closes #10185 closes #10186 closes #10187 closes #10188 closes #10189 closes #10190 closes #10191 closes #10192 closes #10193 closes #10194 closes #10195 closes #10196 closes #10197 closes #10198 closes #10199 closes #10200 closes #10201 closes #10202 closes #10203 closes #10204 closes #10205 closes #10206 closes #10207 closes #10208 closes #10209 closes #10210 closes #10211 closes #10212 closes #10213 closes #10214 closes #10215 closes #10216 closes #10217 closes #10218 closes #10219 closes #10220 closes #10221 closes #10222 closes #10223 closes #10224 closes #10225 closes #10226 closes #10227 closes #10228 closes #10229 closes #10230 closes #10231 closes #10232 closes #10234 closes #10235 closes #10236 closes #10237 closes #10238 closes #10239 closes #10240 closes #10241 closes #10242 closes #10243 closes #10244 --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index c8daf220..11d4274a 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -63,7 +63,7 @@ class GitlabNotifierJob < ApplicationJob # la notificamos por correo rescue Exception => e email_notification.call(e, data: @issue) - email_notification.call(exception, options) + email_notification.call(exception, data: options) end private From 6f363f2c358a63d6ad74c2c0d962ca93f148c06b Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 16:16:46 -0300 Subject: [PATCH 037/235] fix: params a veces es un array?? --- app/jobs/gitlab_notifier_job.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 11d4274a..291112a5 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -84,10 +84,14 @@ class GitlabNotifierJob < ApplicationJob exception.class.name, Digest::SHA1.hexdigest(exception.message), Digest::SHA1.hexdigest(backtrace&.first.to_s), - Digest::SHA1.hexdigest(options.dig(:data, :params, 'errors').to_s) + Digest::SHA1.hexdigest(errors.to_s) ].join('/') end + def errors + options.dig(:data, :params, 'errors') if options.dig(:data, :params).is_a? Hash + end + # Define si es una excepción de javascript o local # # @see BacktraceJob From bbd19f44aee1686defc5039df36378ff8bc75c89 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 25 Jan 2023 14:27:14 -0300 Subject: [PATCH 038/235] ci: compilar assets cuando cambian las dependencias --- .woodpecker.yml | 17 +++++++++++++++++ package.json | 1 + 2 files changed, 18 insertions(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index 087b2e90..b3406f39 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,4 +1,21 @@ pipeline: + assets: + image: "registry.nulo.in/sutty/panel:3.14.8-2.7.6" + commands: + - "apk add python2" + - "yarn" + - "RAILS_GROUPS=assets bundle install --path=vendor" + - "RAILS_GROUPS=assets bundle exec rails assets:precompile assets:clean" + - "git add assets && git commit -m \"[skip ci] JS\" || true" + when: + branch: + - "rails" + - "panel.sutty.nl" + path: + include: + - "app/assets/**/*" + - "package.json" + - "yarn.lock" publish: image: plugins/docker settings: diff --git a/package.json b/package.json index d520c8f5..6a5f159f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "sutty", + "author": "Sutty ", "private": true, "dependencies": { "@airbrake/browser": "^1.4.1", From 1b0c3cb0acf7d6aca045b253e2022065e60a152b Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:11:18 -0300 Subject: [PATCH 039/235] ci: compilar en cambios de javascript tambien --- .woodpecker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index b3406f39..a2289c12 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -14,6 +14,7 @@ pipeline: path: include: - "app/assets/**/*" + - "app/javascript/**/*" - "package.json" - "yarn.lock" publish: From 0b63ebdd278051ba1b3b5c29fec87b67a6cedb60 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:15:26 -0300 Subject: [PATCH 040/235] chore: yaml --- .woodpecker.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index a2289c12..de760284 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -18,29 +18,29 @@ pipeline: - "package.json" - "yarn.lock" publish: - image: plugins/docker + image: "plugins/docker" settings: - registry: registry.nulo.in - username: sutty - repo: registry.nulo.in/sutty/panel + registry: "registry.nulo.in" + username: "sutty" + repo: "registry.nulo.in/sutty/panel" tags: - - ${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH} - - latest + - "${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" + - "latest" build_args: - - RUBY_VERSION=${RUBY_VERSION} - - RUBY_PATCH=${RUBY_PATCH} - - ALPINE_VERSION=${ALPINE_VERSION} - - BASE_IMAGE=registry.nulo.in/sutty/rails + - "RUBY_VERSION=${RUBY_VERSION}" + - "RUBY_PATCH=${RUBY_PATCH}" + - "ALPINE_VERSION=${ALPINE_VERSION}" + - "BASE_IMAGE=registry.nulo.in/sutty/rails" purge: false secrets: - - docker_password + - "docker_password" when: branch: - - rails - - panel.sutty.nl - event: push + - "rails" + - "panel.sutty.nl" + event: "push" matrix: include: - - ALPINE_VERSION: 3.14.8 - RUBY_VERSION: 2.7 - RUBY_PATCH: 6 + - ALPINE_VERSION: "3.14.8" + RUBY_VERSION: "2.7" + RUBY_PATCH: "6" From 6d25d71dd13d2dda59f7b8ae493cac597de383aa Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:17:16 -0300 Subject: [PATCH 041/235] fix: solo compilar el container cuando cambia --- .woodpecker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index de760284..aef70024 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -39,6 +39,10 @@ pipeline: - "rails" - "panel.sutty.nl" event: "push" + path: + include: + - "Dockerfile" + - ".dockerignore" matrix: include: - ALPINE_VERSION: "3.14.8" From 25e6cd62dd797be25c38e35124c8bce3ec11b3c1 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:20:13 -0300 Subject: [PATCH 042/235] fix: aplicar una master key --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index aef70024..07f18570 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -5,7 +5,7 @@ pipeline: - "apk add python2" - "yarn" - "RAILS_GROUPS=assets bundle install --path=vendor" - - "RAILS_GROUPS=assets bundle exec rails assets:precompile assets:clean" + - "RAILS_GROUPS=assets RAILS_MASTER_KEY=nada bundle exec rails assets:precompile assets:clean" - "git add assets && git commit -m \"[skip ci] JS\" || true" when: branch: From 4b575801c539351f640a9cb36bcbebd902724780 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:30:58 -0300 Subject: [PATCH 043/235] fix: usar .env --- .env.example | 3 ++- .woodpecker.yml | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index fb086224..3d134dc2 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,8 @@ +RAILS_MASTER_KEY=CHANGEME RAILS_GROUPS=assets DELEGATE=athshe.sutty.nl HAINISH=../haini.sh/haini.sh -DATABASE= +DATABASE_URL=postgres://suttier@postgresql.sutty.local/sutty RAILS_ENV=development IMAP_SERVER= DEFAULT_FROM= diff --git a/.woodpecker.yml b/.woodpecker.yml index 07f18570..1ad83060 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -2,10 +2,11 @@ pipeline: assets: image: "registry.nulo.in/sutty/panel:3.14.8-2.7.6" commands: - - "apk add python2" + - "apk add python2 dotenv" - "yarn" - - "RAILS_GROUPS=assets bundle install --path=vendor" - - "RAILS_GROUPS=assets RAILS_MASTER_KEY=nada bundle exec rails assets:precompile assets:clean" + - "cp .env.example .env" + - "dotenv bundle install --path=vendor" + - "dotenv RAILS_ENV=production bundle exec rails assets:precompile assets:clean" - "git add assets && git commit -m \"[skip ci] JS\" || true" when: branch: From cacd37348f0022c459fe3a59ddc88b3d40ceabb3 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 19:51:46 -0300 Subject: [PATCH 044/235] fix: credenciales de prueba --- .env.example | 3 ++- .gitignore | 1 - config/credentials.yml.enc | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 config/credentials.yml.enc diff --git a/.env.example b/.env.example index 3d134dc2..f3cf48d9 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ -RAILS_MASTER_KEY=CHANGEME +# pwgen -1 32 +RAILS_MASTER_KEY=11111111111111111111111111111111 RAILS_GROUPS=assets DELEGATE=athshe.sutty.nl HAINISH=../haini.sh/haini.sh diff --git a/.gitignore b/.gitignore index 496b66cb..baf85364 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ # Ignore master key for decrypting credentials and more. /config/master.key -/config/credentials.yml.enc /public/packs /public/packs-test diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc new file mode 100644 index 00000000..ad215f22 --- /dev/null +++ b/config/credentials.yml.enc @@ -0,0 +1 @@ +r7drFxABS9885DuIhjg3ErL++9dkHZdO6/kBlBNlML20R2R2hhYkE1C2Q9fO7zGaHQX3y51FKu9nRAI9Bomp5JCF/RR3oEzP24Je9DsN/Q2lg3smTNuXKV5J8NuqZPRVBZIp7FsyR66xThzI6ZSrk0IFXRpTwQkW83v3Z+FqLKCAFBAiJ84occonkLUxppL0W0IYN4FzNAK0KiPixZDTg/oAqG17pY0suyJRCe86OYkdrvblI/EEmoxKzSPzT4fml4wka26z4KYeRYDjaQmlTJ8/zLK82AruxhYvL9abdtjsUYIVVWHdNrlRRZaVhFP79YIa0AFfHK1KviMKAAfb8EfDar1fivtzW9mb46dzZcEu0ynJB+HDdM1JFiVw33INI6BY8I604pu5B5ebd9Djd1nIP2wNZNu7ZBOgvbPnDJUdenVAnWYZAqmPVAryK1MfwvaG0RmVYnhlIZoQ2HTLENHV9AyAfUOUiZUse7GQ85iOqrn3yk2KxEh7i4U5yqZu2tuMBBmQK8jpDWiu6hEtIIDgL2327EUNTw1uDvMfpD64I9pBwHGXhKBr3Qi02rNwOI6wJBTLTaSHv15oAolVmiI3kWtQca+UO7LfMaU+mLb6xZ4jm3/maNmugKKHD4Ud7FO2nJ6m2FPUB7uolQPiiSY4cnkd2uKNn7aQPMDcWlQn1CQuwriGwhJD27YfYzyJRD5PG33bmR3JSSjUe4BI9cBTv3UZ7XS/B7Z7SEzqef09hpMUVzEsEsw5yW6Qm1MV8AhYaxPuWLOElwiATcObehJ7LyjeKQSwoTioEG4GBlvgujcNTxI5O0RkU7hP6I/A3Q==--3br8yafpyHA5Y6YU--Aq+HRsZsGTHm4pOfvQYyoA== \ No newline at end of file From 12a85bc5856424ed5ee87c9715410e4a05a6d694 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 20:05:57 -0300 Subject: [PATCH 045/235] fix: credentials must be strings --- config/credentials.yml.enc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index ad215f22..4add450d 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -r7drFxABS9885DuIhjg3ErL++9dkHZdO6/kBlBNlML20R2R2hhYkE1C2Q9fO7zGaHQX3y51FKu9nRAI9Bomp5JCF/RR3oEzP24Je9DsN/Q2lg3smTNuXKV5J8NuqZPRVBZIp7FsyR66xThzI6ZSrk0IFXRpTwQkW83v3Z+FqLKCAFBAiJ84occonkLUxppL0W0IYN4FzNAK0KiPixZDTg/oAqG17pY0suyJRCe86OYkdrvblI/EEmoxKzSPzT4fml4wka26z4KYeRYDjaQmlTJ8/zLK82AruxhYvL9abdtjsUYIVVWHdNrlRRZaVhFP79YIa0AFfHK1KviMKAAfb8EfDar1fivtzW9mb46dzZcEu0ynJB+HDdM1JFiVw33INI6BY8I604pu5B5ebd9Djd1nIP2wNZNu7ZBOgvbPnDJUdenVAnWYZAqmPVAryK1MfwvaG0RmVYnhlIZoQ2HTLENHV9AyAfUOUiZUse7GQ85iOqrn3yk2KxEh7i4U5yqZu2tuMBBmQK8jpDWiu6hEtIIDgL2327EUNTw1uDvMfpD64I9pBwHGXhKBr3Qi02rNwOI6wJBTLTaSHv15oAolVmiI3kWtQca+UO7LfMaU+mLb6xZ4jm3/maNmugKKHD4Ud7FO2nJ6m2FPUB7uolQPiiSY4cnkd2uKNn7aQPMDcWlQn1CQuwriGwhJD27YfYzyJRD5PG33bmR3JSSjUe4BI9cBTv3UZ7XS/B7Z7SEzqef09hpMUVzEsEsw5yW6Qm1MV8AhYaxPuWLOElwiATcObehJ7LyjeKQSwoTioEG4GBlvgujcNTxI5O0RkU7hP6I/A3Q==--3br8yafpyHA5Y6YU--Aq+HRsZsGTHm4pOfvQYyoA== \ No newline at end of file +1jEfzfldP9tT4+HWfhP48I9hw31gYCnnxHWpYjPrcTm/pgkFdiG+mDa6y31EOxzs50w6FEw2GO127BnyBSUIPIxuWY0cR96xL5pVrS3vjyzM84QN4lJF9ER0Tz1AQ9S7NJ54CelSkMfFt/rf+O4YM8cLtdSVsVC/HlGbp16p3D1pm4MFo5cQb0hEmlyyYlzEn4oJtsp/MCIwI4+z8oFhxKdMIxdbiw+KS/7PBRfMm1h5rdGORCnD69iVmnXseMvVtZn9A7N7uR6+gFlhxlD5yyEW0pwTj3tbu9NeIOVbtmYOL5ZhLW9REXtGTqR5Op/LN+ukIXbDNEScKltJXUdWfa9Pd/QjVT8IMURZ04POEMDgs1cw363yz4f+WQForhSco9oYLDOd5hTGRXoZ9fnjnfJSTjINM62hkfDY3w3+s844nNbjbj+lPTJHU/QjRhcuNqBDDxWUfwTmRIqm5zrelnHnZnuFmFwCNet6NChC6EFUAFjrals6kTSQllyMt4xImqA+HL7DnjWj6VURSH+nGQTA4tQvDdfbDwTzg/PvRkJcsy2dRd135RQdmRZ+8KXBviLabwdR256vaCqSO1j+jyeUPGLll35ghyLxncyBkkAKt1zaDRPDWgVafg0gJ3v7hVV5TYgToPzlv4w88KPCY7cBhkb1qGoXAhtO6iAuZYK9eyZd1gNQJKyqbcLqA5aTTX/ylfdbptWhaZ8ibB8KBgVyn2RmrOHEhB38rDSMHHNfK3Xs4/hhqMFIGHGTGCUYVmjCzhVFd15yRurU32d3YtP8W4L77H7qkFsF1gnvsZx+R084LcJqknwY94dmjtUE4x2u+Qh3ElFj--lr8JoUq1WH9xXNsB--mE8hxHADL7SbDWabAPY1+Q== \ No newline at end of file From 723b8e7974f5a04d1bd775a40e3c9f2c5944ba4a Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 20:26:07 -0300 Subject: [PATCH 046/235] ci: publicar los assets --- .woodpecker.yml | 51 +++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 1ad83060..3f3c510c 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,23 +1,4 @@ pipeline: - assets: - image: "registry.nulo.in/sutty/panel:3.14.8-2.7.6" - commands: - - "apk add python2 dotenv" - - "yarn" - - "cp .env.example .env" - - "dotenv bundle install --path=vendor" - - "dotenv RAILS_ENV=production bundle exec rails assets:precompile assets:clean" - - "git add assets && git commit -m \"[skip ci] JS\" || true" - when: - branch: - - "rails" - - "panel.sutty.nl" - path: - include: - - "app/assets/**/*" - - "app/javascript/**/*" - - "package.json" - - "yarn.lock" publish: image: "plugins/docker" settings: @@ -44,6 +25,38 @@ pipeline: include: - "Dockerfile" - ".dockerignore" + assets: + image: "registry.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" + commands: + - "apk add python2 dotenv openssh-client" + - "mkdir ~/.ssh/" + - "echo \"$${KNOW_HOSTS}\" | base64 -d >> ~/.ssh/known_hosts" + - "eval $(ssh-agent -s)" + - "echo \"$${SSH_KEY}\" | base64 -d | ssh-add -" + - "git config user.name Woodpecker" + - "git config user.email ci@sutty.coop.ar" + - "git remote add origin ${ORIGIN}" + - "git checkout -B ${CI_COMMIT_BRANCH}" + - "yarn" + - "cp .env.example .env" + - "dotenv bundle install --path=vendor" + - "dotenv RAILS_ENV=production bundle exec rails assets:precompile assets:clean" + - "git add public && git commit -m \"ci: assets [skip ci]\"" + - "git push origin ${CI_COMMIT_BRANCH}" + secrets: + - "SSH_KEY" + - "KNOWN_HOSTS" + - "ORIGIN" + when: + branch: + - "rails" + - "panel.sutty.nl" + path: + include: + - "app/assets/**/*" + - "app/javascript/**/*" + - "package.json" + - "yarn.lock" matrix: include: - ALPINE_VERSION: "3.14.8" From 08cad58b77f418b983d03317e0a748153f336e07 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 14 Mar 2023 20:29:58 -0300 Subject: [PATCH 047/235] fixup! ci: publicar los assets --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 3f3c510c..198f5a99 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -35,7 +35,7 @@ pipeline: - "echo \"$${SSH_KEY}\" | base64 -d | ssh-add -" - "git config user.name Woodpecker" - "git config user.email ci@sutty.coop.ar" - - "git remote add origin ${ORIGIN}" + - "git remote add origin $${ORIGIN}" - "git checkout -B ${CI_COMMIT_BRANCH}" - "yarn" - "cp .env.example .env" From 9773285e9f4d060473eafb16a1b76edbf171b475 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Mar 2023 11:23:35 -0300 Subject: [PATCH 048/235] fix: no duplicar el remote --- .woodpecker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 198f5a99..41dc85a3 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -35,14 +35,14 @@ pipeline: - "echo \"$${SSH_KEY}\" | base64 -d | ssh-add -" - "git config user.name Woodpecker" - "git config user.email ci@sutty.coop.ar" - - "git remote add origin $${ORIGIN}" + - "git remote add upstream $${ORIGIN}" - "git checkout -B ${CI_COMMIT_BRANCH}" - "yarn" - "cp .env.example .env" - "dotenv bundle install --path=vendor" - "dotenv RAILS_ENV=production bundle exec rails assets:precompile assets:clean" - "git add public && git commit -m \"ci: assets [skip ci]\"" - - "git push origin ${CI_COMMIT_BRANCH}" + - "git push upstream ${CI_COMMIT_BRANCH}" secrets: - "SSH_KEY" - "KNOWN_HOSTS" From c9d7ac437bd5e88531dac3d375250a2bb096a5cd Mon Sep 17 00:00:00 2001 From: f Date: Thu, 16 Mar 2023 09:51:28 -0300 Subject: [PATCH 049/235] =?UTF-8?q?ci:=20probar=20conexi=C3=B3n=20a=20ssh?= =?UTF-8?q?=20antes=20de=20perder=20tiempo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .woodpecker.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 41dc85a3..84101fdf 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -29,10 +29,12 @@ pipeline: image: "registry.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" commands: - "apk add python2 dotenv openssh-client" - - "mkdir ~/.ssh/" - - "echo \"$${KNOW_HOSTS}\" | base64 -d >> ~/.ssh/known_hosts" + - "install -d -m 700 ~/.ssh/" + - "echo \"$${KNOWN_HOSTS}\" | base64 -d >> ~/.ssh/known_hosts" + - "chmod 600 ~/.ssh/known_hosts" - "eval $(ssh-agent -s)" - "echo \"$${SSH_KEY}\" | base64 -d | ssh-add -" + - "ssh $${ORIGIN%:*}" - "git config user.name Woodpecker" - "git config user.email ci@sutty.coop.ar" - "git remote add upstream $${ORIGIN}" From b51748ddcbc903838fb76c4d1c3df1ee490153bf Mon Sep 17 00:00:00 2001 From: f Date: Thu, 16 Mar 2023 10:18:42 -0300 Subject: [PATCH 050/235] ci: limpiar assets por separado --- .woodpecker.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 84101fdf..e550afbe 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -42,7 +42,8 @@ pipeline: - "yarn" - "cp .env.example .env" - "dotenv bundle install --path=vendor" - - "dotenv RAILS_ENV=production bundle exec rails assets:precompile assets:clean" + - "dotenv RAILS_ENV=production bundle exec rails assets:precompile" + - "dotenv RAILS_ENV=production bundle exec rails assets:clean" - "git add public && git commit -m \"ci: assets [skip ci]\"" - "git push upstream ${CI_COMMIT_BRANCH}" secrets: From 4de942a7ca5536260a092c0e2aa07e57f4f1d283 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 16 Mar 2023 10:23:11 -0300 Subject: [PATCH 051/235] ci: eliminar packs antes de recompilarlos --- .woodpecker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index e550afbe..0492cee2 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -42,6 +42,7 @@ pipeline: - "yarn" - "cp .env.example .env" - "dotenv bundle install --path=vendor" + - "dotenv RAILS_ENV=production bundle exec rails webpacker:clobber" - "dotenv RAILS_ENV=production bundle exec rails assets:precompile" - "dotenv RAILS_ENV=production bundle exec rails assets:clean" - "git add public && git commit -m \"ci: assets [skip ci]\"" From 800386e52ccbe6d40dfe08469d83f1bfa8696040 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 16 Mar 2023 11:24:38 -0300 Subject: [PATCH 052/235] =?UTF-8?q?ci:=20no=20hacer=20conflicto=20con=20la?= =?UTF-8?q?s=20credenciales=20de=20producci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .woodpecker.yml | 1 + config/{credentials.yml.enc => credentials.yml.enc.ci} | 0 2 files changed, 1 insertion(+) rename config/{credentials.yml.enc => credentials.yml.enc.ci} (100%) diff --git a/.woodpecker.yml b/.woodpecker.yml index 0492cee2..ab4887ac 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -39,6 +39,7 @@ pipeline: - "git config user.email ci@sutty.coop.ar" - "git remote add upstream $${ORIGIN}" - "git checkout -B ${CI_COMMIT_BRANCH}" + - "mv config/credentials.yml.enc.ci config/credentials.yml.enc" - "yarn" - "cp .env.example .env" - "dotenv bundle install --path=vendor" diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc.ci similarity index 100% rename from config/credentials.yml.enc rename to config/credentials.yml.enc.ci From a97da5b821768a1a2fdcf0eba185835d70cc2ee7 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 16 Mar 2023 12:22:37 -0300 Subject: [PATCH 053/235] fix: volver a ignorar los secretos --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index baf85364..496b66cb 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ # Ignore master key for decrypting credentials and more. /config/master.key +/config/credentials.yml.enc /public/packs /public/packs-test From f2e79a733d26f1cf578d1f49f995aea14376a246 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:33:52 -0300 Subject: [PATCH 054/235] fix: no fallar si hay errores remotos closes #10467 closes #10506 closes #10509 --- app/models/deploy_distributed_press.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 41054b99..09410201 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -118,7 +118,9 @@ class DeployDistributedPress < Deploy self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end - + rescue DistributedPress::V1::Error, HTTParty::Error => e + ExceptionNotifier.notify_exception(e, data: { site: site.name }) + ensure nil end From 0c674d6ca12fc0f98645a922e18efd13de85cd09 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:37:48 -0300 Subject: [PATCH 055/235] fix: crear el sitio remoto si no se pudo crear antes --- app/models/deploy_distributed_press.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 09410201..bd80dca4 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -27,6 +27,11 @@ class DeployDistributedPress < Deploy time_start + if remote_site_id.blank? || remote_info['njalla'].blank? + create_remote_site! + save + end + site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| until io.eof? From 698b3a0bf6bbbaf6b84a8c0c961de081e2c1989b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:39:41 -0300 Subject: [PATCH 056/235] =?UTF-8?q?feat:=20separar=20la=20creaci=C3=B3n=20?= =?UTF-8?q?de=20DP=20de=20njalla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index bd80dca4..9afc6a5d 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -15,7 +15,7 @@ require 'njalla/v1' class DeployDistributedPress < Deploy store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON - before_create :create_remote_site! + before_create :create_remote_site!, :create_njalla_records! # Actualiza la información y luego envía los cambios # @@ -27,10 +27,9 @@ class DeployDistributedPress < Deploy time_start - if remote_site_id.blank? || remote_info['njalla'].blank? - create_remote_site! - save - end + create_remote_site! if remote_site_id.blank? + create_njalla_records! if remote_info['njalla'].blank? + save site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| @@ -115,7 +114,16 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h + rescue DistributedPress::V1::Error + ExceptionNotifier.notify_exception(e, data: { site: site.name }) + ensure + nil + end + # Crea los registros en Njalla + # + # @return [nil] + def create_njalla_records! # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay # que eliminarlo. unless site.name.end_with? '.' @@ -123,7 +131,7 @@ class DeployDistributedPress < Deploy self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end - rescue DistributedPress::V1::Error, HTTParty::Error => e + rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) ensure nil From b297800933ae0556845f1e710ce181a6d4e158cb Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:44:13 -0300 Subject: [PATCH 057/235] fix: volver a fallar si al hacer deploy todavia estan caidos los servicios --- app/models/deploy_distributed_press.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 9afc6a5d..e8d8b095 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -31,6 +31,10 @@ class DeployDistributedPress < Deploy create_njalla_records! if remote_info['njalla'].blank? save + if remote_site_id.blank? || remote_info['njalla'].blank? + raise DeployJob::DeployException, '' + end + site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| until io.eof? @@ -133,6 +137,7 @@ class DeployDistributedPress < Deploy end rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) + self.remote_info['njalla'] = nil ensure nil end From 5ec698366a524583063cefb84d652084e2841788 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 11:46:21 -0300 Subject: [PATCH 058/235] fix: capturar standard error --- app/jobs/gitlab_notifier_job.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 291112a5..fb25be10 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -61,7 +61,7 @@ class GitlabNotifierJob < ApplicationJob Rails.cache.write(cache_key, issue_data) # Si este trabajo genera una excepción va a entrar en un loop, así que # la notificamos por correo - rescue Exception => e + rescue StandardError => e email_notification.call(e, data: @issue) email_notification.call(exception, data: options) end @@ -89,7 +89,9 @@ class GitlabNotifierJob < ApplicationJob end def errors - options.dig(:data, :params, 'errors') if options.dig(:data, :params).is_a? Hash + return '' unless javascript? + + options.dig(:data, :params, 'errors') end # Define si es una excepción de javascript o local From 16ed7db1d76ff24ee5c8a6d88b6c35788c22441a Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 12:13:51 -0300 Subject: [PATCH 059/235] =?UTF-8?q?fix:=20capturar=20la=20excepci=C3=B3n?= =?UTF-8?q?=20#10546?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index e8d8b095..6940a83e 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -118,7 +118,7 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h - rescue DistributedPress::V1::Error + rescue DistributedPress::V1::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) ensure nil From d25937f536ef072f2a9323b03e1bbaa4809fcd40 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 15:33:28 -0300 Subject: [PATCH 060/235] fix: no producir type error --- app/jobs/gitlab_notifier_job.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index fb25be10..2f39caf9 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -16,7 +16,7 @@ class GitlabNotifierJob < ApplicationJob # @param [Hash] opciones de ExceptionNotifier def perform(exception, **options) @exception = exception - @options = options + @options = fix_options options @issue_data = { count: 1 } # Necesitamos saber si el issue ya existía @cached = false @@ -88,10 +88,9 @@ class GitlabNotifierJob < ApplicationJob ].join('/') end + # @return [Array] def errors - return '' unless javascript? - - options.dig(:data, :params, 'errors') + options.dig(:data, :params, 'errors') || [] end # Define si es una excepción de javascript o local @@ -288,4 +287,15 @@ class GitlabNotifierJob < ApplicationJob def url @url ||= request&.url || options.dig(:data, :params, 'context', 'url') end + + # Define llaves necesarias + # + # @param :options [Hash] + # @return [Hash] + def fix_options(options) + options[:data] ||= {} + options[:data][:params] ||= {} + + options + end end From 706ff80b1864b791197741ff5afbd98ab808baae Mon Sep 17 00:00:00 2001 From: f Date: Tue, 21 Mar 2023 14:05:11 -0300 Subject: [PATCH 061/235] =?UTF-8?q?fix:=20algo=20est=C3=A1=20enviando=20la?= =?UTF-8?q?s=20opciones=20como=20array?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/gitlab_notifier_job.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 2f39caf9..4d57c744 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -293,6 +293,7 @@ class GitlabNotifierJob < ApplicationJob # @param :options [Hash] # @return [Hash] def fix_options(options) + options = { data: options } if options.is_a? Array options[:data] ||= {} options[:data][:params] ||= {} From 1230dc2e96eb2bc117f1f92433e0d97748d4f2bf Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 09:58:00 -0300 Subject: [PATCH 062/235] fix: solo permitimos un hash de opciones --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 4d57c744..7b369fab 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -293,7 +293,7 @@ class GitlabNotifierJob < ApplicationJob # @param :options [Hash] # @return [Hash] def fix_options(options) - options = { data: options } if options.is_a? Array + options = { data: options } unless options.is_a? Hash options[:data] ||= {} options[:data][:params] ||= {} From bbb951594b8594d6d71943b77c077573d813b8e1 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 09:59:36 -0300 Subject: [PATCH 063/235] fix: enviar las opciones post limpieza --- app/jobs/gitlab_notifier_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/gitlab_notifier_job.rb b/app/jobs/gitlab_notifier_job.rb index 7b369fab..575d57d8 100644 --- a/app/jobs/gitlab_notifier_job.rb +++ b/app/jobs/gitlab_notifier_job.rb @@ -63,7 +63,7 @@ class GitlabNotifierJob < ApplicationJob # la notificamos por correo rescue StandardError => e email_notification.call(e, data: @issue) - email_notification.call(exception, data: options) + email_notification.call(exception, data: @options) end private From 823ac94e7434282a55a9d6a71fb235a7af553b2c Mon Sep 17 00:00:00 2001 From: Nulo Date: Mon, 2 May 2022 18:55:35 +0000 Subject: [PATCH 064/235] Arreglar scroll al reordenar posts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utilizaba https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded que es propietario. Ahora usa scrollIntoView siempre, configurado para que prácticamente siempre se pueda ver el post al reordenar. --- app/javascript/controllers/reorder_controller.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/javascript/controllers/reorder_controller.js b/app/javascript/controllers/reorder_controller.js index dca6e166..2cba4163 100644 --- a/app/javascript/controllers/reorder_controller.js +++ b/app/javascript/controllers/reorder_controller.js @@ -103,11 +103,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - if ("scrollIntoViewIfNeeded" in rows[0].row) { - rows[0].row.scrollIntoViewIfNeeded() - } else { - rows[0].row.scrollIntoView() - } + rows[0].row.scrollIntoView({ block: "center" }); } counter () { @@ -146,7 +142,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - rows[0].row.scrollIntoViewIfNeeded() + rows[0].row.scrollIntoView({ block: "center" }); } bottom (event) { @@ -167,7 +163,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - rows[0].row.scrollIntoViewIfNeeded() + rows[0].row.scrollIntoView({ block: "center" }); } /* From 88c1ffe4b8f1ff60bca474cf1ffe5263f8d417e9 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 13:43:13 -0300 Subject: [PATCH 065/235] fix: hacer que los locales sean bidireccionales #10491 #12064 --- app/models/metadata_locales.rb | 11 +----- app/views/posts/attributes/_locales.haml | 48 +++++++----------------- 2 files changed, 16 insertions(+), 43 deletions(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 4d540efc..702e1902 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -1,21 +1,14 @@ # frozen_string_literal: true # Los valores de este metadato son artículos en otros idiomas -class MetadataLocales < MetadataTemplate - def default_value - super || [] - end - +class MetadataLocales < MetadataHasAndBelongsToMany # Todos los valores posibles para cada idioma disponible # - # TODO: Optimizar? - # TODO: Mantener sincronizados - # # @return { lang: { title: uuid } } def values @values ||= site.locales.map do |locale| [locale, site.posts(lang: locale).map do |post| - [post.title.value, post.uuid.value] + [title(post), post.uuid.value] end.to_h] end.to_h end diff --git a/app/views/posts/attributes/_locales.haml b/app/views/posts/attributes/_locales.haml index 8dd7adf6..6d4d3326 100644 --- a/app/views/posts/attributes/_locales.haml +++ b/app/views/posts/attributes/_locales.haml @@ -1,39 +1,19 @@ --# +%fieldset + %legend= post_label_t(attribute, post: post) - Crea un input-map para cada idioma por separado. Podríamos hacer uno - solo que tenga todos los idiomas pero puede ser una interfaz confusa. + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata - TODO: Esto permite seleccionar más de una traducción por idioma... + - site.locales.each do |locale| + - next if post.lang.value == locale + - locale_t = t("locales.#{locale}.name") -- site.locales.each do |locale| - -# Ignorar el idioma actual - - next if post.lang.value == locale - - locale_t = t("locales.#{locale}.name") - - values = metadata.value.select do |x| - - metadata.values[locale].values.include? x + .form-group + = label_tag "#{base}_#{attribute}_#{locale}", locale_t - .form-group - = label_tag "#{base}_#{attribute}_#{locale}", locale_t + = select_tag("#{plain_field_name_for(base, attribute)}[]", + options_for_select(metadata.values[locale]), + **field_options(attribute, metadata), include_blank: t('.empty')) - .mapable{ dir: t("locales.#{locale}.dir"), lang: locale, - data: { values: values.to_json, - 'default-values': metadata.values[locale].to_json, - name: "#{base}[#{attribute}][]", - list: id_for_datalist(attribute, locale), - button: t('posts.attributes.add'), - remove: 'false', legend: locale_t, - described: id_for_help(attribute, locale) } } - - = text_field(*field_name_for(base, attribute, '[]'), - value: values.join(', '), - dir: t("locales.#{locale}.dir"), lang: locale, - **field_options(attribute, metadata)) - - = render 'posts/attribute_feedback', - post: post, - attribute: [attribute, 'mapable'].flatten, - metadata: metadata - - %datalist{ id: id_for_datalist(attribute, locale) } - - metadata.values[locale].keys.each do |value| - %option{ value: value } + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata From ad1d59d6a4616da92048d84587896dcc8041932d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 13:55:51 -0300 Subject: [PATCH 066/235] fix: recuperar el valor --- app/views/posts/attributes/_locales.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/posts/attributes/_locales.haml b/app/views/posts/attributes/_locales.haml index 6d4d3326..21d410be 100644 --- a/app/views/posts/attributes/_locales.haml +++ b/app/views/posts/attributes/_locales.haml @@ -7,13 +7,12 @@ - site.locales.each do |locale| - next if post.lang.value == locale - locale_t = t("locales.#{locale}.name") + - value = metadata.value.find do |v| + - metadata.values[locale].values.include? v .form-group = label_tag "#{base}_#{attribute}_#{locale}", locale_t = select_tag("#{plain_field_name_for(base, attribute)}[]", - options_for_select(metadata.values[locale]), + options_for_select(metadata.values[locale], value), **field_options(attribute, metadata), include_blank: t('.empty')) - - = render 'posts/attribute_feedback', - post: post, attribute: attribute, metadata: metadata From 034015938bd07dd9471f006164cba6a6e564af8f Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 14:14:55 -0300 Subject: [PATCH 067/235] =?UTF-8?q?fix:=20mostrar=20el=20idioma=20si=20no?= =?UTF-8?q?=20existe=20una=20traducci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/posts/attributes/_locales.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/posts/attributes/_locales.haml b/app/views/posts/attributes/_locales.haml index 21d410be..23f66700 100644 --- a/app/views/posts/attributes/_locales.haml +++ b/app/views/posts/attributes/_locales.haml @@ -6,7 +6,7 @@ - site.locales.each do |locale| - next if post.lang.value == locale - - locale_t = t("locales.#{locale}.name") + - locale_t = t("locales.#{locale}.name", default: locale.to_s.humanize) - value = metadata.value.find do |v| - metadata.values[locale].values.include? v From 6d59d79e2a086bc653565cb93c9ef6406a9b910c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 14:26:06 -0300 Subject: [PATCH 068/235] =?UTF-8?q?fix:=20establecer=20relaci=C3=B3n=20bid?= =?UTF-8?q?ireccional=20#10491?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_locales.rb | 36 +++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 702e1902..2e9080c9 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -7,9 +7,43 @@ class MetadataLocales < MetadataHasAndBelongsToMany # @return { lang: { title: uuid } } def values @values ||= site.locales.map do |locale| - [locale, site.posts(lang: locale).map do |post| + [locale, posts.where(lang: locale).map do |post| [title(post), post.uuid.value] end.to_h] end.to_h end + + # Siempre hay una relación inversa + # + # @return [True] + def inverse? + true + end + + # El campo inverso se llama igual en el otro post + # + # @return [Symbol] + def inverse + :locales + end + + private + + # Obtiene todos los locales distintos a este post + # + # @return [Array] + def other_locales + site.locales.reject do |locale| + locale == post.lang.value.to_sym + end + end + + # Obtiene todos los posts de los otros locales con el mismo layout + # + # @return [PostRelation] + def posts + other_locales.map do |locale| + site.posts(lang: locale).where(layout: post.layout.value) + end.reduce(&:concat) + end end From fc14889d0eeb579e2b86aa6fd2250889d3ae0227 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 14:35:47 -0300 Subject: [PATCH 069/235] fix: soporte para urdu --- config/locales/en.yml | 3 +++ config/locales/es.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 10a4793b..eb7ef1ec 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -13,6 +13,9 @@ en: ar: name: Arabic dir: rtl + ur: + name: Urdu + dir: rtl login: email: E-mail address password: Password diff --git a/config/locales/es.yml b/config/locales/es.yml index 02973de5..665fb350 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -13,6 +13,9 @@ es: ar: name: Árabe dir: rtl + ur: + name: Urdu + dir: rtl login: email: Correo electrónico password: Contraseña From 59606f32639fd48f849a0e27fcb1ac3fa8d6c589 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 14:38:18 -0300 Subject: [PATCH 070/235] fix: reducir el alto de la leyenda --- app/assets/stylesheets/application.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index b756759a..ba8de715 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -154,6 +154,12 @@ ol.breadcrumb { transition: all 3s; } +fieldset { + legend { + font-size: 1rem; + } +} + .mapable, .taggable { .input-map, From 758f9de36dde570f619d4f56faf6d9d56144981d Mon Sep 17 00:00:00 2001 From: Nulo Date: Mon, 2 May 2022 18:55:35 +0000 Subject: [PATCH 071/235] Arreglar scroll al reordenar posts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utilizaba https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded que es propietario. Ahora usa scrollIntoView siempre, configurado para que prácticamente siempre se pueda ver el post al reordenar. --- app/javascript/controllers/reorder_controller.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/javascript/controllers/reorder_controller.js b/app/javascript/controllers/reorder_controller.js index dca6e166..2cba4163 100644 --- a/app/javascript/controllers/reorder_controller.js +++ b/app/javascript/controllers/reorder_controller.js @@ -103,11 +103,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - if ("scrollIntoViewIfNeeded" in rows[0].row) { - rows[0].row.scrollIntoViewIfNeeded() - } else { - rows[0].row.scrollIntoView() - } + rows[0].row.scrollIntoView({ block: "center" }); } counter () { @@ -146,7 +142,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - rows[0].row.scrollIntoViewIfNeeded() + rows[0].row.scrollIntoView({ block: "center" }); } bottom (event) { @@ -167,7 +163,7 @@ export default class extends Controller { this.reorder() // Mantenemos el primero a la vista - rows[0].row.scrollIntoViewIfNeeded() + rows[0].row.scrollIntoView({ block: "center" }); } /* From abacabff8efa261f79855cdd22c6217806a096fe Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 18:39:56 -0300 Subject: [PATCH 072/235] fix: agregar licencia con layout --- app/services/site_service.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 22423bb8..436bc1c3 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -104,11 +104,10 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do def add_licencia(lang:) params = ActionController::Parameters.new( post: { + layout: 'license', lang: lang, title: site.licencia.name, description: I18n.t('sites.form.licencia.title'), - author: %w[Sutty], - permalink: "#{I18n.t('activerecord.models.licencia').downcase}/", content: CommonMarker.render_html(site.licencia.deed) } ) From 46c20cae7de41225b63ba5ff44eb7e5484a0e4ab Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 18:41:12 -0300 Subject: [PATCH 073/235] feat: no agregar licencia si la plantilla no lo soporta --- app/services/site_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 436bc1c3..87a08652 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -92,6 +92,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Crea la licencia del sitio para cada locale disponible en el sitio def add_licencias + return unless site.layout? :license + site.locales.each do |locale| next unless I18n.available_locales.include? locale From 0b353466a4c8113ed7c3fd57bed9f622ca298643 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 18:43:20 -0300 Subject: [PATCH 074/235] fix: solo cambiar la licencia si existe una #159 --- app/services/site_service.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 87a08652..b4fa2fa0 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -119,18 +119,14 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Encuentra la licencia a partir de su enlace permanente y le cambia # el contenido - # - # TODO: Crear un layout específico para licencias así es más certera - # la búsqueda. def change_licencias site.locales.each do |locale| next unless I18n.available_locales.include? locale Mobility.with_locale(locale) do - permalink = "#{I18n.t('activerecord.models.licencia').downcase}/" - post = site.posts(lang: locale).find_by(permalink: permalink) + post = site.posts(lang: locale).find_by(layout: 'license') - post ? change_licencia(post: post) : add_licencia(lang: locale) + change_licencia(post: post) if post end end end From 7b68bc15692ba4032e7ec9b660f6fc624512250d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 18:45:41 -0300 Subject: [PATCH 075/235] =?UTF-8?q?fix:=20crear=20las=20licencias=20despu?= =?UTF-8?q?=C3=A9s=20de=20crear=20el=20t=C3=ADtulo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit y los commits también se harían en el idioma de le usuarie --- app/services/site_service.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index b4fa2fa0..e98d2487 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -14,11 +14,10 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do I18n.with_locale(usuarie&.lang&.to_sym || I18n.default_locale) do site.save && site.config.write && - commit_config(action: :create) + commit_config(action: :create) && + add_licencias end - add_licencias - site end @@ -27,11 +26,10 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do I18n.with_locale(usuarie&.lang&.to_sym || I18n.default_locale) do site.update(params) && site.config.write && - commit_config(action: :update) + commit_config(action: :update) && + change_licencias end - change_licencias - site end From ddd2bc07ff62b24745e74af4d6ce7284263e8117 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:04:15 -0300 Subject: [PATCH 076/235] =?UTF-8?q?feat:=20incorporar=20los=20c=C3=B3digos?= =?UTF-8?q?=20de=20conducta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/code_of_conduct.rb | 14 + app/services/site_service.rb | 34 +- config/initializers/inflections.rb | 4 + .../20230322214924_add_code_of_conduct.rb | 22 + db/seeds/codes_of_conduct.yml | 613 ++++++++++++++++++ 5 files changed, 686 insertions(+), 1 deletion(-) create mode 100644 app/models/code_of_conduct.rb create mode 100644 db/migrate/20230322214924_add_code_of_conduct.rb create mode 100644 db/seeds/codes_of_conduct.yml diff --git a/app/models/code_of_conduct.rb b/app/models/code_of_conduct.rb new file mode 100644 index 00000000..87c24c7f --- /dev/null +++ b/app/models/code_of_conduct.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Códigos de conducta +class CodeOfConduct < ApplicationRecord + extend Mobility + + translates :title, type: :string, locale_accessors: true + translates :description, type: :text, locale_accessors: true + translates :content, type: :text, locale_accessors: true + + validates :title, presence: true, uniqueness: true + validates :description, presence: true + validates :content, presence: true +end diff --git a/app/services/site_service.rb b/app/services/site_service.rb index e98d2487..19b95302 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -15,7 +15,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do site.save && site.config.write && commit_config(action: :create) && - add_licencias + add_licencias && + add_code_of_conduct end site @@ -141,10 +142,41 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do params: params).update end + def add_code_of_conduct + # TODO: soportar más códigos de conducta + coc = CodeOfConduct.first + + with_all_locales do |locale| + params = ActionController::Parameters.new( + post: { + layout: 'code_of_conduct', + lang: locale.to_s, + title: coc.title, + description: coc.description, + content: CommonMarker.render_html(coc.content) + } + ) + + PostService.new(site: site, usuarie: usuarie, params: params).create + end + end + # Crea los deploys necesarios para sincronizar a otros nodos de Sutty def sync_nodes Rails.application.nodes.each do |node| site.deploys.build(type: 'DeployRsync', destination: "sutty@#{node}:#{site.hostname}") end end + + private + + def with_all_locales(&block) + site.locales.each do |locale| + next unless I18n.available_locales.include? locale + + Mobility.with_locale(locale) do + yield locale + end + end + end end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 0e18b987..46cb9d78 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -13,6 +13,8 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.singular 'roles', 'rol' inflect.plural 'rollup', 'rollups' inflect.singular 'rollups', 'rollup' + inflect.plural 'code_of_conduct', 'codes_of_conduct' + inflect.singular 'codes_of_conduct', 'code_of_conduct' end ActiveSupport::Inflector.inflections(:es) do |inflect| @@ -28,4 +30,6 @@ ActiveSupport::Inflector.inflections(:es) do |inflect| inflect.singular 'licencias', 'licencia' inflect.plural 'rollup', 'rollups' inflect.singular 'rollups', 'rollup' + inflect.plural 'code_of_conduct', 'codes_of_conduct' + inflect.singular 'codes_of_conduct', 'code_of_conduct' end diff --git a/db/migrate/20230322214924_add_code_of_conduct.rb b/db/migrate/20230322214924_add_code_of_conduct.rb new file mode 100644 index 00000000..f859b08c --- /dev/null +++ b/db/migrate/20230322214924_add_code_of_conduct.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Crea códigos de conducta +class AddCodeOfConduct < ActiveRecord::Migration[6.1] + def up + create_table :codes_of_conduct do |t| + t.timestamps + t.string :title + t.text :description + t.text :content + end + + # XXX: En lugar de ponerlo en las seeds + YAML.safe_load(File.read('db/seeds/codes_of_conduct.yml')).each do |coc| + CodeOfConduct.new(**coc).save! + end + end + + def down + drop_table :codes_of_conduct + end +end diff --git a/db/seeds/codes_of_conduct.yml b/db/seeds/codes_of_conduct.yml new file mode 100644 index 00000000..64582072 --- /dev/null +++ b/db/seeds/codes_of_conduct.yml @@ -0,0 +1,613 @@ +--- +- title_en: "Codes for sharing" + title_es: "Códigos para compartir" + description_en: "Codes of conduct allow inclusive communities." + description_es: "Los códigos de convivencia nos permiten alojar comunidades inclusivas." + content_en: | + # Code for sharing + + > This code of conduct is based in "[Códigos para compartir, hackear, + > piratear en + > libertad](https://utopia.partidopirata.com.ar/zines/codigos_para_compartir.html)" + > published by [Partido Interdimensional + > Pirata](https://partidopirata.com.ar/). + + > We use gender neutral pronouns to include all peoples. In this sense, + > we encourage different forms, strategies and tools used to embody + > practices that aren't anthropocentric, sexist, cis-sexist in our + > language. + + ## Introduction + + This is an example code that strives to give a consensual frame to + enable asistance, permanence and confortable stay to everyone using and + inhabiting [Sutty](https://sutty.nl/), and to welcome new users and + potential allies as well. It sets the floor for desirable and + acceptable, and undesirable and intolerable conducts for its community. + You can use it with or without changes, adapting it to your activities. + This code is in permanent and collective mutation and feeds, copies and + inspires on the following sources: + + * + + * + + * + + * + + We strive to sustain and foment an open community, that invites and + attains participation from more people, in all their diversity. We know + that spaces related to computing and free software are mostly inhabited + by middle class cis white males, even when there's an acknowledgement of + the need to close the gender gap. In this sense, this is our little + contribution, made from collective practices on multiple dimentions, + reflections, readings, and experiences that grow every day. + + ## That everyone needs to be well treated + + Every being that we share space with deserves good treatment, respect + and compassion. Here we share basic criteria for introduction and care. + + ### Towards humans + + Everyone is deserving of care and greetings and we have a right to + assume good intentions from others. + + When we refer to other humans, we try to be careful and respectul + towards their gender identity. For this, these principles are useful: + + * Don't assume, judge or try to "interpret" the gender of others. + + * Don't use gender beforehand. It's related to the previous item, but + puts emphasis towards naturalized gendering behaviour (ie. assuming + someone wearing a dress uses female pronouns...). The proposal is to + discard them. + + * If a person explicits their pronouns and mode in which they want to be + referenced, we respect them, by listening and trying to use their + prefered pronouns. + + * When presentations don't include pronouns, we can ask respectfully + for prefered pronouns. But be careful! This question must be asked + to everyone, otherwise the "suspicion" is loaded towards a person, and + it can become a form of harrassment. + + * Do we need to know the gender of a person to relate with them? Maybe + a better practice is to evade gendering others. But if this means to + use "them" compulsively, some people may be made to feel bad. (For + instance, trans\* people who use female or male pronouns may feel + upset or outed when refering to them as "them", specially if they're + the only ones to be gendered like this in a group! + + * When in doubt, asking and apologizing respectfully is a good way of + being careful towards each other. + + ## Important points to guarantee our space from being expulsive + + **Listening to and between everyone in a caring climate** + + * Listen to what everyone has to say, being mindful that everyone has + something valuable to communicate. + + * For active listening, we prefer to ask first, before making judgement. + + * Sometimes being silent is a condition for others to be able to talk. + To listen is an exercise that requires practice. Also talking. + + * We're interested in what everyone has to say. If you're more trained + in participating, talking, and having opinions, take into account that + not everyone does. Give them space if they want to take it. But + remember that encouraging is not the same as pressuring! + + * We try to check and stop offensive practices to add to the respectful + climate. This doesn't mean to be submissive or to agree to + everything. At the least, it sets a floor of respect towards enabling + a dialogue when necessary. + + * It's at the very least disrepectful to repeat damaging behaviour when + it was already identified as such. It can make others unconfortable, + or hurt and expel them. We'll make this point every time that is + needed and tolerable. + + * We avoid this behaviour ourselves and we help others to notice their + own. + + * When raising attention becomes insufficient, we need to review this + agreements to keep the coexistence. This implies to act in accord to + them, and that this code can be revised and updated when deemed + necessary (there's no consensus). + + * One of the ways in which free software spaces can be and are expulsive + is with attitudes that don't contemplate diversity in knowledges and + interlocutors. By appealing to technicisms, many comrades are kept + out of what's happening, and no one verifies if everyone is keeping up + with the conversation. + + Our fervent recommendation is to be attentive to this dynamic so we + can avoid or revert them. + + * The counter to the previous situation is "mansplaining": a cis-male + person assuming the authoritative place of knowledge to (over-)explain + everything to others, in a patronizing way and without taking into + account what others want to listen or not, to say, what already know + or do, etc. + + * We believe there's no "authoritative voice" to have an opinion and to + participate. Free culture is for everyone to share. + + * "Sharing is caring" v. "Google is your friend". Meritocracy and other + traditional codes in cyber-communities work against free culture. We + support the pirate culture that onboards ever more pirates to their + ships. We believe that culture is for everyone and we defy elitisms. + + * We don't assume that other people shares our likings, beliefs, class + position, sexuality, etc. We can be violent when we misread others. + We recommend to ask respectfully and to avoid comments or jokes that + can be hurtful to others. + + * We speak and act gently and inclusively. + + * We respect different points of view, experiences, beliefs, etc. and we + take them into account when we act collectively so it reflects in our + attitudes. + + * We welcome criticism, specially the constructive kind ;) + + * We focus in what's best for the community, without losing warmth, + respect and diversity amongst ourselves. + + * We show empathy toward others. We want to share and communicate. + + * It's useful to think everyone has different abilities, stories, + experiences... It's possible to not understand some comments. We try + to avoid acting in bad faith and to use every accessibility tool we + can. + + * The last item includes neurodiverse people and those that have + experienced trauma. Sometimes, sarcasm or irony is not well received + or understood by others. We take this into our strategies to include + everyone in our communications. Even more, if we think some topics + could be sensitive to others (memory-triggering, phobias, untolerable, + explicit violence or body images, etc.), we use content warnings (cw) + before what we wanted to share. For instance: "cw: comments about + sexual and physical violence". This allows everyone to opt in to the + content instead of being taken by surprise. + + * We're respectful of limits established by others (personal space, + physical contact, interaction mood, privacy, being photographed, etc.) + + * We want to and believe in welcoming more pirates! + + ## Consent for documenting and sharing in media + + * If you're going to take pictures or record video, ask consent from + people involved. + + * If there're minors, ask their responsible families. + + ## Our commitment against harassment + + In the interest of fomenting an open, diverse and welcoming community, + we contributors and admins make a commitment against harassment in our + projects and community for everyone, without regard of age, body + diversity, capacity, neuro-diversity, ethnicity, gender identity and + expression, experience level, nationality, physical appearance, + religion, sexual identity or orientation. + + Examples of unacceptable behaviour from participants: + + * Offensive comments about gender/s, gender identity and expression, + sexual orientation, capacity, mental sickness, neuro-(a)tipicality, + physical appearance, body size, ethnicity or religion. + + * Unwelcomed comments related to personal and life choices, including + amongst others, those related to food, health, children upbringing, + drug use and employment. + + * Insulting or despective comments and personal or political attacks. + **Trolling**. + + * Assuming others' gender. If you're in doubt, ask politely about + pronouns. Don't use the name(s) that people don't use anymore, use + the name, _nickname_ or pseudonym that they prefer. Do you really + need the name, ID number, biometric data, birth certificate of others? + + * Sexual comments, images or behaviour, unneeded or in spaces where they + weren't appropiate. + + * Unconsented physical contact or repeated after being asked to stop. + + * Threatening others. + + * Inciting violence towards others, including self-damage. + + * Deliberate intimidation. + + * Stalking. + + * To harass by photographing or recording without consent, including + uploading personal information to the Internet. + + * Interrupting a conversation constantly. + + * Making unwanted sexual comments. + + * Unappropiate patterns of social contact, like asking/assuming + inappropiate intimacy levels with others. + + * Trying to interact with a person after being asked not to. + + * Exposing deliberately any aspect of a person identity without consent, + except when necessary for protecting others against intentional abuse. + + * Making public any kind of private conversation. + + * Other kinds of conduct that can be considered inappropiate in an + environment of camaraderie. + + * Repeating attitudes that others find offensive or violatory of this + code. + + ## Consequences + + * Any person that has been asked to stop offensive behaviour is expected + to respond immediately, even when in disagreement. + + * Admins can take any action deemed necessary and adequate, including + expelling the person or removing their site without advertence. This + decision is taken by consensus between admins and is reserved for + extreme cases that compromise the community or the permanence of + others without feeling wronged or threatened. + + * Admins reserve the right to forbid participation to any future + activity or publication. + + As we mentioned before, this code is in permanent collective mutation. + It's main objective is to generate an inclusive and non-expulsive + environment that is also transparent and open without [missing + stairs](https://en.wikipedia.org/wiki/Missing_stair) ("the missing stair + from a house that everyone knows about but no one wants to take + responsibility for"). It's important to adapt it to different + activities and that it nurtures from contributions from its users. + Receiving your comments and input will help us to achieve this + objective. + + ## Let's keep in contact! + + Si pasaste por alguna situación que quieras compartir --te hayas animado + o no a decirlo en el momento--, podés ponerte en contacto con nosotres. + + Con respecto a quejas o avisos acerca de situaciones de violencia, + acoso, abuso o repetición de conductas que se advirtieron como + intolerables, tomamos la responsabilidad de tenerlas en cuenta y + trabajar en ellas para que el resultado sea el favorable al espíritu de + colectiva que elegimos y describimos aquí. Si bien consideramos que las + prácticas punitivistas no van con nosotres, nuestra decisión explícita + es escuchar a la persona que se manifiesta como violentada o víctima y + acompañarla. + + You can contact us if you were part of a situation you want to share + --even if you didn't pointed it in the moment. + + In regards to complaints or notices about violence, harassment, abuse or + repeated untolerable conducts, we take the responsibility of working on + them for a favorable result towards the collective spirit we defined + here. Even when we don't condone punitivist practices, our explicit + decision is for the victim to be listened and accompanied. + content_es: | + # Códigos para compartir + + > Este código de convivencia está basado en los "[Códigos para + > compartir, hackear, piratear en + > libertad](https://utopia.partidopirata.com.ar/zines/codigos_para_compartir.html)" + > publicados por el [Partido Interdimensional + > Pirata](https://partidopirata.com.ar/). + + > Utilizamos preferentemente la 'e' para referirnos a las personas en + > general. En ese sentido, alentamos las diferentes formas, estrategias + > y herramientas para incorporar prácticas no antropocéntricas, + > sexistas, ni cisexistas en la lengua. Otras alternativas que apoyamos + > --y eventualmente usamos-- son el uso del femenino, la letra e, arrobas, + > equis, asteriscos, etc. + + ## Introducción + + Este es un ejemplo de código que busca aportar un marco de consenso para + garantizar la asistencia, permanencia y cómoda estadía de todas las + personas que habitan y utilizan Sutty, así como para bienvenir a nueves + usuaries y potenciales aliades. Para esto, fija un piso de conductas + deseables, aceptables, indeseables y/o intolerables para la comunidad. + Podés usarlo sin cambios o modificarlo para adaptarlo a tus actividades. + Este código está en permanente mutación colectiva y se alimenta, copia e + inspira de las siguientes fuentes: + + * + + * + + * + + * + + Procuramos mantener y fomentar una comunidad abierta, que invite y logre + la participación de cada vez más personas, en toda su diversidad. + Sabemos que los espacios de Software Libre, informática, sistemas, etc. + son habitados mayormente por varones cis, blancos y de clase media, pese + al reconocimiento de la necesidad de eliminar la brecha de géneros. En + este sentido, este es nuestro pequeño aporte, hecho de prácticas + colectivas de múltiples dimensiones, reflexiones, lecturas, experiencias + que crecen día a día. + + ## Que todes les seres sean bien tratades + + Cada ser con el que compartamos el espacio es merecedore de buen trato, + respeto y compasión. En otras palabras, compartimos a continuación los + criterios básicos de presentación y cuidados. + + Para les humanes + + Todes somos dignes de cuidados y de saludos y tenemos derecho a suponer + las buenas intenciones de le otre. + + Para referirnos a otres humanes, trataremos de ser cuidadoses y + respuestuoses de su identidad de género. Para ello, son útiles los + siguientes principios: + + * No presuponer, juzgar o "interpretar" el género de le otre. + + * No generizar de antemano. Se desprende del punto anterior, pero hace + especial énfasis en comportamientos naturalizados de generización (EJ: + presuponer que porque una persona usa un vestido se nombra en + femenino...). La propuesta es desecharlos. + + * Si la persona explicita sus pronombres y modos en que quiere ser + referenciade, lo respetamos, escuchando y procurando referirnos a elle + usando sus pronombres elegidos. + + * Si no se incluye en la presentación los pronombres preferidos, podemos + preguntar respetuosamente qué pronombres se usan. ¡Pero atención! Es + una pregunta que debe dirigirse a todes por igual, de lo contrario, + carga la "sospecha" sobre la persona señalada y puede resultar en una + forma de hostigamiento. + + * ¿Es necesario conocer el género de una persona para relacionarnos o + referirnos a ella? Quizás una buena práctica es evitar generizar para + todas las personas. Pero si esto implica el uso compulsivo de la "e" + para todes, puede ser que alguna persona se sienta molesta. (Por + ejemplo, las personas trans\* que se identifican en femenino o + masculino suelen sentirse molestas y "sacadas del clóset" u *outeadas* + si se refieren a ellas con la "e", ¡en especial si son las únicas en + ser generizadas de esta forma en un grupo!). + + * Ante cualquier duda, preguntar respetuosamente y disculparse + respetuosamente es una buena idea para ayudar a cuidarnos. + + ## Puntos importantes para garantizar que nuestro espacio no resulte expulsivo + + **Escucharnos a todas y entre todas en un clima de cuidados** + + * Escuchar lo que cada quien tiene para decir, conscientes de que todes + tenemos algo valioso para comunicar(nos). + + * Para la escucha activa, preferimos preguntar primero, en lugar de + hacer juicios. + + * Hacer silencio a veces es la condición para que otres puedan animarse + a hablar. Escuchar es un ejercicio que requiere práctica. También lo + es hablar. + + * Nos interesa lo que todes tengan para decir. Por lo tanto, si estás + más entrenade en el ejercicio de participar, hablar, opinar, tené en + cuenta que quizás haya otres que no lo estén tanto: darles el espacio + si quieren tomarlo. ¡Pero recordá que incentivar no es lo mismo que + presionar! + + * Tratamos de revisar y discontinuar alguna práctica que pueda haber + resultado ofensiva, para sumar al clima de respeto. Sin embargo, esto + no significa "bajar la cabeza" o estar necesariamente de acuerdo. Al + menos, fija un piso de respeto para comenzar un diálogo en el caso en + que sea necesario. + + * Es --al menos-- una falta de respeto repetir un comportamiento dañino + que ya se identificó como tal. Puede incomodar, lastimar y expulsar a + otres, por lo que preferimos llamar la atención sobre este punto todas + las veces que sea necesario y tolerable. + + * Evitamos esto nosotres y ayudamos a otres a darse cuenta cuando lo + están haciendo. + + * En los casos en los que los llamados de atención resulten + insuficientes, hemos de revisar estos acuerdos para sostener la + convivencia. Eso implica actuar de acuerdo a ellos. Y también que + estos códigos pueden ser revisados y actualizados en caso de que se + considere necesario (deje de haber consenso). + + * Una manera en la que los espacios de Software Libre y tecnologías + pueden y suelen ser expulsivos es mediante actitudes que no contemplan + la diversidad de saberes e interlocutor\*s. So pretexto de incluir + tecnicismos, muches compañeres quedan al margen de lo que está + sucediendo, muchas veces, sin que nadie tenga la mínima delicadeza de + verificar que todes estén siguiendo la conversación. + + Recomendamos fervientemente estar atentes a estas dinámicas para poder + evitarlas y/o revertirlas. + + * La otra cara de la situación anterior es el famoso _mansplaining_: un + tipo cis poniéndose en el lugar de la autoridad del saber para + (sobre-)explicar todo a le otre, de manera paternalista y sin tener en + cuenta lo que le otre quiere o no escuchar, decir, lo que sabe o hace, + etc. + + * Creemos que no hace falta ser "una voz autorizada" para opinar y + participar. La cultura libre se comparte entre todes. + + * "Compartir es bueno" vs. "Google es tu amigo". La meritocracia y + ciertos códigos tradicionales de ciertas ciber-comunidades suelen + operar de manera contraria a la propuesta de la cultura libre de + compartir. Apoyamos la cultura piratil que suma más piratas a los + barcos. Creemos que la cultura es para todes y desafiamos las + prácticas elitistas. + + * No damos por sentado que la persona con la que estamos interactuando + comparte gustos, creencias, pertenencias de clase, sexualidad, etc. + Podemos ser violentes si hacemos una lectura equivocada de le otre. + Recomendamos siempre preguntar de manera respetuosa y evitar + comentarios o chistes que puedan herir a les otres. + + * Usamos lenguaje amable e inclusivo y mostramos conductas amables e + inclusivas. + + * Respetamos los diferentes puntos de vista, experiencias, creencias, + etc. y lo tenemos en cuenta cuando estamos en grupo para verlo + reflejado en nuestras actitudes. + + * Aceptamos las críticas. En especial las constructivas ;) + + * Nos enfocamos en lo que es mejor para la comunidad, sin por ello + perder de vista la calidez, el respeto y la diversidad entre cada une + de nosotres. + + * Mostramos empatía con les otres. Queremos comunicarnos y compartir. + + * Es útil tener en cuenta que las personas tenemos capacidades, + historias, recorridos... diferentes. Es posible que algunos + comentarios no sean comprendidos. Trataremos de evitar la mala fe y + sumar todas las herramientas de accesibilidad para todas las personas. + + * El punto anterior incluye a personas neurodiversas y con experiencias + de trauma. A veces el sarcasmo o la ironía no es bien recibido o + comprendido por todes. Será útil tenerlo en cuenta para buscar + estrategias que no excluyan a las personas de nuestros intercambios. + Por otro lado, si creemos que determinados temas pueden ser sensibles + (desencadenantes de recuerdos, fobias, difíciles de tolerar o cargados + de violencia o imágenes corporales muy explícitas, por ejemplo) para + algunas personas y nos valemos de las advertencias de contenido o + _content warning_ (cw) (ej: "cw: comentarios de violencia sexual y + violencia física") antes del contenido a introducir. Esto permite que + cada cual pueda elegir si acceder o no a esos contenidos y que no le + tomen por sorpresa. + + * Respetamos los límites que establecen otras personas (espacio + personal, contacto físico, ganas de interactuar, no querer dar datos + de contacto o ser fotografiades, etc.) + + * ¡Queremos y (creemos) en sumar piratas! + + ## Consentimiento para documentar o compartir en medios + + * Si vas a publicar video o fotos, obtené el consentimiento de las + personas. + + * Si hay menores, consultalo con su familia responsable. + + ## Nuestro compromiso contra el acoso + + En el interés de fomentar una comunidad abierta, diversa y hospitalaria, + nosotres como contribuyentes y administradores nos comprometemos a hacer + de la participación en nuestro proyecto y nuestra comunidad una + experiencia libre de acoso para todes, independientemente de la edad, + diversidad corporal, capacidades, neuro-diversidad, etnia, identidad y + expresión de género, nivel de experiencia, nacionalidad, apariencia + física, raza, religión, identidad u orientación sexual y otras. + + Ejemplos de comportamiento inaceptable por parte de participantes: + + * Comentarios ofensivos relacionados con el/los género/s, la identidad + y expresión de género, la orientación sexual, las capacidades, las + enfermedades mentales, la neuro(a)tipicalidad, la apariencia física, + el tamaño corporal, la raza o la religión. + + * Comentarios indeseados relacionados con las elecciones y las prácticas + de estilo de vida de una persona, incluidas, entre otras, las + relacionadas con alimentos, salud, crianza de les hijes, drogas y + empleo. + + * Comentarios insultantes o despectivos (_trolling_) y ataques + personales o políticos. + + * Dar por sentado el género de las demás personas. En caso de duda, + preguntá educadamente por los pronombres. No uses nombres con los que + las personas no se identifican, usá el nombre, _nickname_ o apodo que + hayan elegido (¿Realmente necesitás el nombre y el número de DNI, + datos biométricos, carta natal, etc.?). + + * Comentarios, imágenes o comportamientos sexuales innecesarios o fuera + de lugar en espacios en los que no son apropiados. + + * Contacto físico sin consentimiento o reiterado tras un pedido de cese. + En el mismo sentido, invasión del espacio corporal (y espacios en + general). + + * Amenazas contra otras personas. + + * Incitación a la violencia contra otra persona, que también incluye + alentar a una persona a autolesionarse. + + * Intimidación deliberada. + + * Acechar (_stalkear_) o perseguir. + + * Acosar fotografiando o grabando sin consentimiento, incluyendo también + subir información personal a Internet sobre alguien para acosarle. + + * Interrumpir constantemente en una conversación. + + * Hacer comentarios sexuales indeseados. + + * Patrones de contacto social inapropiados, como por ejemplo + pedir/suponer niveles de intimidad inapropiados con les demás. + + * Seguir tratando de entablar conversación con una persona cuando se te + pidió que no lo hagas. + + * Divulgar deliberadamente cualquier aspecto de la identidad de una + persona sin su consentimiento, excepto que sea necesario para proteger + a otras personas de abuso intencional. + + * Hacer pública una conversación privada de cualquier tipo. + + * Otros tipos de conducta que pudieran considerarse inapropiadas en un + entorno de camaradería. + + * Reiteración de actitudes que les participantes señalen como ofensivas + o violatorias de este código. + + ## Consecuencias + + * Se espera que la persona a la que se la haya pedido que cese un + comportamiento que infringe este código acate el pedido de forma + inmediata, incluso si no está de acuerdo con este. + + * Les administradores pueden tomar cualquier acción que juzguen + necesaria y adecuada, incluyendo expulsar a la persona o dar de baja + sus sitios sin advertencia. Esta decisión la toman les administradores + en consenso y se reserva para casos extremos que comprometan la + continuidad de la comunidad o bien la posibilidad de permanencia en + ella de otres participantes sin sentirse agraviades o amenazades. + + * Les administradores se reservan el derecho a prohibir la asistencia a + cualquier actividad futura o publicación de sitios. + + Como mencionamos antes, este código está en permanente mutación + colectiva. El objetivo principal es generar un ambiente inclusivo y no + expulsivo, un ambiente transparente y abierto en el que no haya + escalones faltantes ("el escalón que falta en la escalera y todo el + mundo sabe y avisa pero nadie se quiere hacer cargo"). Es importante que + se adapte a las actividades y se nutra de las contribuciones de les + usuaries. Recibir tus comentarios y aportes nos ayudará a cumplir con + su objetivo principal. + + ## ¡Sigamos en contacto! + + Si pasaste por alguna situación que quieras compartir --te hayas animado + o no a decirlo en el momento--, podés ponerte en contacto con nosotres. + + Con respecto a quejas o avisos acerca de situaciones de violencia, + acoso, abuso o repetición de conductas que se advirtieron como + intolerables, tomamos la responsabilidad de tenerlas en cuenta y + trabajar en ellas para que el resultado sea el favorable al espíritu de + colectiva que elegimos y describimos aquí. Si bien consideramos que las + prácticas punitivistas no van con nosotres, nuestra decisión explícita + es escuchar a la persona que se manifiesta como violentada o víctima y + acompañarla. From 3f3ef0041092c06ade35df5a0b278a4e79fc976c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:06:57 -0300 Subject: [PATCH 077/235] =?UTF-8?q?fix:=20solo=20crear=20el=20c=C3=B3digo?= =?UTF-8?q?=20de=20conducta=20si=20la=20plantilla=20lo=20soporta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit como fallback usamos page --- app/services/site_service.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 19b95302..e0fe17cd 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -143,13 +143,15 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do end def add_code_of_conduct + return unless site.layout?(:code_of_conduct) || site.layout?(:page) + # TODO: soportar más códigos de conducta coc = CodeOfConduct.first with_all_locales do |locale| params = ActionController::Parameters.new( post: { - layout: 'code_of_conduct', + layout: site.layout?(:code_of_conduct) ? 'code_of_conduct' : 'page', lang: locale.to_s, title: coc.title, description: coc.description, From 89ef2959e3c93a889677c3051a6987712a3434af Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:21:52 -0300 Subject: [PATCH 078/235] feat: usar un slug sino cuando cambia la licencia queda con la url de la anterior --- app/services/site_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index e0fe17cd..225c6292 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -106,6 +106,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do params = ActionController::Parameters.new( post: { layout: 'license', + slug: Jekyll::Utils.slugify(I18n.t('activerecord.models.licencia')), lang: lang, title: site.licencia.name, description: I18n.t('sites.form.licencia.title'), From e25b4858a01df490a66e5c818c0676828e45d539 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:23:51 -0300 Subject: [PATCH 079/235] fix: no cambiar las licencias si el sitio no las soporta --- app/services/site_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 225c6292..e4793453 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -120,6 +120,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Encuentra la licencia a partir de su enlace permanente y le cambia # el contenido def change_licencias + return unless site.layout? :license + site.locales.each do |locale| next unless I18n.available_locales.include? locale From 368001b341bfa0b6891a15088625c615d6839098 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:32:52 -0300 Subject: [PATCH 080/235] =?UTF-8?q?fix:=20poder=20encadenar=20licencias=20?= =?UTF-8?q?con=20c=C3=B3digos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/site_service.rb | 46 ++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index e4793453..47b532f4 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -90,18 +90,19 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do end # Crea la licencia del sitio para cada locale disponible en el sitio + # + # @return [Boolean] def add_licencias - return unless site.layout? :license + return true unless site.layout? :license - site.locales.each do |locale| - next unless I18n.available_locales.include? locale - - Mobility.with_locale(locale) do - add_licencia lang: locale - end - end + with_all_locales do |locale| + add_licencia lang: locale + end.compact.map(&:valid?).all? end + # Crea una licencia + # + # @return [Post] def add_licencia(lang:) params = ActionController::Parameters.new( post: { @@ -119,20 +120,22 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Encuentra la licencia a partir de su enlace permanente y le cambia # el contenido + # + # @return [Boolean] def change_licencias - return unless site.layout? :license + return true unless site.layout? :license - site.locales.each do |locale| - next unless I18n.available_locales.include? locale + with_all_locales do |locale| + post = site.posts(lang: locale).find_by(layout: 'license') - Mobility.with_locale(locale) do - post = site.posts(lang: locale).find_by(layout: 'license') - - change_licencia(post: post) if post - end - end + change_licencia(post: post) if post + end.compact.map(&:valid?).all? end + # Cambia una licencia + # + # @param :post [Post] + # @return [Post] def change_licencia(post:) params = ActionController::Parameters.new( post: { @@ -145,8 +148,11 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do params: params).update end + # Agrega un código de conducta + # + # @return [Boolean] def add_code_of_conduct - return unless site.layout?(:code_of_conduct) || site.layout?(:page) + return true unless site.layout?(:code_of_conduct) || site.layout?(:page) # TODO: soportar más códigos de conducta coc = CodeOfConduct.first @@ -163,7 +169,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do ) PostService.new(site: site, usuarie: usuarie, params: params).create - end + end.compact.map(&:valid?).all? end # Crea los deploys necesarios para sincronizar a otros nodos de Sutty @@ -176,7 +182,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do private def with_all_locales(&block) - site.locales.each do |locale| + site.locales.map do |locale| next unless I18n.available_locales.include? locale Mobility.with_locale(locale) do From 136a9e3edba9f5fe719c072c4b020996e90a9a28 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:44:17 -0300 Subject: [PATCH 081/235] =?UTF-8?q?fix:=20traducir=20la=20descripci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/site_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 47b532f4..449db16a 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -110,7 +110,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do slug: Jekyll::Utils.slugify(I18n.t('activerecord.models.licencia')), lang: lang, title: site.licencia.name, - description: I18n.t('sites.form.licencia.title'), + description: site.licencia.description, content: CommonMarker.render_html(site.licencia.deed) } ) From caa4861d79172cf6e49dab6c0e5cade15abcf023 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 19:54:04 -0300 Subject: [PATCH 082/235] fix: poder pasar el slug como parametro como slug es un atributo privado, hay que asignarlo manualmente --- app/services/post_service.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index e448bb4c..81ebe4a1 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -12,6 +12,10 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do post.usuaries << usuarie params[:post][:draft] = true if site.invitade? usuarie + params.require(:post).permit(:slug).tap do |p| + post.slug.value = p[:slug] if p[:slug].present? + end + commit(action: :created, file: update_related_posts) if post.update(post_params) # Devolver el post aunque no se haya salvado para poder rescatar los From 0263169074f7795ae719d074f9f90f7aa2163d5c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 20:00:39 -0300 Subject: [PATCH 083/235] fix: devolver true aunque no haga falta modificar la configuracion --- app/models/site/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/site/config.rb b/app/models/site/config.rb index 3215277e..11277a19 100644 --- a/app/models/site/config.rb +++ b/app/models/site/config.rb @@ -31,7 +31,7 @@ class Site # Escribe los cambios en el repositorio def write - return if persisted? + return true if persisted? @saved = Site::Writer.new(site: site, file: path, content: content.to_yaml).save From 0817139032ad0a93d4618fa6bcc78e474a4212bb Mon Sep 17 00:00:00 2001 From: f Date: Wed, 22 Mar 2023 21:01:29 -0300 Subject: [PATCH 084/235] =?UTF-8?q?feat:=20agregar=20pol=C3=ADtica=20de=20?= =?UTF-8?q?privacidad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/privacy_policy.rb | 14 +++ app/services/site_service.rb | 26 +++- config/initializers/inflections.rb | 4 + .../20230322231344_add_privacy_policy.rb | 22 ++++ db/seeds/privacy_policies.yml | 113 ++++++++++++++++++ 5 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 app/models/privacy_policy.rb create mode 100644 db/migrate/20230322231344_add_privacy_policy.rb create mode 100644 db/seeds/privacy_policies.yml diff --git a/app/models/privacy_policy.rb b/app/models/privacy_policy.rb new file mode 100644 index 00000000..8805daa9 --- /dev/null +++ b/app/models/privacy_policy.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Políticas de privacidad +class PrivacyPolicy < ApplicationRecord + extend Mobility + + translates :title, type: :string, locale_accessors: true + translates :description, type: :text, locale_accessors: true + translates :content, type: :text, locale_accessors: true + + validates :title, presence: true, uniqueness: true + validates :description, presence: true + validates :content, presence: true +end diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 449db16a..64b25297 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -16,7 +16,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do site.config.write && commit_config(action: :create) && add_licencias && - add_code_of_conduct + add_code_of_conduct && + add_privacy_policy end site @@ -172,6 +173,29 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do end.compact.map(&:valid?).all? end + # Agrega política de privacidad + # + # @return [Boolean] + def add_privacy_policy + return true unless site.layout?(:privacy_policy) || site.layout?(:page) + + pp = PrivacyPolicy.first + + with_all_locales do |locale| + params = ActionController::Parameters.new( + post: { + layout: site.layout?(:privacy_policy) ? 'privacy_policy' : 'page', + lang: locale.to_s, + title: pp.title, + description: pp.description, + content: CommonMarker.render_html(pp.content) + } + ) + + PostService.new(site: site, usuarie: usuarie, params: params).create + end.compact.map(&:valid?).all? + end + # Crea los deploys necesarios para sincronizar a otros nodos de Sutty def sync_nodes Rails.application.nodes.each do |node| diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 46cb9d78..6002ee65 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -15,6 +15,8 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.singular 'rollups', 'rollup' inflect.plural 'code_of_conduct', 'codes_of_conduct' inflect.singular 'codes_of_conduct', 'code_of_conduct' + inflect.plural 'privacy_policy', 'privacy_policies' + inflect.singular 'privacy_policies', 'privacy_policy' end ActiveSupport::Inflector.inflections(:es) do |inflect| @@ -32,4 +34,6 @@ ActiveSupport::Inflector.inflections(:es) do |inflect| inflect.singular 'rollups', 'rollup' inflect.plural 'code_of_conduct', 'codes_of_conduct' inflect.singular 'codes_of_conduct', 'code_of_conduct' + inflect.plural 'privacy_policy', 'privacy_policies' + inflect.singular 'privacy_policies', 'privacy_policy' end diff --git a/db/migrate/20230322231344_add_privacy_policy.rb b/db/migrate/20230322231344_add_privacy_policy.rb new file mode 100644 index 00000000..e0d7ae59 --- /dev/null +++ b/db/migrate/20230322231344_add_privacy_policy.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Agrega políticas de privacidad +class AddPrivacyPolicy < ActiveRecord::Migration[6.1] + def up + create_table :privacy_policies do |t| + t.timestamps + t.string :title + t.text :description + t.text :content + end + + # XXX: En lugar de ponerlo en las seeds + YAML.safe_load(File.read('db/seeds/privacy_policies.yml')).each do |pp| + PrivacyPolicy.new(**pp).save! + end + end + + def down + drop_table :privacy_policies + end +end diff --git a/db/seeds/privacy_policies.yml b/db/seeds/privacy_policies.yml new file mode 100644 index 00000000..98ce8379 --- /dev/null +++ b/db/seeds/privacy_policies.yml @@ -0,0 +1,113 @@ +--- +- title_en: "Privacy Policy" + title_es: "Políticas de privacidad" + description_en: "With what care does this site handles personal data of its users and visitors?" + description_es: "¿Cuáles son los cuidados de este sitio con respecto a sus usuaries y visitantes?" + content_en: | + > We use "them" as neutral pronoun to refer to people regardless of + > gender identity. + + This document details Sutty's privacy policy, including web site, + platform, other infrastructure (support channels, etc.) and web sites + generated by users. + + ## This is too long! + + * Sutty doesn't collect any kind of personal data. + + * Sutty may only collect statistical data that doesn't identify + individuals. + + ## Analytic data + + Sutty may only collect data for analytics (number of visits, duration, + etc.), not associated to personal data. + + Analytical data collected for every web site can only be used internally + by Sutty. Sutty doesn't share any data privately with any third + parties. Selected analytical data could be used publicly. + + Sutty doesn't recommend personal data collection in any way, but it + doesn't monitor if its users use third party services with their own + privacy policies. We recommend users and visitors to inform themselves + before using third parties analytics services. + + ## No personal data collection + + Sutty doesn't collect IP addresses from users nor visitors in any way. + + Sutty doesn't ask for personal data for registering user accounts in its + platform. + + Sutty only uses session "cookies" to identify users during their use of + the platform. It doesn't use "cookies" to identify visitors of web + sites hosted by Sutty. + + The only exception where Sutty could collect personal data is during + service payment. Digital safety measures will be taken to keep this + information and to discard it if possible after needed. + + Users will be notified when their personal data is removed. + + If users decide to host their web sites with third parties, they must + inform themselves about the corresponding privacy policies. Sutty only + recommends third parties with privacy policies compatible with these. + content_es: | + > Utilizamos la e como pronombre neutro para referirnos a personas + > independientemente de su identidad de género, por ejemplo “usuarie”. + + Este documento detalla la política de privacidad de Sutty, incluyendo + sitio web, plataforma de edición, infraestructura relacionada (salas de + chat, etc.) y sitios creados por sus usuaries a través de la plataforma, + en adelante "Sutty". + + ## ¡Esto es demasiado largo! + + Un resumen: + + * Sutty no recolecta datos personales de ningún tipo + + * Sutty solo recolectaría datos analíticos que no identifican a + personas + + ## Datos analíticos + + La única recolección de datos realizada por Sutty es con fines + analíticos (cantidad de visitas, duración, etc.), no asociados a datos + personales. + + Los datos analíticos recolectados por cada sitio podrán ser utilizados + internamente por Sutty. Sutty no comparte datos analíticos con + terceros en forma privada. Datos analíticos seleccionados podrán ser + utilizados públicamente. + + Sutty no recomienda la recolección de datos personales de ninguna forma, + pero no monitorea que les usuaries utilicen servicios de terceros con + sus propias políticas de privacidad. Recomendamos a les usuaries y + visitantes informarse antes de utilizar servicios de estadísticas de + terceros. + + ## No registro de datos personales + + Sutty no registra direcciones IP de usuaries ni de visitantes de ninguna + forma. + + Sutty no solicita datos personales para el registro de cuentas de + usuarie en su plataforma. + + Sutty solo utiliza “cookies” de sesión para identificar usuaries + mientras utilicen la plataforma. No se utilizan “cookies” para + identificar visitantes a los sitios alojados por Sutty. + + El único caso en el que Sutty podría solicitar datos personales es + durante el pago de servicios. Se tomarán medidas de seguridad digital + para salvaguardar esta información y descartar lo que sea posible una + vez que ya no sea necesaria. + + Se notificará a les usuaries cuando su información personal sea + eliminada. + + Si les usuaries deciden alojar sus sitios con terceros, deberán + informarse de las políticas de privacidad correspondientes. Sutty + recomienda servicios de terceros con políticas de privacidad coherentes + con estas. From 5cda6a440c00879b3ba6418c208fb2af9b8852b5 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 14:11:19 -0300 Subject: [PATCH 085/235] fix: enviar los argumentos como un hash closes ##12742 closes ##12740 closes ##12734 closes ##12732 closes ##12725 closes ##12721 closes ##12718 closes ##12715 --- config/initializers/sucker_punch.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/sucker_punch.rb b/config/initializers/sucker_punch.rb index 19506c2d..ce1209dd 100644 --- a/config/initializers/sucker_punch.rb +++ b/config/initializers/sucker_punch.rb @@ -2,5 +2,5 @@ # Enviar una notificación cuando falla una tarea SuckerPunch.exception_handler = lambda { |ex, _, args| - ExceptionNotifier.notify_exception(ex, data: args) + ExceptionNotifier.notify_exception(ex, data: { args: args }) } From 98b38e4caabcfa354b4d90e05112d1031fefcf7a Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 15:14:53 -0300 Subject: [PATCH 086/235] =?UTF-8?q?fix:=20el=20=C3=BAltimo=20=C3=ADtem=20e?= =?UTF-8?q?s=20un=20hash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #12747 --- config/initializers/sucker_punch.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/sucker_punch.rb b/config/initializers/sucker_punch.rb index ce1209dd..21997139 100644 --- a/config/initializers/sucker_punch.rb +++ b/config/initializers/sucker_punch.rb @@ -2,5 +2,5 @@ # Enviar una notificación cuando falla una tarea SuckerPunch.exception_handler = lambda { |ex, _, args| - ExceptionNotifier.notify_exception(ex, data: { args: args }) + ExceptionNotifier.notify_exception(ex, data: args.last) } From d01f4ae5e2432b7f34835a1ca50e1629d8ba96c1 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 16:53:06 -0300 Subject: [PATCH 087/235] =?UTF-8?q?fix:=20volver=20a=20leer=20el=20sitio?= =?UTF-8?q?=20despu=C3=A9s=20de=20guardarlo=20#12755?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/site_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 64b25297..eaefca3a 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -15,6 +15,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do site.save && site.config.write && commit_config(action: :create) && + site.reset.nil? && add_licencias && add_code_of_conduct && add_privacy_policy @@ -29,6 +30,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do site.update(params) && site.config.write && commit_config(action: :update) && + site.reset.nil? && change_licencias end From 7a13dffc9b29e89525b9a6e37a38714d53fa9993 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 17:21:05 -0300 Subject: [PATCH 088/235] =?UTF-8?q?fix:=20establecer=20un=20par=C3=A1metro?= =?UTF-8?q?=20por=20defecto=20#12754?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/usuaries_controller.rb | 12 ++++++------ app/models/rol.rb | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/controllers/usuaries_controller.rb b/app/controllers/usuaries_controller.rb index 6d02a35a..746ee822 100644 --- a/app/controllers/usuaries_controller.rb +++ b/app/controllers/usuaries_controller.rb @@ -72,6 +72,8 @@ class UsuariesController < ApplicationController site_usuarie = SiteUsuarie.new(@site, current_usuarie) authorize site_usuarie + params[:invite_as] = invited_as :invite_as + @policy = policy(site_usuarie) end @@ -155,12 +157,10 @@ class UsuariesController < ApplicationController # El tipo de invitación que tenemos que enviar, si alguien mandó # cualquier cosa, usamos el privilegio menor. - def invited_as - if Rol::ROLES.include?(params[:invited_as]) - params[:invited_as] - else - 'invitade' - end + # + # @return [String] + def invited_as(param_key = :invited_as) + Rol.role?(params[param_key]) ? params[param_key] : Rol::INVITADE end def site diff --git a/app/models/rol.rb b/app/models/rol.rb index 5879d666..fcd07037 100644 --- a/app/models/rol.rb +++ b/app/models/rol.rb @@ -21,4 +21,8 @@ class Rol < ApplicationRecord def usuarie? rol == USUARIE end + + def self.role?(rol) + ROLES.include? rol + end end From df8efe800bb6c62b33df9624019e1468d3899cfe Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 17:38:48 -0300 Subject: [PATCH 089/235] fix: no hardcodear roles --- app/controllers/usuaries_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/usuaries_controller.rb b/app/controllers/usuaries_controller.rb index 746ee822..4db6aafd 100644 --- a/app/controllers/usuaries_controller.rb +++ b/app/controllers/usuaries_controller.rb @@ -47,7 +47,7 @@ class UsuariesController < ApplicationController @usuarie = Usuarie.find(params[:usuarie_id]) if @site.usuaries.count > 1 - @usuarie.rol_for_site(@site).update_attribute :rol, 'invitade' + @usuarie.rol_for_site(@site).update_attribute :rol, Rol::INVITADE else flash[:warning] = I18n.t('usuaries.index.demote.denied') end @@ -61,7 +61,7 @@ class UsuariesController < ApplicationController authorize SiteUsuarie.new(@site, current_usuarie) @usuarie = Usuarie.find(params[:usuarie_id]) - @usuarie.rol_for_site(@site).update_attribute :rol, 'usuarie' + @usuarie.rol_for_site(@site).update_attribute :rol, Rol::USUARIE redirect_to site_usuaries_path end From c2fbc06d4102eab6b45a3b567795dfac7a198e47 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 17:50:24 -0300 Subject: [PATCH 090/235] =?UTF-8?q?fix:=20tenemos=20un=20l=C3=ADo=20de=20s?= =?UTF-8?q?ingulares=20y=20plurales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/usuaries_controller.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/usuaries_controller.rb b/app/controllers/usuaries_controller.rb index 4db6aafd..716668a9 100644 --- a/app/controllers/usuaries_controller.rb +++ b/app/controllers/usuaries_controller.rb @@ -72,7 +72,7 @@ class UsuariesController < ApplicationController site_usuarie = SiteUsuarie.new(@site, current_usuarie) authorize site_usuarie - params[:invite_as] = invited_as :invite_as + params[:invite_as] = invite_as @policy = policy(site_usuarie) end @@ -159,8 +159,12 @@ class UsuariesController < ApplicationController # cualquier cosa, usamos el privilegio menor. # # @return [String] - def invited_as(param_key = :invited_as) - Rol.role?(params[param_key]) ? params[param_key] : Rol::INVITADE + def invited_as + Rol.role?(params[:invited_as]) ? params[:invited_as] : Rol::INVITADE + end + + def invite_as + Rol.role?(params[:invite_as].singularize) ? params[:invite_as] : Rol::INVITADE.pluralize end def site From c9fa518b337b9426abb0a22ec61543582ef3bef5 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 17:53:13 -0300 Subject: [PATCH 091/235] =?UTF-8?q?fix:=20el=20parametro=20puede=20venir?= =?UTF-8?q?=20vac=C3=ADo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/usuaries_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/usuaries_controller.rb b/app/controllers/usuaries_controller.rb index 716668a9..d75f3c20 100644 --- a/app/controllers/usuaries_controller.rb +++ b/app/controllers/usuaries_controller.rb @@ -164,7 +164,7 @@ class UsuariesController < ApplicationController end def invite_as - Rol.role?(params[:invite_as].singularize) ? params[:invite_as] : Rol::INVITADE.pluralize + Rol.role?(params[:invite_as]&.singularize) ? params[:invite_as] : Rol::INVITADE.pluralize end def site From b51eb6856c358414a7d4f86cf45db8f511e8a78d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 24 Mar 2023 11:50:25 -0300 Subject: [PATCH 092/235] =?UTF-8?q?fix:=20siempre=20devolver=20una=20relac?= =?UTF-8?q?i=C3=B3n=20#12768?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_locales.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 2e9080c9..3790b944 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -44,6 +44,6 @@ class MetadataLocales < MetadataHasAndBelongsToMany def posts other_locales.map do |locale| site.posts(lang: locale).where(layout: post.layout.value) - end.reduce(&:concat) + end.reduce(&:concat) || PostRelation.new end end From 42b2549f09e5fe9b3f33d6c632995253155400da Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 13:46:30 -0300 Subject: [PATCH 093/235] =?UTF-8?q?feat:=20agregar=20una=20descripci=C3=B3?= =?UTF-8?q?n=20corta=20a=20la=20licencia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit que es lo que usan las plantillas como aviso de licencia --- app/services/site_service.rb | 2 +- ...5163802_add_short_description_to_licencias.rb | 16 ++++++++++++++++ db/seeds/licencias.yml | 6 ++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20230325163802_add_short_description_to_licencias.rb diff --git a/app/services/site_service.rb b/app/services/site_service.rb index eaefca3a..2719a26c 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -113,7 +113,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do slug: Jekyll::Utils.slugify(I18n.t('activerecord.models.licencia')), lang: lang, title: site.licencia.name, - description: site.licencia.description, + description: site.licencia.short_description, content: CommonMarker.render_html(site.licencia.deed) } ) diff --git a/db/migrate/20230325163802_add_short_description_to_licencias.rb b/db/migrate/20230325163802_add_short_description_to_licencias.rb new file mode 100644 index 00000000..efcc01e4 --- /dev/null +++ b/db/migrate/20230325163802_add_short_description_to_licencias.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Agrega descripciones cortas a las licencias +class AddShortDescriptionToLicencias < ActiveRecord::Migration[6.1] + def up + add_column :licencias, :short_description, :string + + YAML.safe_load_file('db/seeds/licencias.yml').each do |licencia| + Licencia.find_by_icons(licencia['icons']).update licencia + end + end + + def down + remove_column :licencias, :short_description + end +end diff --git a/db/seeds/licencias.yml b/db/seeds/licencias.yml index cbe3bace..c5e2886a 100644 --- a/db/seeds/licencias.yml +++ b/db/seeds/licencias.yml @@ -1,6 +1,8 @@ --- - name_en: 'Peer Production License' name_es: 'Licencia de Producción de Pares' + short_description_en: "This work is licensed under a Peer Production License" + short_description_es: "Esta obra está bajo una Licencia de Producción de Pares" icons: "/images/ppl.png" url_en: 'https://wiki.p2pfoundation.net/Peer_Production_License' url_es: 'https://endefensadelsl.org/ppl_es.html' @@ -100,6 +102,8 @@ hacerlo es enlazar a esta página. - icons: "/images/by.png" + short_description_en: "This work is licensed under a Creative Commons Attribution 4.0 International License." + short_description_es: "Esta obra está bajo una Licencia Creative Commons Atribución 4.0 Internacional." name_en: 'Creative Commons Attribution 4.0 International (CC BY 4.0)' description_en: "This license gives everyone the freedom to use, adapt, and redistribute the contents of your site by requiring @@ -194,6 +198,8 @@ - icons: "/images/sa.png" name_en: "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)" name_es: "Creative Commons Atribución-CompartirIgual 4.0 Internacional (CC BY-SA 4.0)" + short_description_en: "This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License." + short_description_es: "Esta obra está bajo una Licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional." url_en: 'https://creativecommons.org/licenses/by-sa/4.0/' url_es: 'https://creativecommons.org/licenses/by-sa/4.0/deed.es' description_en: "This license is the same as the CC-BY 4.0 but it adds From c62d0d3a7254779f728fd14c224e2dc56127082e Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 13:48:30 -0300 Subject: [PATCH 094/235] =?UTF-8?q?fixup!=20feat:=20agregar=20una=20descri?= =?UTF-8?q?pci=C3=B3n=20corta=20a=20la=20licencia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/licencia.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/licencia.rb b/app/models/licencia.rb index c0eb1c80..f0a542ef 100644 --- a/app/models/licencia.rb +++ b/app/models/licencia.rb @@ -7,6 +7,7 @@ class Licencia < ApplicationRecord translates :name, type: :string, locale_accessors: true translates :url, type: :string, locale_accessors: true translates :description, type: :text, locale_accessors: true + translates :short_description, type: :string, locale_accessors: true translates :deed, type: :text, locale_accessors: true has_many :sites @@ -14,5 +15,6 @@ class Licencia < ApplicationRecord validates :name, presence: true, uniqueness: true validates :url, presence: true validates :description, presence: true + validates :short_description, presence: true validates :deed, presence: true end From d44ca16f81ec09f39713a94ee74da2b28c8b91e0 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 13:51:07 -0300 Subject: [PATCH 095/235] =?UTF-8?q?fix:=20cambiar=20la=20descripci=C3=B3n?= =?UTF-8?q?=20de=20la=20licencia=20tambi=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/site_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 2719a26c..ce596482 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -143,6 +143,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do params = ActionController::Parameters.new( post: { title: site.licencia.name, + description: site.licencia.short_description, content: CommonMarker.render_html(site.licencia.deed) } ) From 960c8dcca450a27ab410833e6c5c35bcb9b8ccbf Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 14:50:36 -0300 Subject: [PATCH 096/235] feat: implementar un servicio liviano de git-lfs #9361 --- app/services/lfs_object_service.rb | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 app/services/lfs_object_service.rb diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb new file mode 100644 index 00000000..65db113d --- /dev/null +++ b/app/services/lfs_object_service.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +# Representa un objeto git LFS +class LfsObjectService + attr_reader :site, :blob, :usuarie + + # @param :site [Site] + # @param :blob [ActiveStorage::Blob] + def initialize(site:, blob:, usuarie:) + @site = site + @blob = blob + @usuarie = usuarie + end + + def process + # Crear el directorio + FileUtils.mkdir_p(File.dirname(object_path)) + + # Mover el archivo + FileUtils.mv(path, object_path) unless File.exist? object_path + + # Crear el pointer + Site::Writer.new(site: site, file: path, content: pointer).save + + # Commitear el pointer + site.repository.commit(file: path, usuarie: usuarie, message: File.basename(path)) + + # Eliminar el pointer + FileUtils.rm(path) + + # Hacer link duro del objeto al archivo + FileUtils.ln(object_path, path) + end + + # @return [String] + def path + @path ||= blob.service.path_for(blob.key) + end + + # @return [String] + def digest + @digest ||= Digest::SHA256.file(path).hexdigest + end + + # @return [String] + def object_path + @git_lfs_object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) + end + + # @return [Integer] + def size + @size ||= File.size(File.exist?(object_path) ? object_path : path) + end + + # @return [String] + def pointer + @pointer ||= + <<~POINTER + version https://git-lfs.github.com/spec/v1 + oid sha256:#{digest} + size #{size} + POINTER + end +end From 2215a00727d60d18147e76692dfe797a1183bd38 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:22:54 -0300 Subject: [PATCH 097/235] feat: commitear el archivo en lfs al subirlo --- app/lib/active_storage/service/jekyll_service.rb | 15 +++++++++------ app/services/lfs_object_service.rb | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 88ffa83c..6763ee0d 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -4,11 +4,6 @@ module ActiveStorage class Service # Sube los archivos a cada repositorio y los agrega al LFS de su # repositorio git. - # - # @todo: Implementar LFS. No nos gusta mucho la idea porque duplica - # el espacio en disco, pero es la única forma que tenemos (hasta que - # implementemos IPFS) para poder transferir los archivos junto con el - # sitio. class JekyllService < Service::DiskService # Genera un servicio para un sitio determinado # @@ -27,7 +22,10 @@ module ActiveStorage # @param :checksum [String] def upload(key, io, checksum: nil, **) instrument :upload, key: key, checksum: checksum do - IO.copy_stream(io, make_path_for(key)) unless exist?(key) + unless exist?(key) + IO.copy_stream(io, make_path_for(key)) + LfsObjectService.new(site: site, usuarie: current_usuarie, blob: blob).process + end ensure_integrity_of(key, checksum) if checksum end end @@ -91,6 +89,11 @@ module ActiveStorage def path_for(key) File.join root, folder_for(key), filename_for(key) end + + # @return [Site] + def site + @site ||= Site.find_by_name(File.basename(root)) + end end end end diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb index 65db113d..61775e12 100644 --- a/app/services/lfs_object_service.rb +++ b/app/services/lfs_object_service.rb @@ -44,7 +44,7 @@ class LfsObjectService # @return [String] def object_path - @git_lfs_object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) + @object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) end # @return [Integer] From 2940b5d3e818d047afedf173df0d7a2d6b6f0613 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:29:49 -0300 Subject: [PATCH 098/235] =?UTF-8?q?fix:=20no=20podemos=20saber=20qui=C3=A9?= =?UTF-8?q?n=20subi=C3=B3=20el=20archivo=20todav=C3=ADa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/active_storage/service/jekyll_service.rb | 2 +- app/services/lfs_object_service.rb | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 6763ee0d..f399f440 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -24,7 +24,7 @@ module ActiveStorage instrument :upload, key: key, checksum: checksum do unless exist?(key) IO.copy_stream(io, make_path_for(key)) - LfsObjectService.new(site: site, usuarie: current_usuarie, blob: blob).process + LfsObjectService.new(site: site, blob: blob).process end ensure_integrity_of(key, checksum) if checksum end diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb index 61775e12..bb62301d 100644 --- a/app/services/lfs_object_service.rb +++ b/app/services/lfs_object_service.rb @@ -2,14 +2,13 @@ # Representa un objeto git LFS class LfsObjectService - attr_reader :site, :blob, :usuarie + attr_reader :site, :blob # @param :site [Site] # @param :blob [ActiveStorage::Blob] - def initialize(site:, blob:, usuarie:) + def initialize(site:, blob:) @site = site @blob = blob - @usuarie = usuarie end def process @@ -23,7 +22,7 @@ class LfsObjectService Site::Writer.new(site: site, file: path, content: pointer).save # Commitear el pointer - site.repository.commit(file: path, usuarie: usuarie, message: File.basename(path)) + site.repository.commit(file: path, usuarie: author, message: File.basename(path)) # Eliminar el pointer FileUtils.rm(path) @@ -61,4 +60,8 @@ class LfsObjectService size #{size} POINTER end + + def author + @author ||= GitAuthor.new email: "disk_service@#{Site.domain}", name: 'DiskService' + end end From 2fb5bc24d5d21fdc2d32146ef114518ed96140c8 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:34:47 -0300 Subject: [PATCH 099/235] fix: encontrar el blob para este servicio --- app/lib/active_storage/service/jekyll_service.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index f399f440..e6c5fda6 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -24,7 +24,7 @@ module ActiveStorage instrument :upload, key: key, checksum: checksum do unless exist?(key) IO.copy_stream(io, make_path_for(key)) - LfsObjectService.new(site: site, blob: blob).process + LfsObjectService.new(site: site, blob: blob_for(key)).process end ensure_integrity_of(key, checksum) if checksum end @@ -77,7 +77,7 @@ module ActiveStorage # @param :key [String] # @return [String] def filename_for(key) - ActiveStorage::Blob.where(key: key).limit(1).pluck(:filename).first.tap do |filename| + blob_for(key).filename.to_s.tap do |filename| raise ArgumentError, "Filename for key #{key} is blank" if filename.blank? end end @@ -92,7 +92,11 @@ module ActiveStorage # @return [Site] def site - @site ||= Site.find_by_name(File.basename(root)) + @site ||= Site.find_by_name(name) + end + + def blob_for(key) + ActiveStorage::Blob.find_by(key: key, service_name: name) end end end From 6b759c92ce0ad52caae465926af55edccc85f402 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 11:45:23 -0300 Subject: [PATCH 100/235] fix: instalar las gemas cuando sea necesario #12755 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit si se modificó el gemfile queremos volver a instalarlas también --- app/models/site.rb | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 4b2a8eb9..6110f104 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -553,10 +553,33 @@ class Site < ApplicationRecord Dir.chdir path, &block end + # Instala las gemas cuando es necesario: + # + # * El sitio existe + # * No están instaladas + # * El archivo Gemfile se modificó + # * El archivo Gemfile.lock se modificó def install_gems return unless persisted? - return if Rails.root.join('_storage', 'gems', name).directory? - deploys.find_by_type('DeployLocal').send(:bundle) + if !gem_dir? || gemfile_updated? || gemfile_lock_updated? + deploys.find_by_type('DeployLocal').send(:bundle) + touch + end + end + + # Detecta si el repositorio de gemas existe + def gem_dir? + Rails.root.join('_storage', 'gems', name).directory? + end + + # Detecta si el Gemfile fue modificado + def gemfile_updated? + updated_at > File.mtime(File.join(path, 'Gemfile')) + end + + # Detecta si el Gemfile.lock fue modificado + def gemfile_lock_updated? + updated_at > File.mtime(File.join(path, 'Gemfile.lock')) end end From 5d40fabe54c34108cdbb5b42ca629568bbaf35d7 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 12:38:31 -0300 Subject: [PATCH 101/235] feat: ordenar los sitios por actividad #12762 --- app/controllers/sites_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index f0eff0dc..7b1496e9 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -10,7 +10,7 @@ class SitesController < ApplicationController # Ver un listado de sitios def index authorize Site - @sites = current_usuarie.sites.order(:title) + @sites = current_usuarie.sites.order(updated_at: :desc) fresh_when @sites end From 706d829613eb60849847f246d8ef4b99e8992821 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 18:46:41 -0300 Subject: [PATCH 102/235] feat: componente de mensajes resaltados --- app/views/bootstrap/_alert.haml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/views/bootstrap/_alert.haml diff --git a/app/views/bootstrap/_alert.haml b/app/views/bootstrap/_alert.haml new file mode 100644 index 00000000..0fb3d2d3 --- /dev/null +++ b/app/views/bootstrap/_alert.haml @@ -0,0 +1,2 @@ +.alert.alert-primary{ role: 'alert', class: local_assigns[:class] } + = yield From d48231e725c9cb1929d9cf9e863d39aaeed3aae5 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 18:52:42 -0300 Subject: [PATCH 103/235] fix: usar siempre el componente --- app/views/invitadxs/show.haml | 2 +- app/views/layouts/_flash.haml | 3 ++- app/views/layouts/_help.haml | 1 + app/views/posts/_form.haml | 8 +++++--- app/views/posts/_submit.haml | 4 ++-- app/views/posts/attributes/_content.haml | 4 ++-- app/views/posts/index.haml | 2 +- app/views/sites/_form.haml | 10 ++++++---- 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/views/invitadxs/show.haml b/app/views/invitadxs/show.haml index e1d47288..0c23522b 100644 --- a/app/views/invitadxs/show.haml +++ b/app/views/invitadxs/show.haml @@ -1,4 +1,4 @@ .row.align-items-center.justify-content-center.full-height .col-md-6.align-self-center - .alert{role: 'alert', class: "alert-success"} + = render 'bootstrap/alert' do = t('.confirmation_sent') diff --git a/app/views/layouts/_flash.haml b/app/views/layouts/_flash.haml index 149f946f..7bd7ec0b 100644 --- a/app/views/layouts/_flash.haml +++ b/app/views/layouts/_flash.haml @@ -1,3 +1,4 @@ - flash.each do |type, message| - unless type == 'js' - .alert{ role: 'alert', class: "alert-#{type}" }= message + = render 'bootstrap/alert' do + = message diff --git a/app/views/layouts/_help.haml b/app/views/layouts/_help.haml index 7a821e2d..6800b524 100644 --- a/app/views/layouts/_help.haml +++ b/app/views/layouts/_help.haml @@ -1,3 +1,4 @@ +-# DEPRECADO .alert.alert-info.alert-dismissible.fade.show{role: 'alert'} - if help.respond_to? :each %ul diff --git a/app/views/posts/_form.haml b/app/views/posts/_form.haml index e46b2eda..f81cef58 100644 --- a/app/views/posts/_form.haml +++ b/app/views/posts/_form.haml @@ -1,7 +1,9 @@ - unless post.errors.empty? - .alert.alert-danger - %h4= t('.errors.title') - %p= t('.errors.help') + - title = t('.errors.title') + - help = t('.errors.help') + = render 'boostrap/alert' do + %h4= title + %p= help %ul - post.errors.each do |attribute, errors| diff --git a/app/views/posts/_submit.haml b/app/views/posts/_submit.haml index b21b5ff2..717b8bfe 100644 --- a/app/views/posts/_submit.haml +++ b/app/views/posts/_submit.haml @@ -1,6 +1,6 @@ .form-group = submit_tag t('.save'), class: 'btn submit-post' - .invalid-help.alert.alert-danger.d-none + = render 'boostrap/alert', class: 'invalid-help d-none' do = site.config.fetch('invalid_help', t('.invalid_help')) - .sending-help.alert.alert-success.d-none + = render 'boostrap/alert', class: 'sending-help d-none' do = site.config.fetch('sending_help', t('.sending_help')) diff --git a/app/views/posts/attributes/_content.haml b/app/views/posts/attributes/_content.haml index 36b88872..5db023fb 100644 --- a/app/views/posts/attributes/_content.haml +++ b/app/views/posts/attributes/_content.haml @@ -6,7 +6,7 @@ .editor{ id: attribute, data: { editor: '' } } -# Esto es para luego decirle al navegador que se olvide estas cosas. = hidden_field_tag 'storage_keys[]', "#{request.original_url}##{attribute}", data: { target: 'storage-key' } - .alert.alert-info + = render 'bootstrap/alert' do :markdown #{t('editor.alert')} = text_area_tag "#{base}[#{attribute}]", '', @@ -123,7 +123,7 @@ %label{ for: 'link-url' }= t('editor.url') %input.form-control{ type: 'url', id: 'link-url', name: 'link-url' }/ - .editor-aviso-word.alert.alert-info + = render 'bootstrap/alert', class: 'editor-aviso-word' do %p= t('editor.word') .editor-content.form-control.h-auto.mt-1{ contenteditable: 'true' } diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index a82616d8..54587fc5 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -34,7 +34,7 @@ = render 'sites/build', site: @site - if @site.design.credits - .alert.alert-primary{ role: 'alert' } + = render 'bootstrap/alert' do = sanitize_markdown @site.design.credits = link_to t('sites.donations.text'), t('sites.donations.url'), class: 'btn' - if @site.design.designer_url diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index 9a044c7f..757b8b48 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -1,7 +1,9 @@ - unless site.errors.empty? - .alert.alert-info - %h4= t('.errors.title') - %p.lead= t('.errors.help') + - title = t('.errors.title') + - help = t('.errors.help') + = render 'bootstrap/alert' do + %h4= title + %p.lead= help %ul - site.errors.messages.each_pair do |attr, error| - attr = attr.to_s @@ -48,7 +50,7 @@ %h2= t('.design.title') %p.lead= t('.help.design') - if invalid? site, :design_id - .alert.alert-info + = render 'bootstrap/alert' do = t('activerecord.errors.models.site.attributes.design_id.layout_incompatible.help', layouts: site.incompatible_layouts.to_sentence) .row.designs From 74a19ad9d9ced91d4e64dba51a48b4138ef133bb Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 18:55:48 -0300 Subject: [PATCH 104/235] feat: mostrar los mensajes en todas las vistas #12792 --- app/views/collaborations/collaborate.haml | 1 - app/views/devise/sessions/new.haml | 2 -- app/views/layouts/application.html.haml | 3 +++ app/views/posts/index.haml | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/collaborations/collaborate.haml b/app/views/collaborations/collaborate.haml index 50cad809..4d43ad7e 100644 --- a/app/views/collaborations/collaborate.haml +++ b/app/views/collaborations/collaborate.haml @@ -11,7 +11,6 @@ url: site_collaborate_path(@site), method: :post) do |f| - unless current_usuarie - = render 'layouts/flash' .form-group = f.label :email = f.email_field :email, autofocus: true, autocomplete: 'email', diff --git a/app/views/devise/sessions/new.haml b/app/views/devise/sessions/new.haml index b5223e5f..9b396187 100644 --- a/app/views/devise/sessions/new.haml +++ b/app/views/devise/sessions/new.haml @@ -3,8 +3,6 @@ .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center - = render 'layouts/flash' - .sr-only %h2= t('.sign_in') %p= t('.help') diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 85d5ab22..965a856f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -21,6 +21,9 @@ %body{ class: yield(:body) } .container-fluid#sutty = render 'layouts/breadcrumb' + = render 'layouts/flash' + = yield + - if flash[:js] .js-flash.d-none{ data: flash[:js] } diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 54587fc5..dbeddaad 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -41,7 +41,6 @@ = link_to t('sites.designer_url'), @site.design.designer_url, class: 'btn' %section.col - = render 'layouts/flash' .d-flex.justify-content-between.align-items-center.pl-2-plus.pr-2-plus.mb-2 %form{ action: site_posts_path } - @filter_params.each do |param, value| From f3845c755f5057ac4512120041ccfdbf30badf75 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:03:00 -0300 Subject: [PATCH 105/235] fix: informar que hay que confirmar la cuenta --- config/locales/devise.views.en.yml | 2 +- config/locales/devise.views.es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index fd041b33..ae024645 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -104,7 +104,7 @@ en: new: sign_up: Sign up help: We only ask for an e-mail address and a password. The password is safely stored, no one else besides you knows it! You'll also receive an e-mail to confirm your account. - signed_up: Welcome! You have signed up successfully. + signed_up: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." signed_up_but_inactive: You have signed up successfully. However, we could not sign you in because your account is not yet activated. signed_up_but_locked: You have signed up successfully. However, we could not sign you in because your account is locked. signed_up_but_unconfirmed: A message with a confirmation link has been sent to your email address. Please follow the link to activate your account. diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index 73166afc..b9e2e5e4 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -104,7 +104,7 @@ es: new: sign_up: Registrarme help: Para registrarte solo pedimos una dirección de correo y una contraseña. La contraseña se almacena de forma segura, ¡nadie más que vos la sabe! Recibirás un correo de confirmación de cuenta. - signed_up: Bienvenide. Tu cuenta fue creada. + signed_up: "Hemos enviado un mensaje con un enlace de confirmación a tu correo electrónico. Por favor, abrí el enlace para terminar de activar tu cuenta." signed_up_but_inactive: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque tu cuenta aún no está activada. signed_up_but_locked: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque que tu cuenta está bloqueada. signed_up_but_unconfirmed: Para recibir actualizaciones, se ha enviado un mensaje con un enlace de confirmación a tu correo electrónico. Abre el enlace para activar tu cuenta. From b415b3f3cfba3bb8dfc70c71b63038b1674201bd Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:05:15 -0300 Subject: [PATCH 106/235] =?UTF-8?q?fix:=20especificar=20d=C3=B3nde=20se=20?= =?UTF-8?q?puede=20pedir=20reconfirmaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/devise.views.en.yml | 2 +- config/locales/devise.views.es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index ae024645..33f7870b 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -138,7 +138,7 @@ en: errors: messages: already_confirmed: was already confirmed, please try signing in - confirmation_period_expired: needs to be confirmed within %{period}, please request a new one + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one using the \"Didn't receive confirmation instructions?\" link" expired: has expired, please request a new one not_found: not found not_locked: was not locked diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index b9e2e5e4..63e3ae41 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -138,7 +138,7 @@ es: errors: messages: already_confirmed: ya ha sido confirmada, por favor intenta iniciar sesión - confirmation_period_expired: necesita confirmarse dentro de %{period}, por favor solicita una nueva + confirmation_period_expired: "necesita confirmarse dentro de %{period}, por favor solicita un nuevo código de confirmación usando la opción \"¿No has recibido las instrucciones de confirmación?\"" expired: ha expirado, por favor solicita una nueva not_found: no se ha encontrado not_locked: no estaba bloqueada From 40e68da16a59d9220299ab6c42428e414de293c2 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:18:11 -0300 Subject: [PATCH 107/235] fix: mostrar los errores de devise --- app/views/devise/confirmations/new.haml | 4 ++-- app/views/devise/invitations/edit.haml | 3 ++- app/views/devise/invitations/new.haml | 3 ++- app/views/devise/passwords/edit.haml | 3 ++- app/views/devise/passwords/new.haml | 3 ++- app/views/devise/registrations/edit.haml | 4 ++-- app/views/devise/registrations/new.haml | 4 ++-- app/views/devise/shared/_error_messages.haml | 9 ++++----- app/views/devise/unlocks/new.haml | 3 ++- 9 files changed, 20 insertions(+), 16 deletions(-) diff --git a/app/views/devise/confirmations/new.haml b/app/views/devise/confirmations/new.haml index 59568cb7..bc2f77bb 100644 --- a/app/views/devise/confirmations/new.haml +++ b/app/views/devise/confirmations/new.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-4.align-self-center .sr-only @@ -11,8 +13,6 @@ url: confirmation_path(resource_name), html: { method: :post }) do |f| - = render 'devise/shared/error_messages', resource: resource - :ruby value = if resource.pending_reconfirmation? resource.unconfirmed_email diff --git a/app/views/devise/invitations/edit.haml b/app/views/devise/invitations/edit.haml index 565429a8..ed4980ef 100644 --- a/app/views/devise/invitations/edit.haml +++ b/app/views/devise/invitations/edit.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center %h2= t 'devise.invitations.edit.header' @@ -8,7 +10,6 @@ as: resource_name, url: invitation_path(resource_name), html: { method: :put }) do |f| - = render 'devise/shared/error_messages', resource: resource = f.hidden_field :invitation_token, readonly: true - if f.object.class.require_password_on_accepting .form-group diff --git a/app/views/devise/invitations/new.haml b/app/views/devise/invitations/new.haml index 44ceec2e..4ebb8fa7 100644 --- a/app/views/devise/invitations/new.haml +++ b/app/views/devise/invitations/new.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center %h2= t 'devise.invitations.new.header' @@ -8,7 +10,6 @@ as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| - = render 'devise/shared/error_messages', resource: resource - resource.class.invite_key_fields.each do |field| .form-group = f.label field diff --git a/app/views/devise/passwords/edit.haml b/app/views/devise/passwords/edit.haml index 7f7b16fb..3a8843c0 100644 --- a/app/views/devise/passwords/edit.haml +++ b/app/views/devise/passwords/edit.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center .sr-only @@ -10,7 +12,6 @@ = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| - = render 'devise/shared/error_messages', resource: resource = f.hidden_field :reset_password_token diff --git a/app/views/devise/passwords/new.haml b/app/views/devise/passwords/new.haml index 3c80b8a0..08dd8d2e 100644 --- a/app/views/devise/passwords/new.haml +++ b/app/views/devise/passwords/new.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center .sr-only @@ -11,7 +13,6 @@ as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| - = render 'devise/shared/error_messages', resource: resource .form-group = f.label :email, class: 'sr-only' = f.email_field :email, autofocus: true, autocomplete: 'email', diff --git a/app/views/devise/registrations/edit.haml b/app/views/devise/registrations/edit.haml index 6a25da65..92699ab8 100644 --- a/app/views/devise/registrations/edit.haml +++ b/app/views/devise/registrations/edit.haml @@ -3,6 +3,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-6.align-self-center %h2= t('.title') @@ -11,8 +13,6 @@ url: registration_path(resource_name), html: { method: :put }) do |f| - = render 'devise/shared/error_messages', resource: resource - .form-group = f.label :email = f.email_field :email, autofocus: true, autocomplete: 'email', diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml index 21676556..e6bda964 100644 --- a/app/views/devise/registrations/new.haml +++ b/app/views/devise/registrations/new.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center %h2= t('.sign_up') @@ -10,8 +12,6 @@ as: resource_name, url: registration_path(resource_name, params: { locale: params[:locale] })) do |f| - = render 'devise/shared/error_messages', resource: resource - .form-group = f.label :email, class: 'sr-only' = f.email_field :email, autofocus: true, autocomplete: 'email', diff --git a/app/views/devise/shared/_error_messages.haml b/app/views/devise/shared/_error_messages.haml index a921fd61..0f0c1835 100644 --- a/app/views/devise/shared/_error_messages.haml +++ b/app/views/devise/shared/_error_messages.haml @@ -1,9 +1,8 @@ - if resource.errors.any? - #error_explanation - %h2 + = render 'bootstrap/alert' do + %h4.alert-heading = I18n.t("errors.messages.not_saved", | count: resource.errors.count, | resource: resource.class.model_name.human.downcase) | - %ul - - resource.errors.full_messages.each do |message| - %li= message + - resource.errors.full_messages.each do |message| + %p= message diff --git a/app/views/devise/unlocks/new.haml b/app/views/devise/unlocks/new.haml index ac511115..09468a52 100644 --- a/app/views/devise/unlocks/new.haml +++ b/app/views/devise/unlocks/new.haml @@ -1,6 +1,8 @@ = content_for :body do - 'black-bg' += render 'devise/shared/error_messages', resource: resource + .row.align-items-center.justify-content-center.full-height .col-md-5.align-self-center .sr-only @@ -11,7 +13,6 @@ as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| - = render 'devise/shared/error_messages', resource: resource .form-group = f.label :email, class: 'sr-only' = f.email_field :email, autofocus: true, autocomplete: 'email', From 944668edbe6c2fa51d0bdce2c8dcb22802760798 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:18:30 -0300 Subject: [PATCH 108/235] =?UTF-8?q?fix:=20mostrar=20siempre=20los=20links?= =?UTF-8?q?=20de=20recuperaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit por si se vencen, poder encontrarlos --- app/views/devise/shared/_links.haml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/views/devise/shared/_links.haml b/app/views/devise/shared/_links.haml index b4b89175..479eb457 100644 --- a/app/views/devise/shared/_links.haml +++ b/app/views/devise/shared/_links.haml @@ -18,17 +18,16 @@ new_password_path(resource_name, params: locale) %br/ -- if devise_mapping.confirmable? && controller_name != 'confirmations' +- if devise_mapping.confirmable? = link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name, params: locale) %br/ - if devise_mapping.lockable? - if resource_class.unlock_strategy_enabled?(:email) - - if controller_name != 'unlocks' - = link_to t('.didn_t_receive_unlock_instructions'), - new_unlock_path(resource_name, params: locale) - %br/ + = link_to t('.didn_t_receive_unlock_instructions'), + new_unlock_path(resource_name, params: locale) + %br/ - if devise_mapping.omniauthable? - resource_class.omniauth_providers.each do |provider| From 79f8241dec54f788910d2f8291b71468e1133f5c Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:18:55 -0300 Subject: [PATCH 109/235] fix: ser especificxs --- config/locales/devise.views.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index 33f7870b..027311c9 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -138,7 +138,7 @@ en: errors: messages: already_confirmed: was already confirmed, please try signing in - confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one using the \"Didn't receive confirmation instructions?\" link" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new confirmation link using the \"Didn't receive confirmation instructions?\" option below" expired: has expired, please request a new one not_found: not found not_locked: was not locked From 445bf26257333d6fb3f96e374721b14d02b88ac6 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 19:21:07 -0300 Subject: [PATCH 110/235] =?UTF-8?q?fix:=20hacer=20la=20caja=20m=C3=A1s=20l?= =?UTF-8?q?egible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/application.scss | 4 ++++ app/views/bootstrap/_alert.haml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index b756759a..72c7788d 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -25,6 +25,10 @@ $spacers: ( 2-plus: 0.75rem ); +$sizes: ( + "70ch": 70ch, +); + @import "bootstrap"; @import "editor"; diff --git a/app/views/bootstrap/_alert.haml b/app/views/bootstrap/_alert.haml index 0fb3d2d3..395f75d2 100644 --- a/app/views/bootstrap/_alert.haml +++ b/app/views/bootstrap/_alert.haml @@ -1,2 +1,2 @@ -.alert.alert-primary{ role: 'alert', class: local_assigns[:class] } +.alert.alert-primary.mx-auto.content.max-w-70ch{ role: 'alert', class: local_assigns[:class] } = yield From 6856b605176ea40b43e039eff1de69eecb9866b2 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 12:05:55 -0300 Subject: [PATCH 111/235] fixup! fix: usar siempre el componente --- app/views/posts/_form.haml | 2 +- app/views/posts/_submit.haml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/posts/_form.haml b/app/views/posts/_form.haml index f81cef58..7de0ea79 100644 --- a/app/views/posts/_form.haml +++ b/app/views/posts/_form.haml @@ -1,7 +1,7 @@ - unless post.errors.empty? - title = t('.errors.title') - help = t('.errors.help') - = render 'boostrap/alert' do + = render 'bootstrap/alert' do %h4= title %p= help diff --git a/app/views/posts/_submit.haml b/app/views/posts/_submit.haml index 717b8bfe..cad43320 100644 --- a/app/views/posts/_submit.haml +++ b/app/views/posts/_submit.haml @@ -1,6 +1,6 @@ .form-group = submit_tag t('.save'), class: 'btn submit-post' - = render 'boostrap/alert', class: 'invalid-help d-none' do + = render 'bootstrap/alert', class: 'invalid-help d-none' do = site.config.fetch('invalid_help', t('.invalid_help')) - = render 'boostrap/alert', class: 'sending-help d-none' do + = render 'bootstrap/alert', class: 'sending-help d-none' do = site.config.fetch('sending_help', t('.sending_help')) From 40dfa65bc2ae690b684e18478f5a0cde7857fc29 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 16:40:10 -0300 Subject: [PATCH 112/235] =?UTF-8?q?feat:=20anchos=20y=20altos=20m=C3=A1xim?= =?UTF-8?q?os=20y=20m=C3=ADnimos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/application.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 72c7788d..830769a7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -408,6 +408,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1); @each $prop, $abbrev in (width: w, height: h) { @each $size, $length in $sizes { .#{$abbrev}-#{$grid-breakpoint}-#{$size} { #{$prop}: $length !important; } + .min-#{$abbrev}#{$infix}-#{$size} { min-#{$prop}: $length !important; } + .max-#{$abbrev}#{$infix}-#{$size} { max-#{$prop}: $length !important; } } } From 951a04574528646272724f4263dd2d5db4fa496d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 16:43:11 -0300 Subject: [PATCH 113/235] =?UTF-8?q?fix:=20no=20mostrar=20un=20t=C3=ADtulo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/devise/shared/_error_messages.haml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/views/devise/shared/_error_messages.haml b/app/views/devise/shared/_error_messages.haml index 0f0c1835..64340e4f 100644 --- a/app/views/devise/shared/_error_messages.haml +++ b/app/views/devise/shared/_error_messages.haml @@ -1,8 +1,4 @@ - if resource.errors.any? = render 'bootstrap/alert' do - %h4.alert-heading - = I18n.t("errors.messages.not_saved", | - count: resource.errors.count, | - resource: resource.class.model_name.human.downcase) | - resource.errors.full_messages.each do |message| %p= message From 167aaf5549106394e15c448731ec938d13ea068d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 16:43:19 -0300 Subject: [PATCH 114/235] =?UTF-8?q?Revert=20"fix:=20mostrar=20siempre=20lo?= =?UTF-8?q?s=20links=20de=20recuperaci=C3=B3n"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 944668edbe6c2fa51d0bdce2c8dcb22802760798. --- app/views/devise/shared/_links.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/devise/shared/_links.haml b/app/views/devise/shared/_links.haml index 479eb457..b4b89175 100644 --- a/app/views/devise/shared/_links.haml +++ b/app/views/devise/shared/_links.haml @@ -18,16 +18,17 @@ new_password_path(resource_name, params: locale) %br/ -- if devise_mapping.confirmable? +- if devise_mapping.confirmable? && controller_name != 'confirmations' = link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name, params: locale) %br/ - if devise_mapping.lockable? - if resource_class.unlock_strategy_enabled?(:email) - = link_to t('.didn_t_receive_unlock_instructions'), - new_unlock_path(resource_name, params: locale) - %br/ + - if controller_name != 'unlocks' + = link_to t('.didn_t_receive_unlock_instructions'), + new_unlock_path(resource_name, params: locale) + %br/ - if devise_mapping.omniauthable? - resource_class.omniauth_providers.each do |provider| From 1f921d836f537994fbba18c4df302dea4a9455e5 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 20:18:52 -0300 Subject: [PATCH 115/235] =?UTF-8?q?fixup!=20feat:=20anchos=20y=20altos=20m?= =?UTF-8?q?=C3=A1ximos=20y=20m=C3=ADnimos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/application.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 830769a7..0e602ac0 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -408,8 +408,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1); @each $prop, $abbrev in (width: w, height: h) { @each $size, $length in $sizes { .#{$abbrev}-#{$grid-breakpoint}-#{$size} { #{$prop}: $length !important; } - .min-#{$abbrev}#{$infix}-#{$size} { min-#{$prop}: $length !important; } - .max-#{$abbrev}#{$infix}-#{$size} { max-#{$prop}: $length !important; } + .min-#{$abbrev}#{$grid-breakpoint}-#{$size} { min-#{$prop}: $length !important; } + .max-#{$abbrev}#{$grid-breakpoint}-#{$size} { max-#{$prop}: $length !important; } } } From ce26c15a505173e8a1579fcdc7578bd4312c74fe Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 20:34:54 -0300 Subject: [PATCH 116/235] fix: mejorar el texto --- config/locales/devise.views.en.yml | 2 +- config/locales/devise.views.es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index 027311c9..793f3a0a 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -138,7 +138,7 @@ en: errors: messages: already_confirmed: was already confirmed, please try signing in - confirmation_period_expired: "needs to be confirmed within %{period}, please request a new confirmation link using the \"Didn't receive confirmation instructions?\" option below" + confirmation_period_expired: "wasn't confirmed within %{period}. Please request a new confirmation link by using the \"Resend confirmation instructions\" button below and find it in your inbox." expired: has expired, please request a new one not_found: not found not_locked: was not locked diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index 63e3ae41..896bcdda 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -138,7 +138,7 @@ es: errors: messages: already_confirmed: ya ha sido confirmada, por favor intenta iniciar sesión - confirmation_period_expired: "necesita confirmarse dentro de %{period}, por favor solicita un nuevo código de confirmación usando la opción \"¿No has recibido las instrucciones de confirmación?\"" + confirmation_period_expired: "sin confirmar luego de %{period}. Por favor, usa el botón \"Reenviar instrucciones de confirmación\" y busca el nuevo link en tu casilla." expired: ha expirado, por favor solicita una nueva not_found: no se ha encontrado not_locked: no estaba bloqueada From a7b199941d5cb3f622712ef065516931792953d7 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 20:39:27 -0300 Subject: [PATCH 117/235] =?UTF-8?q?fixup!=20feat:=20anchos=20y=20altos=20m?= =?UTF-8?q?=C3=A1ximos=20y=20m=C3=ADnimos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/application.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 0e602ac0..2f52829b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -408,8 +408,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1); @each $prop, $abbrev in (width: w, height: h) { @each $size, $length in $sizes { .#{$abbrev}-#{$grid-breakpoint}-#{$size} { #{$prop}: $length !important; } - .min-#{$abbrev}#{$grid-breakpoint}-#{$size} { min-#{$prop}: $length !important; } - .max-#{$abbrev}#{$grid-breakpoint}-#{$size} { max-#{$prop}: $length !important; } + .min-#{$abbrev}-#{$grid-breakpoint}-#{$size} { min-#{$prop}: $length !important; } + .max-#{$abbrev}-#{$grid-breakpoint}-#{$size} { max-#{$prop}: $length !important; } } } From be902e33bc4fa7bac1581da3bc2a7f8b5924b66a Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 20:45:36 -0300 Subject: [PATCH 118/235] fix: demostrar otro sitio #10233 --- db/seeds/designs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds/designs.yml b/db/seeds/designs.yml index 126a9b12..b1508b84 100644 --- a/db/seeds/designs.yml +++ b/db/seeds/designs.yml @@ -23,7 +23,7 @@ - name_en: 'Sutty' name_es: 'Sutty' gem: 'sutty-jekyll-theme' - url: 'https://rubygems.org/gems/sutty-jekyll-theme/' + url: "https://anarres.sutty.nl" description_en: "The Sutty design" description_es: 'El diseño de Sutty' license: 'https://0xacab.org/sutty/jekyll/sutty-jekyll-theme/-/blob/master/LICENSE.txt' From 117b8502769b1b554878a219b32f15d4a4dfb13b Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 10:27:30 -0300 Subject: [PATCH 119/235] fix: hacer pull antes de push --- .woodpecker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index ab4887ac..887d397f 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -47,6 +47,7 @@ pipeline: - "dotenv RAILS_ENV=production bundle exec rails assets:precompile" - "dotenv RAILS_ENV=production bundle exec rails assets:clean" - "git add public && git commit -m \"ci: assets [skip ci]\"" + - "git pull upstream ${CI_COMMIT_BRANCH}" - "git push upstream ${CI_COMMIT_BRANCH}" secrets: - "SSH_KEY" From edd88d04b93aee72429c826ccdf3437a4b2aa0f2 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 11:29:23 -0300 Subject: [PATCH 120/235] =?UTF-8?q?feat:=20pre=20comprimir=20con=20brotli?= =?UTF-8?q?=20tambi=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .woodpecker.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 887d397f..19bd429b 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -28,7 +28,7 @@ pipeline: assets: image: "registry.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" commands: - - "apk add python2 dotenv openssh-client" + - "apk add python2 dotenv openssh-client brotli" - "install -d -m 700 ~/.ssh/" - "echo \"$${KNOWN_HOSTS}\" | base64 -d >> ~/.ssh/known_hosts" - "chmod 600 ~/.ssh/known_hosts" @@ -46,6 +46,7 @@ pipeline: - "dotenv RAILS_ENV=production bundle exec rails webpacker:clobber" - "dotenv RAILS_ENV=production bundle exec rails assets:precompile" - "dotenv RAILS_ENV=production bundle exec rails assets:clean" + - "find public -type f -print0 | xargs -r0 brotli -k9" - "git add public && git commit -m \"ci: assets [skip ci]\"" - "git pull upstream ${CI_COMMIT_BRANCH}" - "git push upstream ${CI_COMMIT_BRANCH}" From 661655abb5d03c2d2e21072de8230a05e324dc28 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 13:51:09 -0300 Subject: [PATCH 121/235] =?UTF-8?q?fix:=20hacer=20el=20deploy=20cuando=20e?= =?UTF-8?q?l=20sitio=20ya=20est=C3=A1=20guardado=20#12276?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/site_service.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 75577226..70824422 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -30,11 +30,10 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do site.reset.nil? && add_licencias && add_code_of_conduct && - add_privacy_policy + add_privacy_policy && + deploy end - deploy - site end From 16c3fa24132037b3ff973b97c97edcb7fbdc8b56 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 14:56:22 -0300 Subject: [PATCH 122/235] =?UTF-8?q?fix:=20ancho=20m=C3=A1ximo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/bootstrap/_alert.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/bootstrap/_alert.haml b/app/views/bootstrap/_alert.haml index 395f75d2..85bcbe84 100644 --- a/app/views/bootstrap/_alert.haml +++ b/app/views/bootstrap/_alert.haml @@ -1,2 +1,2 @@ -.alert.alert-primary.mx-auto.content.max-w-70ch{ role: 'alert', class: local_assigns[:class] } +.alert.alert-primary.mx-auto.content.max-w-md-70ch{ role: 'alert', class: local_assigns[:class] } = yield From aff16fdf779f674257e53f382aa18da71d828d81 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 16:50:45 -0300 Subject: [PATCH 123/235] fix: texto --- config/locales/devise.views.es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index 896bcdda..b745fc5f 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -138,7 +138,7 @@ es: errors: messages: already_confirmed: ya ha sido confirmada, por favor intenta iniciar sesión - confirmation_period_expired: "sin confirmar luego de %{period}. Por favor, usa el botón \"Reenviar instrucciones de confirmación\" y busca el nuevo link en tu casilla." + confirmation_period_expired: "quedó sin confirmar luego de %{period}. Por favor, usa el botón \"Reenviar instrucciones de confirmación\" y busca el nuevo link en tu casilla." expired: ha expirado, por favor solicita una nueva not_found: no se ha encontrado not_locked: no estaba bloqueada From 059230ad6b3249a9dc6c5717bd324102c373345c Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 19:33:04 -0300 Subject: [PATCH 124/235] fix: poder cambiar de idioma manteniendo los parametros #12886 --- app/views/layouts/_breadcrumb.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/_breadcrumb.haml b/app/views/layouts/_breadcrumb.haml index 099ddde4..b1c42cb2 100644 --- a/app/views/layouts/_breadcrumb.haml +++ b/app/views/layouts/_breadcrumb.haml @@ -23,6 +23,7 @@ = link_to t('.logout'), main_app.destroy_usuarie_session_path, method: :delete, role: 'button', class: 'btn' - else + - params.permit! - I18n.available_locales.each do |locale| - next if locale == I18n.locale - = link_to t(locale), "?change_locale_to=#{locale}" + = link_to t(locale), params.to_h.merge(change_locale_to: locale) From 0744e124e350b45a1981080de5981784811dcee7 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 10:56:09 -0300 Subject: [PATCH 125/235] fixup! fix: instalar las gemas cuando sea necesario #12755 --- app/models/site.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 6110f104..804de42c 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -575,11 +575,11 @@ class Site < ApplicationRecord # Detecta si el Gemfile fue modificado def gemfile_updated? - updated_at > File.mtime(File.join(path, 'Gemfile')) + updated_at < File.mtime(File.join(path, 'Gemfile')) end # Detecta si el Gemfile.lock fue modificado def gemfile_lock_updated? - updated_at > File.mtime(File.join(path, 'Gemfile.lock')) + updated_at < File.mtime(File.join(path, 'Gemfile.lock')) end end From 8c5535c5c7a1dc4af94b57ed0e948c0e191f0350 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 17:39:25 -0300 Subject: [PATCH 126/235] =?UTF-8?q?fix:=20ordenar=20layouts=20alfab=C3=A9t?= =?UTF-8?q?icamente=20#5085?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/posts/index.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index a82616d8..8a2a678d 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -5,7 +5,7 @@ %h3= t('posts.new') %table.mb-3 - - @site.layouts.each do |layout| + - @site.layouts.sort_by(&:humanized_name).each do |layout| - next if layout.hidden? %tr %th= layout.humanized_name From 59e97ef6856fb8617df3edaab6dcf7e2df5554e5 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 18:16:11 -0300 Subject: [PATCH 127/235] =?UTF-8?q?fix:=20forzar=20la=20compilaci=C3=B3n?= =?UTF-8?q?=20de=20brotli?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 19bd429b..1d760b52 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -46,7 +46,7 @@ pipeline: - "dotenv RAILS_ENV=production bundle exec rails webpacker:clobber" - "dotenv RAILS_ENV=production bundle exec rails assets:precompile" - "dotenv RAILS_ENV=production bundle exec rails assets:clean" - - "find public -type f -print0 | xargs -r0 brotli -k9" + - "find public -type f -print0 | xargs -r0 brotli -k9f" - "git add public && git commit -m \"ci: assets [skip ci]\"" - "git pull upstream ${CI_COMMIT_BRANCH}" - "git push upstream ${CI_COMMIT_BRANCH}" From 0d0c8c8b073598d9a74114d8ec65923c90ab7e32 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 19:31:22 -0300 Subject: [PATCH 128/235] =?UTF-8?q?fix:=20mostrar=20los=20dise=C3=B1os=20e?= =?UTF-8?q?n=20dos=20columnas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/sites/_form.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index 757b8b48..2d8ea4fb 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -53,10 +53,10 @@ = render 'bootstrap/alert' do = t('activerecord.errors.models.site.attributes.design_id.layout_incompatible.help', layouts: site.incompatible_layouts.to_sentence) - .row.designs + .row.row-cols-1.row-cols-md-2.designs -# Demasiado complejo para un f.collection_radio_buttons - Design.all.find_each do |design| - .design.col-md-4.d-flex.flex-column + .design.col.d-flex.flex-column .custom-control.custom-radio = f.radio_button :design_id, design.id, checked: design.id == site.design_id, From c2fafac7f0556c12015fb0bf8c102cc22c15723f Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 19:32:36 -0300 Subject: [PATCH 129/235] feat: informar el estado del sitio #10492 --- app/models/site.rb | 1 + app/models/site/build_stats.rb | 45 ++++++++++++++++++++++++++++++++++ app/views/posts/index.haml | 4 ++- app/views/sites/_status.haml | 19 ++++++++++++++ config/locales/en.yml | 4 +++ config/locales/es.yml | 4 +++ 6 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/models/site/build_stats.rb create mode 100644 app/views/sites/_status.haml diff --git a/app/models/site.rb b/app/models/site.rb index 4b2a8eb9..6aa96612 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -7,6 +7,7 @@ class Site < ApplicationRecord include Site::Forms include Site::FindAndReplace include Site::Api + include Site::BuildStats include Tienda # Cifrar la llave privada que cifra y decifra campos ocultos. Sutty diff --git a/app/models/site/build_stats.rb b/app/models/site/build_stats.rb new file mode 100644 index 00000000..8b23942d --- /dev/null +++ b/app/models/site/build_stats.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class Site + module BuildStats + extend ActiveSupport::Concern + + included do + # Devuelve el tiempo promedio de publicación para este sitio + # + # @return [Integer] + def average_publication_time + build_stats.group(:action).average(:seconds).values.reduce(:+).round + end + + # Devuelve el tiempo promedio de compilación para sitios similares + # a este. + # + # @return [Integer] + def average_publication_time_for_similar_sites + similar_deploys = Deploy.where(type: deploys.pluck(:type)).pluck(:id) + + BuildStat.where(deploy_id: similar_deploys).group(:action).average(:seconds).values.reduce(:+).round + end + + # Define si podemos calcular el tiempo promedio de publicación + # para este sitio + # + # @return [Boolean] + def average_publication_time_calculable? + build_stats.jekyll.where(status: true).count > 0 + end + + def similar_sites? + !design.no_theme? + end + + # Detecta si el sitio todavía no ha sido publicado + # + # @return [Boolean] + def not_published_yet? + build_stats.jekyll.where(status: true).count.zero? + end + end + end +end diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index dbeddaad..f7b884af 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -1,7 +1,9 @@ %main.row %aside.menu.col-md-3 - %h1= link_to @site.title, @site.url + %h1= @site.title %p.lead= @site.description + - cache_if @usuarie, [@site, I18n.locale] do + = render 'sites/status', site: @site %h3= t('posts.new') %table.mb-3 diff --git a/app/views/sites/_status.haml b/app/views/sites/_status.haml new file mode 100644 index 00000000..fb38896a --- /dev/null +++ b/app/views/sites/_status.haml @@ -0,0 +1,19 @@ +- link = nil +- if site.not_published_yet? + - message = t('.not_published_yet') +- if site.building? + - if site.average_publication_time_calculable? + - average_building_time = site.average_building_time + - elsif !site.similar_sites? + - average_building_time = 60 + - else + - average_building_time = site.average_publication_time_for_similar_sites + + - average_publication_time_human = distance_of_time_in_words average_building_time + - message = t('.building', average_time: average_publication_time_human, seconds: average_building_time) +- else + - message = t('.available') + - link = true + += render 'bootstrap/alert' do + = link_to_if link, message.html_safe, site.url diff --git a/config/locales/en.yml b/config/locales/en.yml index 567ab6bb..ee16f506 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -330,6 +330,10 @@ en: designer_url: 'Support the designer' static_file_migration: 'File migration' find_and_replace: 'Search and replace' + status: + building: "Your site is building, please wait ..." + not_published_yet: "Your site is being published for the first time, please wait up to 1 minute..." + available: "Your site is available! Click here to visit it." index: title: 'My Sites' pull: 'Upgrade' diff --git a/config/locales/es.yml b/config/locales/es.yml index 0a829e4a..e3d3f2ef 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -335,6 +335,10 @@ es: designer_url: 'Apoyá a le(s) diseñadore(s)' static_file_migration: 'Migración de archivos' find_and_replace: 'Búsqueda y reemplazo' + status: + building: "Tu sitio se está publicando, por favor espera ..." + not_published_yet: "Tu sitio se está publicando por primera vez, por favor espera hasta un minuto..." + available: "¡Tu sitio está disponible! Cliquea aquí para visitarlo." index: title: 'Mis sitios' pull: 'Actualizar' From 0442aa1e0672167a9502a5c5b7d14440bd7fdf88 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 19:37:47 -0300 Subject: [PATCH 130/235] fixup! feat: informar el estado del sitio #10492 --- app/views/sites/_status.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/sites/_status.haml b/app/views/sites/_status.haml index fb38896a..52afa3ca 100644 --- a/app/views/sites/_status.haml +++ b/app/views/sites/_status.haml @@ -3,7 +3,7 @@ - message = t('.not_published_yet') - if site.building? - if site.average_publication_time_calculable? - - average_building_time = site.average_building_time + - average_building_time = site.average_publication_time - elsif !site.similar_sites? - average_building_time = 60 - else From 8f19f837cdb11740cfe58d8be7fee4af30a70962 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 20:20:37 -0300 Subject: [PATCH 131/235] =?UTF-8?q?fix:=20hacer=20que=20devise=20respete?= =?UTF-8?q?=20el=20idioma=20de=20la=20sesi=C3=B3n=20#10478?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/devise/failure_app_decorator.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/lib/devise/failure_app_decorator.rb diff --git a/app/lib/devise/failure_app_decorator.rb b/app/lib/devise/failure_app_decorator.rb new file mode 100644 index 00000000..f17cb482 --- /dev/null +++ b/app/lib/devise/failure_app_decorator.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Devise + module FailureAppDecorator + extend ActiveSupport::Concern + + included do + include AbstractController::Callbacks + + around_action :set_locale + + private + + def set_locale(&action) + I18n.with_locale(session[:locale] || I18n.locale, &action) + end + end + end +end + +Devise::FailureApp.include Devise::FailureAppDecorator From f62d7fcc800fd5e6c5eeea9306ee60df49ae9943 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 20:51:20 -0300 Subject: [PATCH 132/235] =?UTF-8?q?fix:=20esperar=20a=20que=20la=20primera?= =?UTF-8?q?=20publicaci=C3=B3n=20termine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/site/build_stats.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/site/build_stats.rb b/app/models/site/build_stats.rb index 8b23942d..6eebcc84 100644 --- a/app/models/site/build_stats.rb +++ b/app/models/site/build_stats.rb @@ -27,7 +27,7 @@ class Site # # @return [Boolean] def average_publication_time_calculable? - build_stats.jekyll.where(status: true).count > 0 + build_stats.jekyll.where(status: true).count > 1 end def similar_sites? From 5ae3fe0b354a9649c8b079c2f5966b23cd7b7eef Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 20:52:35 -0300 Subject: [PATCH 133/235] =?UTF-8?q?fix:=20dar=20una=20acci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 2 +- config/locales/es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index ee16f506..f3e319ee 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -331,7 +331,7 @@ en: static_file_migration: 'File migration' find_and_replace: 'Search and replace' status: - building: "Your site is building, please wait ..." + building: "Your site is building, please wait to refresh this page..." not_published_yet: "Your site is being published for the first time, please wait up to 1 minute..." available: "Your site is available! Click here to visit it." index: diff --git a/config/locales/es.yml b/config/locales/es.yml index e3d3f2ef..98181fb3 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -336,7 +336,7 @@ es: static_file_migration: 'Migración de archivos' find_and_replace: 'Búsqueda y reemplazo' status: - building: "Tu sitio se está publicando, por favor espera ..." + building: "Tu sitio se está publicando, por favor espera para recargar esta página..." not_published_yet: "Tu sitio se está publicando por primera vez, por favor espera hasta un minuto..." available: "¡Tu sitio está disponible! Cliquea aquí para visitarlo." index: From ec47335f04ccc4b0a7424fcbe92ad65d7ce6c129 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 12:44:09 -0300 Subject: [PATCH 134/235] fix: es necesario el arbol actual para ignorar cambios en paralelo cuando estamos guardando un post con archivos subidos y posts relacionados, al no usar el arbol actual se pisaban los archivos modificados y el repositorio quedaba en un estado inconsistente. --- app/models/site/repository.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/models/site/repository.rb b/app/models/site/repository.rb index f63288d4..62e4c45e 100644 --- a/app/models/site/repository.rb +++ b/app/models/site/repository.rb @@ -117,6 +117,9 @@ class Site def commit(file:, usuarie:, message:, remove: false) file = [file] unless file.respond_to? :each + # Cargar el árbol actual + rugged.index.read_tree rugged.head.target.tree + file.each do |f| remove ? rm(f) : add(f) end From ad76fed1b19dac253f67b333be25b7cdd7ee01fa Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 13:31:32 -0300 Subject: [PATCH 135/235] fix: alert en modo oscuro --- app/assets/stylesheets/application.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 2f52829b..258698d3 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -52,6 +52,12 @@ $sizes: ( --background: #{$black}; --color: #{$cyan}; } + + .alert-primary { + @include alert-variant(theme-color-level($cyan, $alert-bg-level), + theme-color-level($cyan, $alert-border-level), + theme-color-level($cyan, $alert-color-level)); + } } // TODO: Encontrar la forma de generar esto desde los locales de Rails From bd21f3d9b4806b54b63b3ece2efa5a0d4acbbf5e Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 13:47:12 -0300 Subject: [PATCH 136/235] fixup! fix: alert en modo oscuro --- app/assets/stylesheets/application.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 258698d3..99b5a296 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -54,9 +54,9 @@ $sizes: ( } .alert-primary { - @include alert-variant(theme-color-level($cyan, $alert-bg-level), - theme-color-level($cyan, $alert-border-level), - theme-color-level($cyan, $alert-color-level)); + @include alert-variant(theme-color-level("cyan", $alert-bg-level), + theme-color-level("cyan", $alert-border-level), + theme-color-level("cyan", $alert-color-level)); } } From 191dbbd82344a8e7545c4c65e9d84838c435e27e Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 13:47:59 -0300 Subject: [PATCH 137/235] fix: indicar que hay un link --- app/views/sites/_status.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/sites/_status.haml b/app/views/sites/_status.haml index 52afa3ca..a731aa7d 100644 --- a/app/views/sites/_status.haml +++ b/app/views/sites/_status.haml @@ -16,4 +16,4 @@ - link = true = render 'bootstrap/alert' do - = link_to_if link, message.html_safe, site.url + = link_to_if link, message.html_safe, site.url, class: 'alert-link' From 3dacef76f1cafb9ecb64cb527737ba34452e9536 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 13:55:21 -0300 Subject: [PATCH 138/235] fix: esto no funciona --- app/assets/stylesheets/application.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 99b5a296..2f52829b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -52,12 +52,6 @@ $sizes: ( --background: #{$black}; --color: #{$cyan}; } - - .alert-primary { - @include alert-variant(theme-color-level("cyan", $alert-bg-level), - theme-color-level("cyan", $alert-border-level), - theme-color-level("cyan", $alert-color-level)); - } } // TODO: Encontrar la forma de generar esto desde los locales de Rails From b7a27a87dd2879622f89d4102f4a4346aa7c17ac Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 16:58:22 -0300 Subject: [PATCH 139/235] feat: cuando se modifica la licencia, considerarla personalizada --- app/models/licencia.rb | 4 ++++ app/services/post_service.rb | 12 ++++++++++++ app/views/sites/_form.haml | 1 + db/seeds/licencias.yml | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/app/models/licencia.rb b/app/models/licencia.rb index f0a542ef..351a8ae5 100644 --- a/app/models/licencia.rb +++ b/app/models/licencia.rb @@ -17,4 +17,8 @@ class Licencia < ApplicationRecord validates :description, presence: true validates :short_description, presence: true validates :deed, presence: true + + def custom? + url == 'custom' + end end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 81ebe4a1..f1b9f7c3 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -18,6 +18,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do commit(action: :created, file: update_related_posts) if post.update(post_params) + update_site_license! + # Devolver el post aunque no se haya salvado para poder rescatar los # errores post @@ -44,6 +46,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # relacionados. commit(action: :updated, file: update_related_posts) if post.update(post_params) + update_site_license! + # Devolver el post aunque no se haya salvado para poder rescatar los # errores post @@ -137,4 +141,12 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do p.path.absolute if p.save(validate: false) end.compact << post.path.absolute end + + # Si les usuaries modifican o crean una licencia, considerarla + # personalizada en el panel. + def update_site_license! + if site.usuarie?(usuarie) && post.layout.name == :license + site.update licencia: Licencia.find_by_url('custom') + end + end end diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index 9a044c7f..10f158c8 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -79,6 +79,7 @@ %h2= t('.licencia.title') %p.lead= t('.help.licencia') - Licencia.all.find_each do |licencia| + - next if licencia.custom? && site.licencia != licencia .row.license .col .media.mt-1 diff --git a/db/seeds/licencias.yml b/db/seeds/licencias.yml index c5e2886a..402e5d8b 100644 --- a/db/seeds/licencias.yml +++ b/db/seeds/licencias.yml @@ -1,4 +1,10 @@ --- +- name_en: "Custom license" + name_es: "Licencia personalizada" + url_en: "custom" + url_es: "custom" + description_en: "The license terms are provided by you." + description_es: "Los términos de la licencia fueron provistos por vos." - name_en: 'Peer Production License' name_es: 'Licencia de Producción de Pares' short_description_en: "This work is licensed under a Peer Production License" From 94d30ac12aebac141992747613f888b573f5f43f Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 17:50:04 -0300 Subject: [PATCH 140/235] fixup! feat: cuando se modifica la licencia, considerarla personalizada --- app/models/licencia.rb | 2 +- app/services/post_service.rb | 4 ++-- app/services/site_service.rb | 2 ++ app/views/sites/_form.haml | 7 ++++--- db/seeds/licencias.yml | 9 +++++++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/models/licencia.rb b/app/models/licencia.rb index 351a8ae5..65009f46 100644 --- a/app/models/licencia.rb +++ b/app/models/licencia.rb @@ -19,6 +19,6 @@ class Licencia < ApplicationRecord validates :deed, presence: true def custom? - url == 'custom' + icons == 'custom' end end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index f1b9f7c3..7b31867d 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -145,8 +145,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # Si les usuaries modifican o crean una licencia, considerarla # personalizada en el panel. def update_site_license! - if site.usuarie?(usuarie) && post.layout.name == :license - site.update licencia: Licencia.find_by_url('custom') + if site.usuarie?(usuarie) && post.layout.name == :license && !site.licencia.custom? + site.update licencia: Licencia.find_by_icons('custom') end end end diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 70824422..5e1d5055 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -110,6 +110,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # @return [Boolean] def add_licencias return true unless site.layout? :license + return true if site.licencia.custom? with_all_locales do |locale| add_licencia lang: locale @@ -140,6 +141,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # @return [Boolean] def change_licencias return true unless site.layout? :license + return true if site.licencia.custom? with_all_locales do |locale| post = site.posts(lang: locale).find_by(layout: 'license') diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index 10f158c8..137a40b0 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -83,7 +83,8 @@ .row.license .col .media.mt-1 - = image_tag licencia.icons, alt: licencia.name, class: 'mr-3 mt-4' + - unless licencia.custom? + = image_tag licencia.icons, alt: licencia.name, class: 'mr-3 mt-4' .media-body .custom-control.custom-radio = f.radio_button :licencia_id, licencia.id, @@ -94,8 +95,8 @@ = sanitize_markdown licencia.description, tags: %w[p a strong em ul ol li h1 h2 h3 h4 h5 h6] - = link_to t('.licencia.url'), licencia.url, - target: '_blank', class: 'btn' + - unless licencia.custom? + = link_to t('.licencia.url'), licencia.url, target: '_blank', class: 'btn', rel: 'noopener' %hr/ diff --git a/db/seeds/licencias.yml b/db/seeds/licencias.yml index 402e5d8b..f6b76296 100644 --- a/db/seeds/licencias.yml +++ b/db/seeds/licencias.yml @@ -1,10 +1,15 @@ --- - name_en: "Custom license" name_es: "Licencia personalizada" - url_en: "custom" - url_es: "custom" + url_en: "" + url_es: "" + icons: "custom" + short_description_en: "" + short_description_es: "" description_en: "The license terms are provided by you." description_es: "Los términos de la licencia fueron provistos por vos." + deed_en: "" + deed_es: "" - name_en: 'Peer Production License' name_es: 'Licencia de Producción de Pares' short_description_en: "This work is licensed under a Peer Production License" From ea71aafe58c233234bcdf1c00df7fac5df2b1cea Mon Sep 17 00:00:00 2001 From: f Date: Tue, 4 Apr 2023 11:33:51 -0300 Subject: [PATCH 141/235] fix: enviar los correos de devise en el idioma de le usuarie #12952 --- app/models/usuarie.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/usuarie.rb b/app/models/usuarie.rb index c87d82f9..7b83ee75 100644 --- a/app/models/usuarie.rb +++ b/app/models/usuarie.rb @@ -41,6 +41,12 @@ class Usuarie < ApplicationRecord lock_access! if attempts_exceeded? && !access_locked? end + def send_devise_notification(notification, *args) + I18n.with_locale(lang) do + devise_mailer.send(notification, self, *args).deliver_later + end + end + private def lang_from_locale! From 38d6f6d842ebcb6715aa02427a8875e9c9fd2b3b Mon Sep 17 00:00:00 2001 From: f Date: Tue, 4 Apr 2023 13:21:38 -0300 Subject: [PATCH 142/235] =?UTF-8?q?fix:=20mantener=20la=20notificaci=C3=B3?= =?UTF-8?q?n=20hasta=20que=20se=20confirme=20el=20correo=20#12950?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e80c279d..0628421f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base before_action :prepare_exception_notifier before_action :configure_permitted_parameters, if: :devise_controller? + before_action :notify_unconfirmed_email, unless: :devise_controller? around_action :set_locale rescue_from Pundit::NilPolicyError, with: :page_not_found @@ -27,6 +28,13 @@ class ApplicationController < ActionController::Base private + def notify_unconfirmed_email + return unless current_usuarie + return if current_usuarie.confirmed? + + flash[:notice] ||= I18n.t('devise.registrations.signed_up') + end + def uuid?(string) /[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/ =~ string end From 8d31170086d3fa51c946c244fff4814f72b9075f Mon Sep 17 00:00:00 2001 From: f Date: Tue, 4 Apr 2023 13:34:19 -0300 Subject: [PATCH 143/235] fix: usar el idioma de le usuarie --- app/controllers/application_controller.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0628421f..b4be5a97 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -32,7 +32,9 @@ class ApplicationController < ActionController::Base return unless current_usuarie return if current_usuarie.confirmed? - flash[:notice] ||= I18n.t('devise.registrations.signed_up') + I18n.with_locale(current_usuarie.lang) do + flash[:notice] ||= I18n.t('devise.registrations.signed_up') + end end def uuid?(string) @@ -92,6 +94,7 @@ class ApplicationController < ActionController::Base protected def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: Usuarie::CONSENT_FIELDS) devise_parameter_sanitizer.permit(:account_update, keys: %i[lang]) end From 29be4b26b034ee7e2a78413e9c8dbd6278266fc8 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 5 Apr 2023 19:30:44 -0300 Subject: [PATCH 144/235] fix: no producir un error al no haber locales --- app/models/metadata_locales.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 3790b944..37b50286 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -44,6 +44,6 @@ class MetadataLocales < MetadataHasAndBelongsToMany def posts other_locales.map do |locale| site.posts(lang: locale).where(layout: post.layout.value) - end.reduce(&:concat) || PostRelation.new + end.reduce(&:concat) || PostRelation.new(site: site, lang: 'any') end end From 6bc013c8593bdb9d184fadcd6f091ab1e2d4d8eb Mon Sep 17 00:00:00 2001 From: f Date: Wed, 5 Apr 2023 19:30:59 -0300 Subject: [PATCH 145/235] fix: no mostrar el campo si no hay locales --- app/views/posts/attribute_ro/_locales.haml | 19 +++++++------- app/views/posts/attributes/_locales.haml | 29 +++++++++++----------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/app/views/posts/attribute_ro/_locales.haml b/app/views/posts/attribute_ro/_locales.haml index 3ac22933..16ecb532 100644 --- a/app/views/posts/attribute_ro/_locales.haml +++ b/app/views/posts/attribute_ro/_locales.haml @@ -1,9 +1,10 @@ -%tr{ id: attribute } - %th= post_label_t(attribute, post: post) - %td - %ul - - metadata.value.each do |uuid| - - p = site.docs.find(uuid, uuid: true) - %li{ dir: t("locales.#{p.lang.value}.dir"), lang: p.lang.value } - = link_to p.title.value, - site_post_path(site, p.id, locale: p.lang.value) +- if site.locales.count > 1 + %tr{ id: attribute } + %th= post_label_t(attribute, post: post) + %td + %ul + - metadata.value.each do |uuid| + - p = site.docs.find(uuid, uuid: true) + %li{ dir: t("locales.#{p.lang.value}.dir"), lang: p.lang.value } + = link_to p.title.value, + site_post_path(site, p.id, locale: p.lang.value) diff --git a/app/views/posts/attributes/_locales.haml b/app/views/posts/attributes/_locales.haml index 23f66700..4978f6b4 100644 --- a/app/views/posts/attributes/_locales.haml +++ b/app/views/posts/attributes/_locales.haml @@ -1,18 +1,19 @@ -%fieldset - %legend= post_label_t(attribute, post: post) +- if site.locales.count > 1 + %fieldset + %legend= post_label_t(attribute, post: post) - = render 'posts/attribute_feedback', - post: post, attribute: attribute, metadata: metadata + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata - - site.locales.each do |locale| - - next if post.lang.value == locale - - locale_t = t("locales.#{locale}.name", default: locale.to_s.humanize) - - value = metadata.value.find do |v| - - metadata.values[locale].values.include? v + - site.locales.each do |locale| + - next if post.lang.value == locale + - locale_t = t("locales.#{locale}.name", default: locale.to_s.humanize) + - value = metadata.value.find do |v| + - metadata.values[locale].values.include? v - .form-group - = label_tag "#{base}_#{attribute}_#{locale}", locale_t + .form-group + = label_tag "#{base}_#{attribute}_#{locale}", locale_t - = select_tag("#{plain_field_name_for(base, attribute)}[]", - options_for_select(metadata.values[locale], value), - **field_options(attribute, metadata), include_blank: t('.empty')) + = select_tag("#{plain_field_name_for(base, attribute)}[]", + options_for_select(metadata.values[locale], value), + **field_options(attribute, metadata), include_blank: t('.empty')) From dd3ef04fc4b759d818ac9ef16db88e59761889ab Mon Sep 17 00:00:00 2001 From: f Date: Thu, 6 Apr 2023 11:19:33 -0300 Subject: [PATCH 146/235] =?UTF-8?q?feat:=20generar=20im=C3=A1genes=20p?= =?UTF-8?q?=C3=BAblicas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .woodpecker.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 1d760b52..2e775624 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,10 +1,10 @@ pipeline: publish: - image: "plugins/docker" + image: "docker.io/woodpeckerci/plugin-docker-buildx" settings: - registry: "registry.nulo.in" + registry: "gitea.nulo.in" username: "sutty" - repo: "registry.nulo.in/sutty/panel" + repo: "gitea.nulo.in/sutty/panel" tags: - "${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" - "latest" @@ -12,10 +12,10 @@ pipeline: - "RUBY_VERSION=${RUBY_VERSION}" - "RUBY_PATCH=${RUBY_PATCH}" - "ALPINE_VERSION=${ALPINE_VERSION}" - - "BASE_IMAGE=registry.nulo.in/sutty/rails" + - "BASE_IMAGE=gitea.nulo.in/sutty/rails" purge: false secrets: - - "docker_password" + - "DOCKER_PASSWORD" when: branch: - "rails" @@ -26,7 +26,7 @@ pipeline: - "Dockerfile" - ".dockerignore" assets: - image: "registry.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" + image: "gitea.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}" commands: - "apk add python2 dotenv openssh-client brotli" - "install -d -m 700 ~/.ssh/" @@ -66,6 +66,6 @@ pipeline: - "yarn.lock" matrix: include: - - ALPINE_VERSION: "3.14.8" + - ALPINE_VERSION: "3.14.10" RUBY_VERSION: "2.7" - RUBY_PATCH: "6" + RUBY_PATCH: "8" From 34d26a0174b0644d96e430b3bf894c734d366dce Mon Sep 17 00:00:00 2001 From: f Date: Thu, 6 Apr 2023 11:27:28 -0300 Subject: [PATCH 147/235] fix: instalar pnpm 7 porque 8 es incompatible con node 14 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a6420a35..3da9ffab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 \ RUN gem install --no-document --no-user-install foreman RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz -O - | tar --strip-components 1 -xvzf - pandoc-${PANDOC_VERSION}/bin/pandoc && mv /bin/pandoc /usr/bin/pandoc -RUN apk add npm && npm install -g pnpm && apk del npm +RUN apk add npm && npm install -g pnpm@~7 && apk del npm COPY ./monit.conf /etc/monit.d/sutty.conf From 6cab61891c9c1fd0fb7c3a260febc816d40178ea Mon Sep 17 00:00:00 2001 From: f Date: Thu, 6 Apr 2023 20:30:47 -0300 Subject: [PATCH 148/235] fix: la tarea estaba mal nombrada --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 950168dd..25a1639d 100644 --- a/Procfile +++ b/Procfile @@ -5,6 +5,6 @@ blazer_1h: bundle exec rake blazer:run_checks SCHEDULE="1 hour" blazer_1d: bundle exec rake blazer:run_checks SCHEDULE="1 day" blazer: bundle exec rake blazer:send_failing_checks prometheus: bundle exec prometheus_exporter -b 0.0.0.0 --prefix "sutty_" -distributed_press_renew_tokens: bundle exec rake distributed_press:tokens:renew +distributed_press_tokens_renew: bundle exec rake distributed_press:tokens:renew cleanup: bundle exec rake cleanup:everything stats: bundle exec rake stats:process_all From 4f8ea0d9a726b860edce4227939e7005c6b1107e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 18:38:47 -0300 Subject: [PATCH 149/235] feat: los deploys son interdependientes --- app/models/deploy.rb | 7 +++---- app/models/deploy_alternative_domain.rb | 2 ++ app/models/deploy_rsync.rb | 8 ++++++++ app/models/deploy_www.rb | 2 ++ app/models/deploy_zip.rb | 2 ++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 9d5c1d27..942336ad 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'open3' + # Este modelo implementa los distintos tipos de alojamiento que provee # Sutty. # @@ -11,11 +12,9 @@ class Deploy < ApplicationRecord belongs_to :site has_many :build_stats, dependent: :destroy - def deploy(**) - raise NotImplementedError - end + DEPENDENCIES = [] - def url + def deploy(**) raise NotImplementedError end diff --git a/app/models/deploy_alternative_domain.rb b/app/models/deploy_alternative_domain.rb index 5ad381d5..114f2aa5 100644 --- a/app/models/deploy_alternative_domain.rb +++ b/app/models/deploy_alternative_domain.rb @@ -4,6 +4,8 @@ class DeployAlternativeDomain < Deploy store :values, accessors: %i[hostname], coder: JSON + DEPENDENCIES = %i[local] + # Generar un link simbólico del sitio principal al alternativo def deploy(**) File.symlink?(destination) || diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index a658de6b..9ced0bb1 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -5,6 +5,14 @@ class DeployRsync < Deploy store :values, accessors: %i[destination host_keys], coder: JSON + DEPENDENCIES = %i[ + alternative_domain + hidden_service + local + www + zip + ] + def deploy(output: false) ssh? && rsync(output: output) end diff --git a/app/models/deploy_www.rb b/app/models/deploy_www.rb index dff769a6..e6cfe407 100644 --- a/app/models/deploy_www.rb +++ b/app/models/deploy_www.rb @@ -4,6 +4,8 @@ class DeployWww < Deploy store :values, accessors: %i[], coder: JSON + DEPENDENCIES = %i[local] + before_destroy :remove_destination! def deploy(**) diff --git a/app/models/deploy_zip.rb b/app/models/deploy_zip.rb index f1c94083..2f9ac173 100644 --- a/app/models/deploy_zip.rb +++ b/app/models/deploy_zip.rb @@ -8,6 +8,8 @@ require 'zip' class DeployZip < Deploy store :values, accessors: %i[], coder: JSON + DEPENDENCIES = %i[local] + # Una vez que el sitio está generado, tomar todos los archivos y # y generar un zip accesible públicamente. # From db25750ab0580f92d93e5194e4ba7d14ca883ddf Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 18:54:38 -0300 Subject: [PATCH 150/235] feat: usar un grafo dirigido para ordenar las dependencias #10464 --- Gemfile | 1 + Gemfile.lock | 7 ++++++ app/models/site/deploy_dependencies.rb | 30 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 app/models/site/deploy_dependencies.rb diff --git a/Gemfile b/Gemfile index f3799638..489097a6 100644 --- a/Gemfile +++ b/Gemfile @@ -23,6 +23,7 @@ if ENV['RAILS_GROUPS']&.split(',')&.include? 'assets' end gem 'nokogiri' +gem 'rgl' # Turbolinks makes navigating your web application faster. Read more: # https://github.com/turbolinks/turbolinks diff --git a/Gemfile.lock b/Gemfile.lock index abaf45c9..5df84963 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -353,6 +353,7 @@ GEM mini_portile2 (~> 2.6.1) racc (~> 1.4) orm_adapter (0.5.0) + pairing_heap (3.0.0) parallel (1.21.0) parser (3.0.2.0) ast (~> 2.4.1) @@ -443,6 +444,10 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.5) + rgl (0.6.2) + pairing_heap (>= 0.3.0) + rexml (~> 3.2, >= 3.2.4) + stream (~> 0.5.3) rouge (3.26.1) rubocop (1.23.0) parallel (~> 1.10) @@ -510,6 +515,7 @@ GEM sprockets (>= 3.0.0) sqlite3 (1.4.2-x86_64-linux-musl) stackprof (0.2.17-x86_64-linux-musl) + stream (0.5.5) sucker_punch (3.0.1) concurrent-ruby (~> 1.0) sutty-archives (2.5.4) @@ -626,6 +632,7 @@ DEPENDENCIES rails_warden redis redis-rails + rgl rollups! rubocop-rails rubyzip diff --git a/app/models/site/deploy_dependencies.rb b/app/models/site/deploy_dependencies.rb new file mode 100644 index 00000000..33ed9e37 --- /dev/null +++ b/app/models/site/deploy_dependencies.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'rgl/adjacency' + +class Site + module DeployDependencies + extend ActiveSupport::Concern + + included do + # Genera un grafo dirigido de todos los métodos de publicación + # + # @return [RGL::DirectedAdjacencyGraph] + def deployment_graph + @deployment_graph ||= RGL::DirectedAdjacencyGraph.new.tap do |graph| + deploys.each do |deploy| + graph.add_vertex deploy + end + + deploys.each do |deploy| + deploy.class::DEPENDENCIES.each do |dependency| + deploys.where(type: "Deploy#{dependency.to_s.classify}").each do |deploy_dependency| + graph.add_edge deploy_dependency, deploy + end + end + end + end + end + end + end +end From 0ed01a61f7e85c8ac2580ccf4bb526edb905262c Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 21:37:58 -0300 Subject: [PATCH 151/235] feat: devolver una lista ordenada de metodos de publicacion --- app/models/site/deploy_dependencies.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/models/site/deploy_dependencies.rb b/app/models/site/deploy_dependencies.rb index 33ed9e37..05939320 100644 --- a/app/models/site/deploy_dependencies.rb +++ b/app/models/site/deploy_dependencies.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'rgl/adjacency' +require 'rgl/topsort' class Site module DeployDependencies @@ -25,6 +26,13 @@ class Site end end end + + # Devuelve una lista ordenada de todos los métodos de publicación + # + # @return [Array] + def deployment_list + @deployment_list ||= deployment_graph.topsort_iterator.to_a + end end end end From 607f19f6805512383358b80eea64197d5a20aafe Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 21:38:31 -0300 Subject: [PATCH 152/235] feat: activar ordenamiento de metodos de publicacion --- app/models/site.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/site.rb b/app/models/site.rb index 4b2a8eb9..f88e2e97 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -7,6 +7,7 @@ class Site < ApplicationRecord include Site::Forms include Site::FindAndReplace include Site::Api + include Site::DeployDependencies include Tienda # Cifrar la llave privada que cifra y decifra campos ocultos. Sutty From e5f96c435d8efec81f1a3cee4f5f657c3a32d7d3 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 13:42:47 -0300 Subject: [PATCH 153/235] feat: generar el sitio en orden #10464 --- app/jobs/deploy_job.rb | 86 +++++++++++-------------- app/models/deploy_alternative_domain.rb | 2 +- app/models/deploy_rsync.rb | 10 +-- app/models/deploy_www.rb | 2 +- app/models/deploy_zip.rb | 2 +- app/models/site/deploy_dependencies.rb | 2 +- 6 files changed, 48 insertions(+), 56 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index e018533c..f7d07349 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -30,28 +30,30 @@ class DeployJob < ApplicationJob return end + @deployed = {} @site.update status: 'building' - # Asegurarse que DeployLocal sea el primero! - @deployed = { - deploy_local: { - status: deploy_locally, - seconds: deploy_local.build_stats.last.seconds, - size: deploy_local.size, - urls: [deploy_local.url] + @site.deployment_list.each do |d| + begin + raise DeployException, 'Una dependencia falló' if failed_dependencies? d + + status = d.deploy + seconds = d.build_stats.last.try(:seconds) + rescue StandardError => e + status = false + seconds = 0 + + notify_exception e, d + end + + @deployed[d.type.underscore.to_sym] = { + status: status, + seconds: seconds || 0, + size: d.size, + urls: d.respond_to?(:urls) ? d.urls : [d.url].compact } - } - - # No es opcional - unless @deployed[:deploy_local][:status] - # Hacer fallar la tarea - raise DeployException, "#{@site.name}: Falló la compilación" end - - deploy_others rescue DeployTimedOutException => e notify_exception e - rescue DeployException => e - notify_exception e, deploy_local ensure @site&.update status: 'waiting' @@ -62,47 +64,37 @@ class DeployJob < ApplicationJob private + # Detecta si un método de publicación tiene dependencias fallidas + # + # @param :deploy [Deploy] + # @return [Boolean] + def failed_dependencies?(deploy) + failed_dependencies(deploy).present? + end + + # Obtiene las dependencias fallidas de un deploy + # + # @param :deploy [Deploy] + # @return [Array] + def failed_dependencies(deploy) + deploy.class::DEPENDENCIES & (@deployed.reject do |_, v| + v[:status] + end.keys) + end + # @param :exception [StandardError] # @param :deploy [Deploy] def notify_exception(exception, deploy = nil) data = { site: @site.id, deploy: deploy&.type, - log: deploy&.build_stats&.last&.log + log: deploy&.build_stats&.last&.log, + failed_dependencies: (failed_dependencies(deploy) if deploy) } ExceptionNotifier.notify_exception(exception, data: data) end - def deploy_local - @deploy_local ||= @site.deploys.find_by(type: 'DeployLocal') - end - - def deploy_locally - deploy_local.deploy(output: @output) - end - - def deploy_others - @site.deploys.where.not(type: 'DeployLocal').find_each do |d| - begin - status = d.deploy(output: @output) - seconds = d.build_stats.last.try(:seconds) - rescue StandardError => e - status = false - seconds = 0 - - notify_exception e, d - end - - @deployed[d.type.underscore.to_sym] = { - status: status, - seconds: seconds || 0, - size: d.size, - urls: d.respond_to?(:urls) ? d.urls : [d.url].compact - } - end - end - def notify_usuaries @site.roles.where(rol: 'usuarie', temporal: false).pluck(:usuarie_id).each do |usuarie| DeployMailer.with(usuarie: usuarie, site: @site.id) diff --git a/app/models/deploy_alternative_domain.rb b/app/models/deploy_alternative_domain.rb index 114f2aa5..9b1d63d7 100644 --- a/app/models/deploy_alternative_domain.rb +++ b/app/models/deploy_alternative_domain.rb @@ -4,7 +4,7 @@ class DeployAlternativeDomain < Deploy store :values, accessors: %i[hostname], coder: JSON - DEPENDENCIES = %i[local] + DEPENDENCIES = %i[deploy_local] # Generar un link simbólico del sitio principal al alternativo def deploy(**) diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index 9ced0bb1..dd7a492b 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -6,11 +6,11 @@ class DeployRsync < Deploy store :values, accessors: %i[destination host_keys], coder: JSON DEPENDENCIES = %i[ - alternative_domain - hidden_service - local - www - zip + deploy_alternative_domain + deploy_hidden_service + deploy_local + deploy_www + deploy_zip ] def deploy(output: false) diff --git a/app/models/deploy_www.rb b/app/models/deploy_www.rb index e6cfe407..d27f77cc 100644 --- a/app/models/deploy_www.rb +++ b/app/models/deploy_www.rb @@ -4,7 +4,7 @@ class DeployWww < Deploy store :values, accessors: %i[], coder: JSON - DEPENDENCIES = %i[local] + DEPENDENCIES = %i[deploy_local] before_destroy :remove_destination! diff --git a/app/models/deploy_zip.rb b/app/models/deploy_zip.rb index 2f9ac173..bba13686 100644 --- a/app/models/deploy_zip.rb +++ b/app/models/deploy_zip.rb @@ -8,7 +8,7 @@ require 'zip' class DeployZip < Deploy store :values, accessors: %i[], coder: JSON - DEPENDENCIES = %i[local] + DEPENDENCIES = %i[deploy_local] # Una vez que el sitio está generado, tomar todos los archivos y # y generar un zip accesible públicamente. diff --git a/app/models/site/deploy_dependencies.rb b/app/models/site/deploy_dependencies.rb index 05939320..a01f99e7 100644 --- a/app/models/site/deploy_dependencies.rb +++ b/app/models/site/deploy_dependencies.rb @@ -19,7 +19,7 @@ class Site deploys.each do |deploy| deploy.class::DEPENDENCIES.each do |dependency| - deploys.where(type: "Deploy#{dependency.to_s.classify}").each do |deploy_dependency| + deploys.where(type: dependency.to_s.classify).each do |deploy_dependency| graph.add_edge deploy_dependency, deploy end end From 3de6f14e63a7922e6670b45a87d4e079830e7244 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 13:47:34 -0300 Subject: [PATCH 154/235] =?UTF-8?q?fix:=20no=20pedir=20el=20tama=C3=B1o=20?= =?UTF-8?q?si=20fall=C3=B3=20la=20compilaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/deploy_job.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index f7d07349..fe344454 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -38,9 +38,11 @@ class DeployJob < ApplicationJob status = d.deploy seconds = d.build_stats.last.try(:seconds) + size = d.size rescue StandardError => e status = false seconds = 0 + size = 0 notify_exception e, d end @@ -48,7 +50,7 @@ class DeployJob < ApplicationJob @deployed[d.type.underscore.to_sym] = { status: status, seconds: seconds || 0, - size: d.size, + size: size, urls: d.respond_to?(:urls) ? d.urls : [d.url].compact } end From ea1ac09f9698be5cc615a4471a3d77b1bdbe9ca2 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 13:54:19 -0300 Subject: [PATCH 155/235] =?UTF-8?q?fix:=20mejorar=20gesti=C3=B3n=20de=20zi?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_zip.rb | 53 +++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/app/models/deploy_zip.rb b/app/models/deploy_zip.rb index bba13686..5f72a728 100644 --- a/app/models/deploy_zip.rb +++ b/app/models/deploy_zip.rb @@ -14,24 +14,43 @@ class DeployZip < Deploy # y generar un zip accesible públicamente. # # rubocop:disable Metrics/MethodLength - def deploy(**) + def deploy(output: false) FileUtils.rm_f path - time_start - Dir.chdir(destination) do - Zip::File.open(path, Zip::File::CREATE) do |z| - Dir.glob('./**/**').each do |f| - File.directory?(f) ? z.mkdir(f) : z.add(f, f) + Zip::File.open(path, Zip::File::CREATE) do |zip| + Dir.glob(File.join(destination, '**', '**')).each do |file| + entry = Pathname.new(file).relative_path_from(destination).to_s + + if File.directory? file + log "Creando directorio #{entry}", output + + zip.mkdir(entry) + else + log "Comprimiendo #{entry}", output + zip.add(entry, file) end end end + time_stop - build_stats.create action: 'zip', - seconds: time_spent_in_seconds, - bytes: size + File.exist?(path).tap do |status| + build_stats.create action: 'zip', + seconds: time_spent_in_seconds, + bytes: size, + log: @log.join("\n"), + status: status + end + rescue Zip::Error => e + ExceptionNotifier.notify_exception(e, data: { site: site.name }) - File.exist? path + build_stats.create action: 'zip', + seconds: 0, + bytes: 0, + log: @log.join("\n"), + status: false + + false end # rubocop:enable Metrics/MethodLength @@ -43,8 +62,9 @@ class DeployZip < Deploy File.size path end + # @return [String] def destination - File.join(Rails.root, '_deploy', site.hostname) + Rails.root.join('_deploy', site.hostname).realpath.to_s end def file @@ -58,4 +78,15 @@ class DeployZip < Deploy def path File.join(destination, file) end + + private + + # @param :line [String] + # @param :output [Boolean] + def log(line, output) + @log ||= [] + @log << line + + puts line if output + end end From 199199117da9c70b666d851ebff29ea59f5c7ec0 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 16 Mar 2022 18:19:04 -0300 Subject: [PATCH 156/235] implementar la misma api en todos los deploys --- app/models/deploy.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 942336ad..7aedbb19 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -18,6 +18,10 @@ class Deploy < ApplicationRecord raise NotImplementedError end + def url + raise NotImplementedError + end + def limit raise NotImplementedError end From 875f1873d374d14b8fafbc5fb452afbf6ede9b3b Mon Sep 17 00:00:00 2001 From: f Date: Mon, 18 Apr 2022 17:27:43 -0300 Subject: [PATCH 157/235] no fallar al cerrarse la salida --- app/models/deploy.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 7aedbb19..922c7560 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -74,8 +74,7 @@ class Deploy < ApplicationRecord puts line if output end rescue IOError => e - lines << e.message - puts e.message if output + ExceptionNotifier.notify(e, data: { site: site.name }) end r = t.value From e8746ca385805b288f291866145ad8c005d7f4f0 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Jun 2022 15:07:08 -0300 Subject: [PATCH 158/235] =?UTF-8?q?notificar=20correctamente=20la=20excepc?= =?UTF-8?q?i=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 922c7560..e02602f8 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -74,7 +74,7 @@ class Deploy < ApplicationRecord puts line if output end rescue IOError => e - ExceptionNotifier.notify(e, data: { site: site.name }) + ExceptionNotifier.notify_exception(e, data: { site: site.name }) end r = t.value From 92b97b508b9414384adc2df6e697e7d537ef8d18 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Jun 2022 18:41:51 -0300 Subject: [PATCH 159/235] no generar issues para log --- app/models/deploy.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index e02602f8..7aedbb19 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -74,7 +74,8 @@ class Deploy < ApplicationRecord puts line if output end rescue IOError => e - ExceptionNotifier.notify_exception(e, data: { site: site.name }) + lines << e.message + puts e.message if output end r = t.value From 4ebd9881f558bf443ae58cb566952b0bd91f792e Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 14:31:39 -0300 Subject: [PATCH 160/235] =?UTF-8?q?fix:=20mejorar=20gesti=C3=B3n=20de=20sy?= =?UTF-8?q?mlink?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_www.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/deploy_www.rb b/app/models/deploy_www.rb index d27f77cc..bb25cc64 100644 --- a/app/models/deploy_www.rb +++ b/app/models/deploy_www.rb @@ -8,7 +8,9 @@ class DeployWww < Deploy before_destroy :remove_destination! - def deploy(**) + def deploy(output: false) + puts "Creando symlink #{site.hostname} => #{destination}" if output + File.symlink?(destination) || File.symlink(site.hostname, destination).zero? end @@ -30,7 +32,7 @@ class DeployWww < Deploy end def url - "https://www.#{site.hostname}/" + "https://#{fqdn}/" end private From 1e188bab0297ea1a21004239a59e7d118807ec69 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 14:37:52 -0300 Subject: [PATCH 161/235] =?UTF-8?q?fix:=20rsync=20no=20deber=C3=ADa=20depe?= =?UTF-8?q?nder=20de=20zip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aunque el zip no se genere igual queremos poder sincronizar el sitio --- app/models/deploy_rsync.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index dd7a492b..04c33cb8 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -10,7 +10,6 @@ class DeployRsync < Deploy deploy_hidden_service deploy_local deploy_www - deploy_zip ] def deploy(output: false) From 431b7223b6b4c428a6edde72d74f5ab8d030abd7 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 14:38:45 -0300 Subject: [PATCH 162/235] feat: eliminar archivos al sincronizar --- app/models/deploy_rsync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index 04c33cb8..8702449a 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -91,7 +91,7 @@ class DeployRsync < Deploy # # @return [Boolean] def rsync(output: output) - run %(rsync -aviH --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/), output: output + run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/) end # El origen es el destino de la compilación From f90ca9cd12d1e6019272393864c5ccbc7e203229 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 14:45:35 -0300 Subject: [PATCH 163/235] fix: output para rsync --- app/models/deploy_rsync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index 8702449a..51d7b2d2 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -91,7 +91,7 @@ class DeployRsync < Deploy # # @return [Boolean] def rsync(output: output) - run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/) + run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/), output: output end # El origen es el destino de la compilación From c6f48f55fcaa602c960c602b70d503bf6e7969d1 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 14:59:34 -0300 Subject: [PATCH 164/235] feat: mostrar una tabla con el resumen en la consola --- app/jobs/deploy_job.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index fe344454..e7ce7ed0 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -54,6 +54,16 @@ class DeployJob < ApplicationJob urls: d.respond_to?(:urls) ? d.urls : [d.url].compact } end + + return unless @output + + puts (Terminal::Table.new do |t| + t << (%w[type] + @deployed.values.first.keys) + t.add_separator + @deployed.each do |type, row| + t << ([type.to_s] + row.values) + end + end) rescue DeployTimedOutException => e notify_exception e ensure From 58dffd00c9111ef2686264ae8f1d867a6fb46456 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 15:10:32 -0300 Subject: [PATCH 165/235] =?UTF-8?q?fix:=20fallar=20el=20hidden=20service?= =?UTF-8?q?=20si=20no=20se=20gener=C3=B3=20el=20onion=20aun?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_hidden_service.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/models/deploy_hidden_service.rb b/app/models/deploy_hidden_service.rb index dc9549f5..79ff1bae 100644 --- a/app/models/deploy_hidden_service.rb +++ b/app/models/deploy_hidden_service.rb @@ -2,14 +2,10 @@ # Genera una versión onion class DeployHiddenService < DeployWww - def deploy(**) - return true if fqdn.blank? - - super - end - def fqdn - values[:onion] + values[:onion].tap do |onion| + raise ArgumentError, 'Aun no se generó la dirección .onion' if onion.blank? + end end def url From d4f4627dab695c73d58c63deb19def3cff5c2d5c Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 15:22:10 -0300 Subject: [PATCH 166/235] fix: capturar todas las posibles excepciones --- app/jobs/deploy_job.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index e7ce7ed0..67548e07 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -39,19 +39,21 @@ class DeployJob < ApplicationJob status = d.deploy seconds = d.build_stats.last.try(:seconds) size = d.size + urls = d.respond_to?(:urls) ? d.urls : [d.url].compact rescue StandardError => e status = false - seconds = 0 - size = 0 + seconds ||= 0 + size ||= 0 + urls ||= [] notify_exception e, d end @deployed[d.type.underscore.to_sym] = { status: status, - seconds: seconds || 0, + seconds: seconds, size: size, - urls: d.respond_to?(:urls) ? d.urls : [d.url].compact + urls: urls } end From 5974a40d027e1f7c6de11585591f7190918efa56 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 15:23:13 -0300 Subject: [PATCH 167/235] feat: hacer sonar una campana --- app/jobs/deploy_job.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 67548e07..3c9b2740 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -66,6 +66,8 @@ class DeployJob < ApplicationJob t << ([type.to_s] + row.values) end end) + + puts "\a" rescue DeployTimedOutException => e notify_exception e ensure From ba91ed56aa89546f494c14cd9dec8bcb1fe59ae9 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 15:50:05 -0300 Subject: [PATCH 168/235] feat: separar rsync de full rsync los segundos se usan para sincronizar todas las versiones de un sitio con otro servidor de sutty. los primeros solo sincronizan los archivos a otro servidor, no necesariamente bajo el mismo nombre. --- app/models/deploy_alternative_domain.rb | 6 ++- app/models/deploy_full_rsync.rb | 22 +++++++++++ app/models/deploy_rsync.rb | 9 +---- app/services/site_service.rb | 2 +- ...ename_deploy_rsync_to_deploy_full_rsync.rb | 37 +++++++++++++++++++ 5 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 app/models/deploy_full_rsync.rb create mode 100644 db/migrate/20230318183722_rename_deploy_rsync_to_deploy_full_rsync.rb diff --git a/app/models/deploy_alternative_domain.rb b/app/models/deploy_alternative_domain.rb index 9b1d63d7..75b69180 100644 --- a/app/models/deploy_alternative_domain.rb +++ b/app/models/deploy_alternative_domain.rb @@ -20,7 +20,11 @@ class DeployAlternativeDomain < Deploy end def destination - @destination ||= File.join(Rails.root, '_deploy', hostname.gsub(/\.\z/, '')) + @destination ||= File.join(Rails.root, '_deploy', fqdn) + end + + def fqdn + hostname.gsub(/\.\z/, '') end def url diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb new file mode 100644 index 00000000..c0ff84c6 --- /dev/null +++ b/app/models/deploy_full_rsync.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class DeployFullRsync < DeployRsync + DEPENDENCIES = %i[ + deploy_alternative_domain + deploy_hidden_service + deploy_local + deploy_www + ] + + # Sincroniza las ubicaciones alternativas también + # + # @param :output [Boolean] + # @return [Boolean] + def rsync(output: false) + DEPENDENCIES.map(&:to_s).map(&:classify).map do |dependency| + site.deploys.where(type: dependency).find_each.map do |deploy| + run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape deploy.destination} #{Shellwords.escape destination}), output: output + end + end.flatten.all? + end +end diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index 51d7b2d2..6a96a274 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -5,12 +5,7 @@ class DeployRsync < Deploy store :values, accessors: %i[destination host_keys], coder: JSON - DEPENDENCIES = %i[ - deploy_alternative_domain - deploy_hidden_service - deploy_local - deploy_www - ] + DEPENDENCIES = %i[deploy_local] def deploy(output: false) ssh? && rsync(output: output) @@ -90,7 +85,7 @@ class DeployRsync < Deploy # Sincroniza hacia el directorio remoto # # @return [Boolean] - def rsync(output: output) + def rsync(output: false) run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/), output: output end diff --git a/app/services/site_service.rb b/app/services/site_service.rb index f5f415e7..0ecccba4 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -163,7 +163,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Crea los deploys necesarios para sincronizar a otros nodos de Sutty def sync_nodes Rails.application.nodes.each do |node| - site.deploys.build(type: 'DeployRsync', destination: "sutty@#{node}:#{site.hostname}") + site.deploys.build(type: 'DeployFullRsync', destination: "sutty@#{node}:") end end end diff --git a/db/migrate/20230318183722_rename_deploy_rsync_to_deploy_full_rsync.rb b/db/migrate/20230318183722_rename_deploy_rsync_to_deploy_full_rsync.rb new file mode 100644 index 00000000..689dc559 --- /dev/null +++ b/db/migrate/20230318183722_rename_deploy_rsync_to_deploy_full_rsync.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Cambia todos los DeployRsync propios de Sutty a DeployFullRsync que se +# encarga de sincronizar todo. +class RenameDeployRsyncToDeployFullRsync < ActiveRecord::Migration[6.1] + def up + DeployRsync.all.find_each do |deploy| + dest = deploy.destination.split(':', 2).first + + next unless nodes.include? dest + + deploy.destination = "#{dest}:" + deploy.type = 'DeployFullRsync' + + deploy.save + end + end + + def down + DeployFullRsync.all.find_each do |deploy| + next unless nodes.include? deploy.destination.split(':', 2).first + + deploy.destination = "#{deploy.destination}#{deploy.site.hostname}" + deploy.type = 'DeployRsync' + + deploy.save + end + end + + private + + def nodes + @nodes ||= Rails.application.nodes.map do |node| + "sutty@#{node}" + end + end +end From 6f4e91d3180005372a5ee9f7bb3e0db140d6c63f Mon Sep 17 00:00:00 2001 From: f Date: Wed, 5 Oct 2022 18:44:23 -0300 Subject: [PATCH 169/235] soportar distributed press apiv0 #7839 --- app/models/deploy.rb | 15 ++++++++++ app/models/deploy_distributed_press.rb | 34 +++++++++++++++++++++++ app/models/deploy_local.rb | 38 ++++++++++++++++++-------- 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 app/models/deploy_distributed_press.rb diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 7aedbb19..52031d87 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -92,6 +92,13 @@ class Deploy < ApplicationRecord r&.success? end + # Variables de entorno + # + # @return [Hash] + def local_env + @local_env ||= {} + end + private # @param [String] @@ -99,4 +106,12 @@ class Deploy < ApplicationRecord def readable_cmd(cmd) cmd.split(' -', 2).first.tr(' ', '_') end + + def deploy_local + @deploy_local ||= site.deploys.find_by(type: 'DeployLocal') + end + + def non_local_deploys + @non_local_deploys ||= site.deploys.where.not(type: 'DeployLocal') + end end diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb new file mode 100644 index 00000000..51788865 --- /dev/null +++ b/app/models/deploy_distributed_press.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Soportar Distributed Press APIv0 +# +# No se realiza ninguna acción porque el deploy se hace desde el plugin +# local. +class DeployDistributedPress < Deploy + store :values, accessors: %i[api_key hostname], coder: JSON + + def deploy; end + + def limit; end + + def size + deploy_local.size + end + + # TODO: Devolver hyper:// y otras + def url + "ipfs://#{hostname}/" + end + + # Devuelve variables de entorno para enviarle a DeployLocal + # + # @return [Hash] + def local_env + { + 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, + 'DISTRIBUTED_PRESS_API_KEY' => api_key + } + end + + def destination; end +end diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 00e0985d..2d77df75 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -67,21 +67,24 @@ class DeployLocal < Deploy end # Un entorno que solo tiene lo que necesitamos + # + # @return [Hash] def env # XXX: This doesn't support Windows paths :B paths = [File.dirname(`which bundle`), '/usr/bin', '/bin'] - { - 'HOME' => home_dir, - 'PATH' => paths.join(':'), - 'SPREE_API_KEY' => site.tienda_api_key, - 'SPREE_URL' => site.tienda_url, - 'AIRBRAKE_PROJECT_ID' => site.id.to_s, - 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, - 'JEKYLL_ENV' => Rails.env, - 'LANG' => ENV['LANG'], - 'YARN_CACHE_FOLDER' => yarn_cache_dir - } + # Las variables de entorno extra no pueden superponerse al local. + extra_env.merge({ + 'HOME' => home_dir, + 'PATH' => paths.join(':'), + 'SPREE_API_KEY' => site.tienda_api_key, + 'SPREE_URL' => site.tienda_url, + 'AIRBRAKE_PROJECT_ID' => site.id.to_s, + 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, + 'JEKYLL_ENV' => Rails.env, + 'LANG' => ENV['LANG'], + 'YARN_CACHE_FOLDER' => yarn_cache_dir + }) end def yarn_cache_dir @@ -125,4 +128,17 @@ class DeployLocal < Deploy def remove_destination! FileUtils.rm_rf destination end + + # Consigue todas las variables de entorno configuradas por otros + # deploys. + # + # @return [Hash] + def extra_env + @extra_env ||= + non_local_deploys.reduce({}) do |extra_env, deploy| + extra_env.tap do |e| + e.merge! deploy.local_env + end + end + end end From b7daa8e0eb4a111e880329b1ed57ccf6dc88063a Mon Sep 17 00:00:00 2001 From: f Date: Fri, 18 Nov 2022 15:56:59 -0300 Subject: [PATCH 170/235] feat: poder modificar la url de distributed press --- app/models/deploy_distributed_press.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 51788865..a24ae62c 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -5,7 +5,7 @@ # No se realiza ninguna acción porque el deploy se hace desde el plugin # local. class DeployDistributedPress < Deploy - store :values, accessors: %i[api_key hostname], coder: JSON + store :values, accessors: %i[api_url api_key hostname], coder: JSON def deploy; end @@ -26,7 +26,8 @@ class DeployDistributedPress < Deploy def local_env { 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, - 'DISTRIBUTED_PRESS_API_KEY' => api_key + 'DISTRIBUTED_PRESS_API_KEY' => api_key, + 'DISTRIBUTED_PRESS_API_URL' => api_url } end From ecdbfeb56863589f0c2b16031a17ecaf3da5769c Mon Sep 17 00:00:00 2001 From: Maki Date: Tue, 17 Jan 2023 18:31:54 -0300 Subject: [PATCH 171/235] agrego toggler para distributed press --- app/models/site.rb | 2 +- .../deploys/_deploy_distributed_press.haml | 21 +++++++++++++++++++ config/locales/en.yml | 4 ++++ config/locales/es.yml | 4 ++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 app/views/deploys/_deploy_distributed_press.haml diff --git a/app/models/site.rb b/app/models/site.rb index f88e2e97..af0b2c53 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -18,7 +18,7 @@ class Site < ApplicationRecord # 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].freeze + DEPLOYS = %i[local private www zip hidden_service distributed_press].freeze validates :name, uniqueness: true, hostname: { allow_root_label: true diff --git a/app/views/deploys/_deploy_distributed_press.haml b/app/views/deploys/_deploy_distributed_press.haml new file mode 100644 index 00000000..d7d54db0 --- /dev/null +++ b/app/views/deploys/_deploy_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', public_url: deploy.object.site.url), + tags: %w[p strong em a] + + +%hr/ diff --git a/config/locales/en.yml b/config/locales/en.yml index 567ab6bb..595d6145 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -272,6 +272,10 @@ en: Only accessible through [Tor Browser](https://www.torproject.org/download/) + deploy_distributed_press: + title: 'Publish on Distributed Press' + help: | + ipfs stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index 0a829e4a..3be67130 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -277,6 +277,10 @@ es: Sólo será accesible a través del [Navegador Tor](https://www.torproject.org/es/download/). + deploy_distributed_press: + title: 'Alojar en la web distribuida' + help: | + Es para que esté en la web distribuida stats: index: title: Estadísticas From 84b2968cdbf85c66a5a9ab1a4534f75a20463e3a Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 18:22:08 -0300 Subject: [PATCH 172/235] feat: almacenar y renovar tokens de distributed press --- Gemfile | 1 + Gemfile.lock | 40 ++++++++++- Procfile | 1 + .../renew_distributed_press_tokens_job.rb | 17 +++++ app/models/distributed_press_publisher.rb | 68 +++++++++++++++++++ ...5420_create_distributed_press_publisher.rb | 14 ++++ lib/tasks/distributed_press.rake | 10 +++ monit.conf | 5 ++ 8 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 app/jobs/renew_distributed_press_tokens_job.rb create mode 100644 app/models/distributed_press_publisher.rb create mode 100644 db/migrate/20230119165420_create_distributed_press_publisher.rb create mode 100644 lib/tasks/distributed_press.rake diff --git a/Gemfile b/Gemfile index 489097a6..fb1f4953 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' +gem 'distributed-press-api-client', '~> 0.2.0' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 5df84963..9a754b83 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -115,6 +115,7 @@ GEM xpath (>= 2.0, < 4.0) chartkick (4.1.2) childprocess (4.1.0) + climate_control (1.2.0) coderay (1.1.3) colorator (1.1.0) commonmarker (0.21.2-x86_64-linux-musl) @@ -153,12 +154,45 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) + distributed-press-api-client (0.2.0) + addressable (~> 2.3, >= 2.3.0) + climate_control + dry-schema + httparty (~> 0.18) + json (~> 2.1, >= 2.1.0) + jwt (~> 2.6.0) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) down (5.2.4) addressable (~> 2.8) + dry-configurable (1.0.1) + dry-core (~> 1.0, < 2) + zeitwerk (~> 2.6) + dry-core (1.0.0) + concurrent-ruby (~> 1.0) + zeitwerk (~> 2.6) + dry-inflector (1.0.0) + dry-initializer (3.1.1) + dry-logic (1.5.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0, < 2) + zeitwerk (~> 2.6) + dry-schema (1.13.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 1.0, >= 1.0.1) + dry-core (~> 1.0, < 2) + dry-initializer (~> 3.0) + dry-logic (>= 1.5, < 2) + dry-types (>= 1.7, < 2) + zeitwerk (~> 2.6) + dry-types (1.7.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0, < 2) + dry-inflector (~> 1.0, < 2) + dry-logic (>= 1.4, < 2) + zeitwerk (~> 2.6) ed25519 (1.2.4-x86_64-linux-musl) em-websocket (0.5.3) eventmachine (>= 0.12.9) @@ -216,8 +250,8 @@ GEM thor hiredis (0.6.3-x86_64-linux-musl) http_parser.rb (0.8.0-x86_64-linux-musl) - httparty (0.18.1) - mime-types (~> 3.0) + httparty (0.21.0) + mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) i18n (1.8.11) concurrent-ruby (~> 1.0) @@ -292,6 +326,7 @@ GEM jekyll-write-and-commit-changes (0.2.1) jekyll (~> 4) rugged (~> 1) + jwt (2.6.0) kaminari (1.2.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.1) @@ -584,6 +619,7 @@ DEPENDENCIES devise devise-i18n devise_invitable + distributed-press-api-client (~> 0.2.0) dotenv-rails down ed25519 diff --git a/Procfile b/Procfile index 45fe1df7..79daa90b 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,3 @@ cleanup: bundle exec rake cleanup:everything stats: bundle exec rake stats:process_all +distributed_press_renew_tokens: bundle exec rake distributed_press:tokens:renew diff --git a/app/jobs/renew_distributed_press_tokens_job.rb b/app/jobs/renew_distributed_press_tokens_job.rb new file mode 100644 index 00000000..5664d9fa --- /dev/null +++ b/app/jobs/renew_distributed_press_tokens_job.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Renueva los tokens de Distributed Press antes que se venzan, +# activando los callbacks que hacen que se refresque el token. +class RenewDistributedPressTokensJob < ApplicationJob + # Renueva todos los tokens a punto de vencer o informa el error sin + # detener la tarea si algo pasa. + def perform + DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher| + publisher.touch + rescue DistributedPress::V1::Error => e + data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at } + + ExceptionNotifier.notify_exception(e, data: data) + end + end +end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb new file mode 100644 index 00000000..610d698d --- /dev/null +++ b/app/models/distributed_press_publisher.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'distributed_press/v1' + +# Almacena el token de autenticación y la URL, por ahora solo vamos +# a tener uno, pero queda abierta la posibilidad de agregar más. +class DistributedPressPublisher < ApplicationRecord + # Cifrar la información del token en la base de datos + has_encrypted :token + + # La instancia es única + validates_uniqueness_of :instance + + # El token es necesario + validates_presence_of :token + + # Mantener la fecha de vencimiento actualizada + before_save :update_expires_at_from_token!, :update_token_from_client! + + # Devuelve todos los tokens que vencen en una hora + scope :with_about_to_expire_tokens, lambda { + where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour) + } + + # Al cambiar el token genera un cliente nuevo + # + # @return [String] + def token=(new_token) + @client = nil + super + end + + # Al cambiar la instancia genera un cliente nuevo + # + # @return [String] + def instance=(new_instance) + @client = nil + super + end + + # Instancia un cliente de Distributed Press a partir del token. Al + # cargar un token a punto de vencer se renueva automáticamente. + # + # @return [DistributedPress::V1::Client] + def client + @client ||= DistributedPress::V1::Client.new(url: instance, token: token) + end + + private + + # Actualiza o desactiva la fecha de vencimiento a partir de la + # información del token. + # + # @return [nil] + def update_expires_at_from_token! + self.expires_at = client.token.forever? ? nil : client.token.expires_at + nil + end + + # Actualiza el token a partir del cliente, que ya actualiza el token + # automáticamente. + # + # @return [nil] + def update_token_from_client! + self.token = client.token.to_s + nil + end +end diff --git a/db/migrate/20230119165420_create_distributed_press_publisher.rb b/db/migrate/20230119165420_create_distributed_press_publisher.rb new file mode 100644 index 00000000..8d8de37a --- /dev/null +++ b/db/migrate/20230119165420_create_distributed_press_publisher.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Crea la tabla de publishers de Distributed Press que contiene las +# instancias y tokens +class CreateDistributedPressPublisher < ActiveRecord::Migration[6.1] + def change + create_table :distributed_press_publishers do |t| + t.timestamps + t.string :instance, unique: true + t.text :token_ciphertext, null: false + t.datetime :expires_at, null: true + end + end +end diff --git a/lib/tasks/distributed_press.rake b/lib/tasks/distributed_press.rake new file mode 100644 index 00000000..8ba270ec --- /dev/null +++ b/lib/tasks/distributed_press.rake @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +namespace :distributed_press do + namespace :tokens do + desc 'Renew tokens' + task renew: :environment do + RenewDistributedPressTokensJob.perform_now + end + end +end diff --git a/monit.conf b/monit.conf index 39f45d6d..1d6bbae1 100644 --- a/monit.conf +++ b/monit.conf @@ -13,3 +13,8 @@ check program stats with path "/usr/bin/foreman run -f /srv/Procfile -d /srv stats" as uid "rails" gid "www-data" every "0 1 * * *" if status != 0 then alert + +check program distributed_press_tokens_renew + with path "/usr/bin/foreman run -f /srv/Procfile -d /srv distributed_press_tokens_renew" as uid "rails" gid "www-data" + every "0 3 * * *" + if status != 0 then alert From c44584596da1d3e23d8f986ec7d2b9a421bfb1b6 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 20:34:27 -0300 Subject: [PATCH 173/235] feat: crear y publicar el sitio en distributed press v1 --- app/models/deploy_distributed_press.rb | 143 ++++++++++++++++++---- app/models/distributed_press_publisher.rb | 5 + 2 files changed, 125 insertions(+), 23 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index a24ae62c..09ba0364 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,13 +1,43 @@ # frozen_string_literal: true -# Soportar Distributed Press APIv0 -# -# No se realiza ninguna acción porque el deploy se hace desde el plugin -# local. -class DeployDistributedPress < Deploy - store :values, accessors: %i[api_url api_key hostname], coder: JSON +require 'distributed_press/v1/client/auth' +require 'distributed_press/v1/client/site' - def deploy; end +# Soportar Distributed Press APIv1 +# +# Usa tokens de publicación efímeros para todas las acciones. +# +# Al ser creado, genera el sitio en la instancia de Distributed Press +# configurada y almacena el ID. +# +# Al ser publicado, envía los archivos en un tarball y actualiza la +# información. +class DeployDistributedPress < Deploy + store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON + + before_create :create_remote_site! + + # Actualiza la información y luego envía los cambios + # + # @param :output [Bool] + # @return [Bool] + def deploy + time_start + + status = false + + site_client.tap do |c| + update remote_info: c.show(publishing_site).to_h + + status = c.publish(publishing_site, deploy_local.destination) + end + + time_stop + + create_stat! status + + status + end def limit; end @@ -15,21 +45,88 @@ class DeployDistributedPress < Deploy deploy_local.size end - # TODO: Devolver hyper:// y otras - def url - "ipfs://#{hostname}/" - end - - # Devuelve variables de entorno para enviarle a DeployLocal - # - # @return [Hash] - def local_env - { - 'DISTRIBUTED_PRESS_PROJECT_DOMAIN' => hostname, - 'DISTRIBUTED_PRESS_API_KEY' => api_key, - 'DISTRIBUTED_PRESS_API_URL' => api_url - } - end - def destination; end + + private + + # El cliente de la API + # + # TODO: cuando soportemos más, tiene que haber una relación entre + # DeployDistributedPress y DistributedPressPublisher. + # + # @return [DistributedPressPublisher] + def publisher + @publisher ||= DistributedPressPublisher.first + end + + # El cliente de autenticación se encarga de intercambiar un token por + # otro + # + # @return [DistributedPress::V1::Client::Auth] + def auth_client + DistributedPress::V1::Client::Auth.new(publisher.client) + end + + # Genera un token con permisos de publicación + # + # @return [DistributedPress::V1::Schemas::NewTokenPayload] + def publishing_token_payload + DistributedPress::V1::Schemas::NewTokenPayload.new.call(capabilities: %w[publisher]) + end + + # Genera un token efímero para publicar el sitio + # + # @return [DistributedPress::V1::Token] + def publishing_token + auth_client.exchange(publishing_token_payload) + end + + # Genera un cliente para publicar el sitio + # + # @return [DistributedPress::V1::Client] + def publishing_client + DistributedPress::V1::Client.new(url: publisher.instance, token: publishing_token) + end + + # El cliente para actualizar el sitio + # + # @return [DistributedPress::V1::Client::Site] + def site_client + DistributedPress::V1::Client::Site.new(publishing_client) + end + + # Genera el esquema de datos para poder publicar el sitio + # + # @return [DistributedPress::V1::Schemas::PublishingSite] + def publishing_site + DistributedPress::V1::Schemas::PublishingSite.new.call(id: remote_site_id) + end + + # Genera el esquema de datos para crear el sitio + # + # @return [DistributedPressPublisher::V1::Schemas::NewSite] + def create_site + DistributedPress::V1::Schemas::NewSite.new.call(domain: hostname, protocols: { http: true, ipfs: true, hyper: true }) + end + + # Crea el sitio en la instancia con el hostname especificado + # + # @return [nil] + def create_remote_site! + created_site = site_client.create(create_site) + + self.remote_site_id = created_site[:id] + self.remote_info = created_site.to_h + + nil + end + + # Registra lo que sucedió + # + # @param status [Bool] + # @return [nil] + def create_stat!(status) + build_stats.create action: publisher.to_s, seconds: time_spent_in_seconds, bytes: size, status: status + nil + end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 610d698d..5358e738 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -46,6 +46,11 @@ class DistributedPressPublisher < ApplicationRecord @client ||= DistributedPress::V1::Client.new(url: instance, token: token) end + # @return [String] + def to_s + "Distributed Press <#{instance}>" + end + private # Actualiza o desactiva la fecha de vencimiento a partir de la From f190fb2dc82bc5f3a3e829ec1a10aa672f19f890 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Jan 2023 20:35:39 -0300 Subject: [PATCH 174/235] fix: permitir modificar el token estos parches hacian que no se pueda modificar el token --- app/models/distributed_press_publisher.rb | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 5358e738..acfc4226 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -22,22 +22,6 @@ class DistributedPressPublisher < ApplicationRecord where('expires_at > ? and expires_at < ?', Time.now, Time.now + 1.hour) } - # Al cambiar el token genera un cliente nuevo - # - # @return [String] - def token=(new_token) - @client = nil - super - end - - # Al cambiar la instancia genera un cliente nuevo - # - # @return [String] - def instance=(new_instance) - @client = nil - super - end - # Instancia un cliente de Distributed Press a partir del token. Al # cargar un token a punto de vencer se renueva automáticamente. # From 4ebbd48fde8b8bf8203e163a48ddd9159f1a06df Mon Sep 17 00:00:00 2001 From: f Date: Mon, 23 Jan 2023 18:39:10 -0300 Subject: [PATCH 175/235] =?UTF-8?q?feat:=20no=20vamos=20a=20expedir=20toke?= =?UTF-8?q?ns=20ef=C3=ADmeros=20por=20ahora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 31 +------------------------- 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 09ba0364..38cb59e3 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -59,40 +59,11 @@ class DeployDistributedPress < Deploy @publisher ||= DistributedPressPublisher.first end - # El cliente de autenticación se encarga de intercambiar un token por - # otro - # - # @return [DistributedPress::V1::Client::Auth] - def auth_client - DistributedPress::V1::Client::Auth.new(publisher.client) - end - - # Genera un token con permisos de publicación - # - # @return [DistributedPress::V1::Schemas::NewTokenPayload] - def publishing_token_payload - DistributedPress::V1::Schemas::NewTokenPayload.new.call(capabilities: %w[publisher]) - end - - # Genera un token efímero para publicar el sitio - # - # @return [DistributedPress::V1::Token] - def publishing_token - auth_client.exchange(publishing_token_payload) - end - - # Genera un cliente para publicar el sitio - # - # @return [DistributedPress::V1::Client] - def publishing_client - DistributedPress::V1::Client.new(url: publisher.instance, token: publishing_token) - end - # El cliente para actualizar el sitio # # @return [DistributedPress::V1::Client::Site] def site_client - DistributedPress::V1::Client::Site.new(publishing_client) + DistributedPress::V1::Client::Site.new(publisher.client) end # Genera el esquema de datos para poder publicar el sitio From c789813a46834ee675f12c1a05bb7fe987dbb817 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Jan 2023 15:41:54 -0300 Subject: [PATCH 176/235] fix: actualizar api --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9a754b83..c739d86b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -154,7 +154,7 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) - distributed-press-api-client (0.2.0) + distributed-press-api-client (0.2.1) addressable (~> 2.3, >= 2.3.0) climate_control dry-schema From ea0539bb1f2db3145f3a05b9ab067a9530872d84 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 6 Feb 2023 16:09:51 -0300 Subject: [PATCH 177/235] feat: usar pnpm si existe relacionado con sutty/jekyll/sutty-base-jekyll-theme#53 --- Dockerfile | 2 ++ app/models/deploy_local.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Dockerfile b/Dockerfile index 342c2750..71edc3d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,8 @@ RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pando COPY ./monit.conf /etc/monit.d/sutty.conf +RUN apk add npm && npm install -g pnpm && apk del npm + VOLUME "/srv" EXPOSE 3000 diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 2d77df75..0e4f6c1c 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -15,6 +15,7 @@ class DeployLocal < Deploy def deploy(output: false) return false unless mkdir return false unless yarn(output: output) + return false unless pnpm(output: output) return false unless bundle(output: output) jekyll_build(output: output) @@ -91,6 +92,10 @@ class DeployLocal < Deploy Rails.root.join('_yarn_cache').to_s end + def pnpm_cache_dir + Rails.root.join('_pnpm_cache').to_s + end + def yarn_lock File.join(site.path, 'yarn.lock') end @@ -103,6 +108,14 @@ class DeployLocal < Deploy run %(gem install bundler --no-document), output: output end + def pnpm_lock + File.join(site.path, 'pnpm-lock.yaml') + end + + def pnpm_lock? + File.exist? pnpm_lock + end + # Corre yarn dentro del repositorio def yarn(output: false) return true unless yarn_lock? @@ -114,6 +127,13 @@ class DeployLocal < Deploy run %(bundle install --no-cache --path="#{gems_dir}" --clean --without test development), output: output end + def pnpm + return true unless pnpm_lock? + + run %(pnpm config set store-dir "#{pnpm_cache_dir}") + run 'pnpm install --production' + end + def jekyll_build(output: false) run %(bundle exec jekyll build --trace --profile --destination "#{escaped_destination}"), output: output end From 0bb0698bd45cb2224d9d81e973f7b8cde1c19c90 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 6 Feb 2023 16:16:27 -0300 Subject: [PATCH 178/235] fix: pnpm se instala localmente --- app/models/deploy_local.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 0e4f6c1c..d6dc6c28 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -72,7 +72,7 @@ class DeployLocal < Deploy # @return [Hash] def env # XXX: This doesn't support Windows paths :B - paths = [File.dirname(`which bundle`), '/usr/bin', '/bin'] + paths = [File.dirname(`which bundle`), '/usr/local/bin', '/usr/bin', '/bin'] # Las variables de entorno extra no pueden superponerse al local. extra_env.merge({ From 436b55d3179beca19495a61b273ab2ed22a66474 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 7 Feb 2023 18:15:25 -0300 Subject: [PATCH 179/235] feat: textos para el panel --- config/locales/en.yml | 16 ++++++++++++++-- config/locales/es.yml | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 595d6145..66372077 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -273,9 +273,21 @@ en: Only accessible through [Tor Browser](https://www.torproject.org/download/) deploy_distributed_press: - title: 'Publish on Distributed Press' + title: 'Publish to the distributed Web' help: | - ipfs + Make your site available through peer-to-peer protocols, + Inter-Planetary File System (IPFS), Hypercore, and via + BitTorrent, so your site is more resilient and can be available + offline, including in community mesh networks. + + **Important:** Only use this option if you would like your data + to be permanently available. If you decide to undo this + selection, a cleared version of the site will be shared in its + place. However, it is possible that nodes on the distributed + storage network may continue retaining copies of the data + indefinitely. + + [Learn more](#) stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index 3be67130..79736137 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -278,9 +278,21 @@ es: Sólo será accesible a través del [Navegador Tor](https://www.torproject.org/es/download/). deploy_distributed_press: - title: 'Alojar en la web distribuida' + title: 'Publicar a la Web distribuida' help: | - Es para que esté en la web distribuida + Utiliza protocolos de pares, Inter-Planetary File System (IPFS), + Hypercore y torrents, para que tu sitio sea más resiliente y + esté disponible _offline_, inclusive en redes _mesh_ + comunitarias. + + **Importante:** Sólo usa esta opción si te parece correcto que + tu contenido esté disponible permanentemente. Cuando elijas + des-hacer esta acción, una versión "vacía" del sitio será + compartida en su lugar. Sin embargo, es posible que algunos + nodos en la red de almacenamiento distribuida puedan retener + copias de tu contenido indefinidamente. + + [Saber más](#) stats: index: title: Estadísticas From 4c6818762d72cca41c3cf22118abbd5e7e163dba Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 09:38:36 -0300 Subject: [PATCH 180/235] fix: faltaban algunos require --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index fb1f4953..f92a37bf 100644 --- a/Gemfile +++ b/Gemfile @@ -39,7 +39,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' -gem 'distributed-press-api-client', '~> 0.2.0' +gem 'distributed-press-api-client', '~> 0.2.1' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index c739d86b..244d5511 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -619,7 +619,7 @@ DEPENDENCIES devise devise-i18n devise_invitable - distributed-press-api-client (~> 0.2.0) + distributed-press-api-client (~> 0.2.1) dotenv-rails down ed25519 From 975bf39c2e233b6d78f0e968c43a34359c3aec7c Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 11:55:07 -0300 Subject: [PATCH 181/235] fix: no fallar si tarda mucho dp --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index f92a37bf..64869a4b 100644 --- a/Gemfile +++ b/Gemfile @@ -39,7 +39,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' -gem 'distributed-press-api-client', '~> 0.2.1' +gem 'distributed-press-api-client', '~> 0.2.2' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 244d5511..c214e144 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -154,7 +154,7 @@ GEM devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) - distributed-press-api-client (0.2.1) + distributed-press-api-client (0.2.2) addressable (~> 2.3, >= 2.3.0) climate_control dry-schema @@ -619,7 +619,7 @@ DEPENDENCIES devise devise-i18n devise_invitable - distributed-press-api-client (~> 0.2.1) + distributed-press-api-client (~> 0.2.2) dotenv-rails down ed25519 From 4e1f14a528f44d98199b20c3969e8129e7e274ad Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 17:08:02 -0300 Subject: [PATCH 182/235] =?UTF-8?q?feat:=20guardar=20un=20log=20y=20mostra?= =?UTF-8?q?rlo=20en=20output=20tambi=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 24 ++++++++++++++++++----- app/models/distributed_press_publisher.rb | 22 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 38cb59e3..d805e923 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -22,19 +22,32 @@ class DeployDistributedPress < Deploy # @param :output [Bool] # @return [Bool] def deploy + status = false + log = [] + time_start - status = false - site_client.tap do |c| + stdout = Thread.new(publisher.logger_out) do |io| + until io.eof? + line = io.gets + + puts line if output + log << line + end + end + update remote_info: c.show(publishing_site).to_h status = c.publish(publishing_site, deploy_local.destination) + + publisher.logger.close + stdout.join end time_stop - create_stat! status + create_stat! status, log.join status end @@ -95,9 +108,10 @@ class DeployDistributedPress < Deploy # Registra lo que sucedió # # @param status [Bool] + # @param log [String] # @return [nil] - def create_stat!(status) - build_stats.create action: publisher.to_s, seconds: time_spent_in_seconds, bytes: size, status: status + def create_stat!(status, log) + build_stats.create action: publisher.to_s,log: log, seconds: time_spent_in_seconds, bytes: size, status: status nil end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index acfc4226..089f63c6 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -8,6 +8,11 @@ class DistributedPressPublisher < ApplicationRecord # Cifrar la información del token en la base de datos has_encrypted :token + # La salida del log + # + # @return [IO] + attr_reader :logger_out + # La instancia es única validates_uniqueness_of :instance @@ -27,7 +32,7 @@ class DistributedPressPublisher < ApplicationRecord # # @return [DistributedPress::V1::Client] def client - @client ||= DistributedPress::V1::Client.new(url: instance, token: token) + @client ||= DistributedPress::V1::Client.new(url: instance, token: token, logger: logger) end # @return [String] @@ -35,8 +40,23 @@ class DistributedPressPublisher < ApplicationRecord "Distributed Press <#{instance}>" end + # @return [Logger] + def logger + @logger ||= + begin + @logger_out, @logger_in = IO.pipe + ::Logger.new @logger_in, formatter: formatter + end + end + private + def formatter + @formatter ||= lambda do |_, _, _, msg| + "#{msg}\n" + end + end + # Actualiza o desactiva la fecha de vencimiento a partir de la # información del token. # From c291fefa998110ecef8f53486169f504ab0f9bb2 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 17:44:35 -0300 Subject: [PATCH 183/235] =?UTF-8?q?fix:=20link=20a=20saber=20m=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 2 +- config/locales/es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 66372077..531b492f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -287,7 +287,7 @@ en: storage network may continue retaining copies of the data indefinitely. - [Learn more](#) + [Learn more](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/) stats: index: title: Statistics diff --git a/config/locales/es.yml b/config/locales/es.yml index 79736137..84723b81 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -292,7 +292,7 @@ es: nodos en la red de almacenamiento distribuida puedan retener copias de tu contenido indefinidamente. - [Saber más](#) + [Saber más (en inglés)](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/) stats: index: title: Estadísticas From 56a3f2becb0f09909e220dd0c62794b95e8aa9d3 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 18:49:37 -0300 Subject: [PATCH 184/235] feat: un deploy puede tener varias urls --- app/models/deploy_distributed_press.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index d805e923..d3474d50 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -60,6 +60,15 @@ class DeployDistributedPress < Deploy def destination; end + # Devuelve las URLs de todos los protocolos + def urls + remote_info[:links].values.map do |protocol| + [ protocol[:link], protocol[:gateway] ] + end.flatten.compact.select do |link| + link.include? '://' + end + end + private # El cliente de la API From 0b96fc44d6ba7eedf93d9dcb4ee607c777d7970e Mon Sep 17 00:00:00 2001 From: f Date: Wed, 8 Feb 2023 18:52:48 -0300 Subject: [PATCH 185/235] =?UTF-8?q?feat:=20texto=20para=20el=20correo=20de?= =?UTF-8?q?=20notificaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 4 ++++ config/locales/es.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 531b492f..e040b781 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -126,6 +126,10 @@ en: title: Synchronize to backup server success: Success! error: Error + deploy_distributed_press: + title: Distributed Web + success: Success! + error: Error help: You can contact us by replying to this e-mail maintenance_mailer: notice: diff --git a/config/locales/es.yml b/config/locales/es.yml index 84723b81..f9fdcf29 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -126,6 +126,10 @@ es: title: Sincronizar al servidor alternativo success: ¡Éxito! error: Hubo un error + deploy_distributed_press: + title: Web distribuida + success: ¡Éxito! + error: Hubo un error help: Por cualquier duda, responde este correo para contactarte con nosotres. maintenance_mailer: notice: From 1b5adfb712bf89342993d3b315f236830bf76c6c Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:01:22 -0300 Subject: [PATCH 186/235] feat: crear temporalmente los dominios en njalla el problema es que no podemos delegar `_dnslink.*.sutty.nl` hacia distributed press, con lo que es necesario crear un subdominio por cada sitio que lo active. --- Gemfile | 1 + Gemfile.lock | 4 ++++ app/models/deploy_distributed_press.rb | 18 ++++++++++++++++++ app/models/distributed_press_publisher.rb | 7 +++++++ 4 files changed, 30 insertions(+) diff --git a/Gemfile b/Gemfile index 64869a4b..9d1b6d67 100644 --- a/Gemfile +++ b/Gemfile @@ -40,6 +40,7 @@ gem 'devise' gem 'devise-i18n' gem 'devise_invitable' gem 'distributed-press-api-client', '~> 0.2.2' +gem 'njalla-api-client' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index c214e144..c2c29531 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -387,6 +387,9 @@ GEM nokogiri (1.12.5-x86_64-linux-musl) mini_portile2 (~> 2.6.1) racc (~> 1.4) + njalla-api-client (0.1.0) + dry-schema + httparty (~> 0.18) orm_adapter (0.5.0) pairing_heap (3.0.0) parallel (1.21.0) @@ -654,6 +657,7 @@ DEPENDENCIES mini_magick mobility net-ssh + njalla-api-client nokogiri pg pg_search diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index d3474d50..6f2b2c78 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -111,6 +111,12 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h + # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay + # que eliminarlo. + self.remote_info['njalla'] = {} + self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + nil end @@ -123,4 +129,16 @@ class DeployDistributedPress < Deploy build_stats.create action: publisher.to_s,log: log, seconds: time_spent_in_seconds, bytes: size, status: status nil end + + # Actualizar registros en Njalla + # + # @return [Njalla::V1::Domain] + def njalla + @njalla ||= + begin + client = Njalla::V1::Client.new(token: ENV['NJALLA_TOKEN']) + + Njalla::V1::Domain.new(domain: Site.domain, client: client) + end + end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 089f63c6..6139db93 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -40,6 +40,13 @@ class DistributedPressPublisher < ApplicationRecord "Distributed Press <#{instance}>" end + # Devuelve el hostname de la instancia + # + # @return [String] + def hostname + @hostname ||= URI.parse(instance).hostname + end + # @return [Logger] def logger @logger ||= From 4666e67b5da555380d340b7b263b0c735e65dd51 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:08:56 -0300 Subject: [PATCH 187/235] fix: no crear subdominios para dominios personalizados esto es por retrocompatibilidad para sitios que no usan DeployAlternativeDomain --- app/models/deploy_distributed_press.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 6f2b2c78..1ae7a2f2 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -113,9 +113,11 @@ class DeployDistributedPress < Deploy # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay # que eliminarlo. - self.remote_info['njalla'] = {} - self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + unless site.name.end_with? '.' + self.remote_info['njalla'] = {} + self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + end nil end From 812fc0315cc2dfee183e87983894848b6ad03e57 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Feb 2023 20:11:17 -0300 Subject: [PATCH 188/235] fix: requires --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 1ae7a2f2..41054b99 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'distributed_press/v1/client/auth' require 'distributed_press/v1/client/site' +require 'njalla/v1' # Soportar Distributed Press APIv1 # From debf45b726cfc1c50cfe379bd73e5365ee9e8faa Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:33:52 -0300 Subject: [PATCH 189/235] fix: no fallar si hay errores remotos closes #10467 closes #10506 closes #10509 --- app/models/deploy_distributed_press.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 41054b99..09410201 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -118,7 +118,9 @@ class DeployDistributedPress < Deploy self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end - + rescue DistributedPress::V1::Error, HTTParty::Error => e + ExceptionNotifier.notify_exception(e, data: { site: site.name }) + ensure nil end From 2b340a4488da30a82fbdfb51bcdf8796a37ebc3d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:37:48 -0300 Subject: [PATCH 190/235] fix: crear el sitio remoto si no se pudo crear antes --- app/models/deploy_distributed_press.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 09410201..bd80dca4 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -27,6 +27,11 @@ class DeployDistributedPress < Deploy time_start + if remote_site_id.blank? || remote_info['njalla'].blank? + create_remote_site! + save + end + site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| until io.eof? From 29e1d09986022af9a9257941cfbe9b53ddf6b8e9 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:39:41 -0300 Subject: [PATCH 191/235] =?UTF-8?q?feat:=20separar=20la=20creaci=C3=B3n=20?= =?UTF-8?q?de=20DP=20de=20njalla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index bd80dca4..9afc6a5d 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -15,7 +15,7 @@ require 'njalla/v1' class DeployDistributedPress < Deploy store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON - before_create :create_remote_site! + before_create :create_remote_site!, :create_njalla_records! # Actualiza la información y luego envía los cambios # @@ -27,10 +27,9 @@ class DeployDistributedPress < Deploy time_start - if remote_site_id.blank? || remote_info['njalla'].blank? - create_remote_site! - save - end + create_remote_site! if remote_site_id.blank? + create_njalla_records! if remote_info['njalla'].blank? + save site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| @@ -115,7 +114,16 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h + rescue DistributedPress::V1::Error + ExceptionNotifier.notify_exception(e, data: { site: site.name }) + ensure + nil + end + # Crea los registros en Njalla + # + # @return [nil] + def create_njalla_records! # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay # que eliminarlo. unless site.name.end_with? '.' @@ -123,7 +131,7 @@ class DeployDistributedPress < Deploy self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end - rescue DistributedPress::V1::Error, HTTParty::Error => e + rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) ensure nil From f0eab9a7b340ca32842373c3937e35794d509602 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 17 Mar 2023 17:44:13 -0300 Subject: [PATCH 192/235] fix: volver a fallar si al hacer deploy todavia estan caidos los servicios --- app/models/deploy_distributed_press.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 9afc6a5d..e8d8b095 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -31,6 +31,10 @@ class DeployDistributedPress < Deploy create_njalla_records! if remote_info['njalla'].blank? save + if remote_site_id.blank? || remote_info['njalla'].blank? + raise DeployJob::DeployException, '' + end + site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| until io.eof? @@ -133,6 +137,7 @@ class DeployDistributedPress < Deploy end rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) + self.remote_info['njalla'] = nil ensure nil end From 78c2fd0053f8491adf71889477e9a76ccb58dada Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 16:40:17 -0300 Subject: [PATCH 193/235] fix: agregar dependencias a distributed press --- app/models/deploy_distributed_press.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index e8d8b095..7f663a0b 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -17,6 +17,8 @@ class DeployDistributedPress < Deploy before_create :create_remote_site!, :create_njalla_records! + DEPENDENCIES = %i[deploy_local] + # Actualiza la información y luego envía los cambios # # @param :output [Bool] From 3dc10c46f80ae1a750a544351ecce69bc8dac9ce Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 16:41:32 -0300 Subject: [PATCH 194/235] =?UTF-8?q?feat:=20todav=C3=ADa=20no=20hay=20inter?= =?UTF-8?q?faz=20para=20estos=20deploys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/deploys/_deploy_full_rsync.haml | 1 + app/views/deploys/_deploy_localized_domain.haml | 1 + 2 files changed, 2 insertions(+) create mode 100644 app/views/deploys/_deploy_full_rsync.haml create mode 100644 app/views/deploys/_deploy_localized_domain.haml diff --git a/app/views/deploys/_deploy_full_rsync.haml b/app/views/deploys/_deploy_full_rsync.haml new file mode 100644 index 00000000..0aab9802 --- /dev/null +++ b/app/views/deploys/_deploy_full_rsync.haml @@ -0,0 +1 @@ +-# nada diff --git a/app/views/deploys/_deploy_localized_domain.haml b/app/views/deploys/_deploy_localized_domain.haml new file mode 100644 index 00000000..0aab9802 --- /dev/null +++ b/app/views/deploys/_deploy_localized_domain.haml @@ -0,0 +1 @@ +-# nada From 8b10cfb524fd8874126070d1f307b423c881e09e Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 16:48:32 -0300 Subject: [PATCH 195/235] feat: darle url a deploy rsync --- app/models/deploy_rsync.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index 6a96a274..ac9f19ec 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -3,7 +3,7 @@ # Sincroniza sitios a servidores remotos usando Rsync. El servidor # remoto tiene que tener rsync instalado. class DeployRsync < Deploy - store :values, accessors: %i[destination host_keys], coder: JSON + store :values, accessors: %i[hostname destination host_keys], coder: JSON DEPENDENCIES = %i[deploy_local] @@ -25,6 +25,11 @@ class DeployRsync < Deploy end end + # @return [String] + def url + "https://#{hostname}/" + end + private # Verificar la conexión SSH implementando Trust On First Use From 91750116a16ba0b64708f69435d7ae0216121881 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 16:52:36 -0300 Subject: [PATCH 196/235] feat: darle url a full rsync --- app/models/deploy_full_rsync.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb index c0ff84c6..8f1d306e 100644 --- a/app/models/deploy_full_rsync.rb +++ b/app/models/deploy_full_rsync.rb @@ -19,4 +19,8 @@ class DeployFullRsync < DeployRsync end end.flatten.all? end + + def url + "https://#{user_host.last}/" + end end From 75621fb5c553368f8c4013a8f4cd2dea856dc5ee Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 16:53:56 -0300 Subject: [PATCH 197/235] fix: traducir metodos de publicacion #10030 --- config/locales/en.yml | 4 ++++ config/locales/es.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index e040b781..8ecdd6d3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -126,6 +126,10 @@ en: title: Synchronize to backup server success: Success! error: Error + deploy_full_rsync: + title: Synchronize to another Sutty node + success: Success! + error: Error deploy_distributed_press: title: Distributed Web success: Success! diff --git a/config/locales/es.yml b/config/locales/es.yml index f9fdcf29..90c07e32 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -126,6 +126,10 @@ es: title: Sincronizar al servidor alternativo success: ¡Éxito! error: Hubo un error + deploy_full_rsync: + title: Sincronizar a otro nodo de Sutty + success: ¡Éxito! + error: Hubo un error deploy_distributed_press: title: Web distribuida success: ¡Éxito! From ad5724be297accc3dd439f0325b615dec9e119e1 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 17:00:29 -0300 Subject: [PATCH 198/235] fix: siempre hay segundos --- app/jobs/deploy_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 3c9b2740..7cc49157 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -37,7 +37,7 @@ class DeployJob < ApplicationJob raise DeployException, 'Una dependencia falló' if failed_dependencies? d status = d.deploy - seconds = d.build_stats.last.try(:seconds) + seconds = d.build_stats.last.try(:seconds) || 0 size = d.size urls = d.respond_to?(:urls) ? d.urls : [d.url].compact rescue StandardError => e From d40c401a7204c277214ddb57cdd955c0eef8e2c7 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 17:01:38 -0300 Subject: [PATCH 199/235] fix: mostrar la salida --- app/jobs/deploy_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 7cc49157..83b17459 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -36,7 +36,7 @@ class DeployJob < ApplicationJob begin raise DeployException, 'Una dependencia falló' if failed_dependencies? d - status = d.deploy + status = d.deploy(output: @output) seconds = d.build_stats.last.try(:seconds) || 0 size = d.size urls = d.respond_to?(:urls) ? d.urls : [d.url].compact From 54575b3bc3e33f3b7a8425a4c9792957e6c9aa71 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 17:02:38 -0300 Subject: [PATCH 200/235] =?UTF-8?q?fix:=20siempre=20avisar=20cuando=20term?= =?UTF-8?q?in=C3=B3=20el=20deploy=20en=20la=20consola?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/deploy_job.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 83b17459..890f993a 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -66,14 +66,14 @@ class DeployJob < ApplicationJob t << ([type.to_s] + row.values) end end) - - puts "\a" rescue DeployTimedOutException => e notify_exception e ensure @site&.update status: 'waiting' notify_usuaries if notify + + puts "\a" if @output end end # rubocop:enable Metrics/MethodLength From 8b51eb99a3e0224fe0aace172735ebf9025618cd Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 19:01:13 -0300 Subject: [PATCH 201/235] fix: private depende de local para instalar las dependencias --- app/models/deploy_private.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/deploy_private.rb b/app/models/deploy_private.rb index d3bfb50d..1fa42648 100644 --- a/app/models/deploy_private.rb +++ b/app/models/deploy_private.rb @@ -6,6 +6,8 @@ # XXX: La plantilla tiene que soportar esto con el plugin # jekyll-private-data class DeployPrivate < DeployLocal + DEPENDENCIES = %i[deploy_local] + # No es necesario volver a instalar dependencias def deploy(output: false) jekyll_build(output: output) From 94980051b65f8ee9bf44fc2890edf02d89c679bb Mon Sep 17 00:00:00 2001 From: f Date: Sat, 18 Mar 2023 19:33:25 -0300 Subject: [PATCH 202/235] fix: volver a hacer depender la sincronizacion del zip --- app/models/deploy_full_rsync.rb | 1 + app/models/deploy_rsync.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb index 8f1d306e..5bdfeeff 100644 --- a/app/models/deploy_full_rsync.rb +++ b/app/models/deploy_full_rsync.rb @@ -6,6 +6,7 @@ class DeployFullRsync < DeployRsync deploy_hidden_service deploy_local deploy_www + deploy_zip ] # Sincroniza las ubicaciones alternativas también diff --git a/app/models/deploy_rsync.rb b/app/models/deploy_rsync.rb index ac9f19ec..1dff2d99 100644 --- a/app/models/deploy_rsync.rb +++ b/app/models/deploy_rsync.rb @@ -5,7 +5,7 @@ class DeployRsync < Deploy store :values, accessors: %i[hostname destination host_keys], coder: JSON - DEPENDENCIES = %i[deploy_local] + DEPENDENCIES = %i[deploy_local deploy_zip] def deploy(output: false) ssh? && rsync(output: output) From 2a93218ef9d8f412b4116b8463e239cf2e413fb4 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 12:20:50 -0300 Subject: [PATCH 203/235] fix: siempre devolver el destino closes ##10541 closes ##10540 closes ##10539 closes ##10538 closes ##10537 closes ##10536 closes ##10535 closes ##10534 closes ##10533 --- app/models/deploy_zip.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/deploy_zip.rb b/app/models/deploy_zip.rb index 5f72a728..85005470 100644 --- a/app/models/deploy_zip.rb +++ b/app/models/deploy_zip.rb @@ -65,6 +65,8 @@ class DeployZip < Deploy # @return [String] def destination Rails.root.join('_deploy', site.hostname).realpath.to_s + rescue Errno::ENOENT + Rails.root.join('_deploy', site.hostname).to_s end def file From f5274cf34224f3e5cef4ae72dbe1a4cb99d5f1a3 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 12:26:11 -0300 Subject: [PATCH 204/235] =?UTF-8?q?fix:=20no=20hacer=20falla=20la=20config?= =?UTF-8?q?uraci=C3=B3n=20si=20todav=C3=ADa=20no=20se=20gener=C3=B3=20el?= =?UTF-8?q?=20onion=20#10542?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/deploys/_deploy_hidden_service.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/deploys/_deploy_hidden_service.haml b/app/views/deploys/_deploy_hidden_service.haml index d6388123..9ebda012 100644 --- a/app/views/deploys/_deploy_hidden_service.haml +++ b/app/views/deploys/_deploy_hidden_service.haml @@ -17,7 +17,8 @@ = sanitize_markdown t('.help', public_url: deploy.object.site.url), tags: %w[p strong em a] - - if deploy.object.fqdn + - begin = sanitize_markdown t('.help_2', url: deploy.object.url), tags: %w[p strong em a] + - rescue ArgumentError %hr/ From ecd8c80e028ab572ea82546e386bce1d17ceb8ba Mon Sep 17 00:00:00 2001 From: f Date: Mon, 20 Mar 2023 12:13:51 -0300 Subject: [PATCH 205/235] =?UTF-8?q?fix:=20capturar=20la=20excepci=C3=B3n?= =?UTF-8?q?=20#10546?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 7f663a0b..9414abc6 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -120,7 +120,7 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h - rescue DistributedPress::V1::Error + rescue DistributedPress::V1::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) ensure nil From 3abd87e8e6ad18744d5b62a3386bdaeef31e258d Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 17:11:51 -0300 Subject: [PATCH 206/235] feat: guardar la api key de njalla en las credenciales --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 9414abc6..6a6b1d64 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -160,7 +160,7 @@ class DeployDistributedPress < Deploy def njalla @njalla ||= begin - client = Njalla::V1::Client.new(token: ENV['NJALLA_TOKEN']) + client = Njalla::V1::Client.new(token: Rails.application.credentials.njalla) Njalla::V1::Domain.new(domain: Site.domain, client: client) end From 1ff48bf4589e8da1b73323c646af9d95d01524b0 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 18:02:43 -0300 Subject: [PATCH 207/235] fix: no intentar notificar si no hay sitio closes #12753 --- app/jobs/deploy_job.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 890f993a..530b69dd 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -69,11 +69,13 @@ class DeployJob < ApplicationJob rescue DeployTimedOutException => e notify_exception e ensure - @site&.update status: 'waiting' + if @site.present? + @site.update status: 'waiting' - notify_usuaries if notify + notify_usuaries if notify - puts "\a" if @output + puts "\a" if @output + end end end # rubocop:enable Metrics/MethodLength From 21dd6ffd55d7870eac6d682efa183a43aaf2deaa Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Mar 2023 18:25:55 -0300 Subject: [PATCH 208/235] =?UTF-8?q?fix:=20no=20fallar=20njalla=20si=20fall?= =?UTF-8?q?=C3=B3=20dp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #12410 --- app/models/deploy_distributed_press.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 6a6b1d64..679da09d 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -133,6 +133,7 @@ class DeployDistributedPress < Deploy # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay # que eliminarlo. unless site.name.end_with? '.' + self.remote_info ||= {} self.remote_info['njalla'] = {} self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h From c53391b21cd881f4de246cf18eacd345d314c215 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 24 Mar 2023 13:30:14 -0300 Subject: [PATCH 209/235] =?UTF-8?q?fix:=20mostrar=20los=20metodos=20fallid?= =?UTF-8?q?os=20en=20el=20correo=20de=20notificaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no salían porque la tabla se genera en base a expandir las urls y cuando las urls venían vacías no se generaba la fila. --- app/jobs/deploy_job.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 530b69dd..aeb0f4b6 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -44,7 +44,8 @@ class DeployJob < ApplicationJob status = false seconds ||= 0 size ||= 0 - urls ||= [] + # XXX: Hace que se vea la tabla + urls ||= [nil] notify_exception e, d end From da192ef14cf43ac136d22a9601073f3bd6f23682 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 24 Mar 2023 14:23:34 -0300 Subject: [PATCH 210/235] =?UTF-8?q?fix:=20sincronizar=20aunque=20algunos?= =?UTF-8?q?=20destinos=20todav=C3=ADa=20no=20existan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit por ejemplo la dependencia en hidden service hace que no se sincronice el sitio principal. --- app/models/deploy_full_rsync.rb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb index 5bdfeeff..a3c1840d 100644 --- a/app/models/deploy_full_rsync.rb +++ b/app/models/deploy_full_rsync.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class DeployFullRsync < DeployRsync - DEPENDENCIES = %i[ + SOFT_DEPENDENCIES = %i[ deploy_alternative_domain deploy_hidden_service deploy_local @@ -9,16 +9,24 @@ class DeployFullRsync < DeployRsync deploy_zip ] - # Sincroniza las ubicaciones alternativas también + # Sincroniza las ubicaciones alternativas también, ignorando las que + # todavía no se generaron. Solo falla si ningún sitio fue + # sincronizado o si alguna sincronización falló. # # @param :output [Boolean] # @return [Boolean] def rsync(output: false) - DEPENDENCIES.map(&:to_s).map(&:classify).map do |dependency| - site.deploys.where(type: dependency).find_each.map do |deploy| - run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape deploy.destination} #{Shellwords.escape destination}), output: output - end - end.flatten.all? + result = + SOFT_DEPENDENCIES.map(&:to_s).map(&:classify).map do |dependency| + site.deploys.where(type: dependency).find_each.map do |deploy| + next unless File.exist? deploy.destination + + run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape deploy.destination} #{Shellwords.escape destination}), output: output + rescue StandardError + end + end.flatten.compact + + result.present? && result.all? end def url From 57542c92a7fcf1548e93e87b0162e19497507037 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:08:19 -0300 Subject: [PATCH 211/235] fix: typo --- app/models/deploy_local.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index d6dc6c28..5b48df29 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -123,15 +123,15 @@ class DeployLocal < Deploy run 'yarn install --production', output: output end - def bundle(output: false) - run %(bundle install --no-cache --path="#{gems_dir}" --clean --without test development), output: output - end - - def pnpm + def pnpm(output: false) return true unless pnpm_lock? - run %(pnpm config set store-dir "#{pnpm_cache_dir}") - run 'pnpm install --production' + run %(pnpm config set store-dir "#{pnpm_cache_dir}"), output: output + run 'pnpm install --production', output: output + end + + def bundle(output: false) + run %(bundle install --no-cache --path="#{gems_dir}" --clean --without test development), output: output end def jekyll_build(output: false) From 42c7e93ac96cff1681047cb9bfc9f4c5f9353945 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:09:16 -0300 Subject: [PATCH 212/235] =?UTF-8?q?fix:=20crear=20un=20registro=20para=20w?= =?UTF-8?q?ww=20tambi=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 679da09d..f26a72b5 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -136,6 +136,7 @@ class DeployDistributedPress < Deploy self.remote_info ||= {} self.remote_info['njalla'] = {} self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['cname'] = njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end rescue HTTParty::Error => e From bef171d3ace090d2afcca7be5ea7be91930baf26 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:10:35 -0300 Subject: [PATCH 213/235] fix: intentar crear siempre los registros en njalla --- app/models/deploy_distributed_press.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index f26a72b5..a2e2e20a 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -30,7 +30,7 @@ class DeployDistributedPress < Deploy time_start create_remote_site! if remote_site_id.blank? - create_njalla_records! if remote_info['njalla'].blank? + create_njalla_records! save if remote_site_id.blank? || remote_info['njalla'].blank? @@ -134,10 +134,10 @@ class DeployDistributedPress < Deploy # que eliminarlo. unless site.name.end_with? '.' self.remote_info ||= {} - self.remote_info['njalla'] = {} - self.remote_info['njalla']['a'] = njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['cname'] = njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['ns'] = njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + self.remote_info['njalla'] ||= {} + self.remote_info['njalla']['a'] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['cname'] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h end rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) From c774337fd325b421fd53c3873b6c9ae0aaef6582 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:43:01 -0300 Subject: [PATCH 214/235] feat: sincronizar dominios por idioma --- app/models/deploy_full_rsync.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb index a3c1840d..7bc0e788 100644 --- a/app/models/deploy_full_rsync.rb +++ b/app/models/deploy_full_rsync.rb @@ -3,6 +3,7 @@ class DeployFullRsync < DeployRsync SOFT_DEPENDENCIES = %i[ deploy_alternative_domain + deploy_localized_domain deploy_hidden_service deploy_local deploy_www From b2c6d40b0f0dbdb7ff26b763db8865b24c4294b0 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:44:22 -0300 Subject: [PATCH 215/235] fix: deprecar DeployLocal#extra_env --- app/models/deploy.rb | 1 + app/models/deploy_local.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 52031d87..33dc9f2b 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -13,6 +13,7 @@ class Deploy < ApplicationRecord has_many :build_stats, dependent: :destroy DEPENDENCIES = [] + SOFT_DEPENDENCIES = [] def deploy(**) raise NotImplementedError diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 5b48df29..d1d93fe5 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -152,6 +152,7 @@ class DeployLocal < Deploy # Consigue todas las variables de entorno configuradas por otros # deploys. # + # @deprecated Solo tenía sentido para Distributed Press v0 # @return [Hash] def extra_env @extra_env ||= From ad0d7aac10736cc375a069e5172454c38950699a Mon Sep 17 00:00:00 2001 From: f Date: Mon, 27 Mar 2023 14:52:37 -0300 Subject: [PATCH 216/235] feat: tener en cuenta las dependencias suaves al armar el grafo --- app/models/deploy.rb | 7 +++++++ app/models/deploy_full_rsync.rb | 4 +--- app/models/site/deploy_dependencies.rb | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 33dc9f2b..a92708c0 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -100,6 +100,13 @@ class Deploy < ApplicationRecord @local_env ||= {} end + # Trae todas las dependencias + # + # @return [Array] + def self.all_dependencies + self::DEPENDENCIES | self::SOFT_DEPENDENCIES + end + private # @param [String] diff --git a/app/models/deploy_full_rsync.rb b/app/models/deploy_full_rsync.rb index 7bc0e788..b8c48eab 100644 --- a/app/models/deploy_full_rsync.rb +++ b/app/models/deploy_full_rsync.rb @@ -5,9 +5,7 @@ class DeployFullRsync < DeployRsync deploy_alternative_domain deploy_localized_domain deploy_hidden_service - deploy_local deploy_www - deploy_zip ] # Sincroniza las ubicaciones alternativas también, ignorando las que @@ -18,7 +16,7 @@ class DeployFullRsync < DeployRsync # @return [Boolean] def rsync(output: false) result = - SOFT_DEPENDENCIES.map(&:to_s).map(&:classify).map do |dependency| + self.class.all_dependencies.map(&:to_s).map(&:classify).map do |dependency| site.deploys.where(type: dependency).find_each.map do |deploy| next unless File.exist? deploy.destination diff --git a/app/models/site/deploy_dependencies.rb b/app/models/site/deploy_dependencies.rb index a01f99e7..ed80a8af 100644 --- a/app/models/site/deploy_dependencies.rb +++ b/app/models/site/deploy_dependencies.rb @@ -18,7 +18,7 @@ class Site end deploys.each do |deploy| - deploy.class::DEPENDENCIES.each do |dependency| + deploy.class.all_dependencies.each do |dependency| deploys.where(type: dependency.to_s.classify).each do |deploy_dependency| graph.add_edge deploy_dependency, deploy end From bee16538301b11a5b8c0bc3645ebe59a09816968 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 14:45:49 -0300 Subject: [PATCH 217/235] =?UTF-8?q?fix:=20evitar=20m=C3=A9todos=20de=20pub?= =?UTF-8?q?licaci=C3=B3n=20duplicados=20#12276?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/sites_controller.rb | 2 -- app/services/site_service.rb | 1 + app/views/sites/_form.haml | 3 --- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index f0eff0dc..8d49fd8a 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -28,8 +28,6 @@ class SitesController < ApplicationController @site = Site.new authorize @site - - @site.deploys.build type: 'DeployLocal' end def create diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 0ecccba4..bb76c6ac 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -14,6 +14,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do self.site = Site.new params add_role temporal: false, rol: 'usuarie' + site.deploys.build type: 'DeployLocal' sync_nodes I18n.with_locale(usuarie.lang.to_sym || I18n.default_locale) do diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index 757b8b48..48e30e0c 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -158,9 +158,6 @@ = f.fields_for :deploys do |deploy| = render "deploys/#{deploy.object.type.underscore}", deploy: deploy, site: site - - else - = f.fields_for :deploys do |deploy| - = deploy.hidden_field :type .form-group = f.submit submit, class: 'btn btn-lg btn-block' From 95198832c4791134df2c8f11fd682219e4684780 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 30 Mar 2023 14:53:34 -0300 Subject: [PATCH 218/235] feat: configurar la fuente de gemas del skel desde el panel --- app/models/deploy_local.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index d1d93fe5..39cd9622 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -84,7 +84,8 @@ class DeployLocal < Deploy 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, 'JEKYLL_ENV' => Rails.env, 'LANG' => ENV['LANG'], - 'YARN_CACHE_FOLDER' => yarn_cache_dir + 'YARN_CACHE_FOLDER' => yarn_cache_dir, + 'GEMS_SOURCE' => ENV['GEMS_SOURCE'] }) end From b759398a4ee15beaa52972840dfc29ac27557a55 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 12:01:00 -0300 Subject: [PATCH 219/235] =?UTF-8?q?BREAKING=20CHANGE:=20usar=20la=20=C3=BA?= =?UTF-8?q?ltima=20instancia=20de=20Distributed=20Press?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index a2e2e20a..64c66cfc 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -88,7 +88,7 @@ class DeployDistributedPress < Deploy # # @return [DistributedPressPublisher] def publisher - @publisher ||= DistributedPressPublisher.first + @publisher ||= DistributedPressPublisher.last end # El cliente para actualizar el sitio From b818408f3e7f5b2c9a4a0983e26102af9e428073 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 12:14:14 -0300 Subject: [PATCH 220/235] feat: indicarle a distributed press que elimine el sitio sutty/distributed-press-api-client#10 --- Gemfile | 2 +- Gemfile.lock | 2 +- app/models/deploy_distributed_press.rb | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 9d1b6d67..2ff1c68c 100644 --- a/Gemfile +++ b/Gemfile @@ -39,7 +39,7 @@ gem 'commonmarker' gem 'devise' gem 'devise-i18n' gem 'devise_invitable' -gem 'distributed-press-api-client', '~> 0.2.2' +gem 'distributed-press-api-client', '~> 0.2.3' gem 'njalla-api-client' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' diff --git a/Gemfile.lock b/Gemfile.lock index c2c29531..30619795 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -622,7 +622,7 @@ DEPENDENCIES devise devise-i18n devise_invitable - distributed-press-api-client (~> 0.2.2) + distributed-press-api-client (~> 0.2.3) dotenv-rails down ed25519 diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 64c66cfc..ca10218a 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -16,6 +16,7 @@ class DeployDistributedPress < Deploy store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON before_create :create_remote_site!, :create_njalla_records! + before_destroy :delete_remote_site! DEPENDENCIES = %i[deploy_local] @@ -120,9 +121,9 @@ class DeployDistributedPress < Deploy self.remote_site_id = created_site[:id] self.remote_info = created_site.to_h + nil rescue DistributedPress::V1::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) - ensure nil end @@ -156,6 +157,14 @@ class DeployDistributedPress < Deploy nil end + def delete_remote_site! + site_client.delete(publishing_site) + nil + rescue DistributedPress::V1::Error => e + ExceptionNotifier.notify_exception(e, data: { site: site.name }) + nil + end + # Actualizar registros en Njalla # # @return [Njalla::V1::Domain] From f6a08f1073c834d2201b7cbcb5d067fa28140cd7 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 13:35:42 -0300 Subject: [PATCH 221/235] feat: eliminar registros en njalla --- Gemfile | 2 +- Gemfile.lock | 2 +- app/models/deploy_distributed_press.rb | 10 +++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 2ff1c68c..b2472035 100644 --- a/Gemfile +++ b/Gemfile @@ -40,7 +40,7 @@ gem 'devise' gem 'devise-i18n' gem 'devise_invitable' gem 'distributed-press-api-client', '~> 0.2.3' -gem 'njalla-api-client' +gem 'njalla-api-client', '~> 0.2.0' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 30619795..67ce13e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -387,7 +387,7 @@ GEM nokogiri (1.12.5-x86_64-linux-musl) mini_portile2 (~> 2.6.1) racc (~> 1.4) - njalla-api-client (0.1.0) + njalla-api-client (0.2.0) dry-schema httparty (~> 0.18) orm_adapter (0.5.0) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index ca10218a..9f78ba28 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -16,7 +16,7 @@ class DeployDistributedPress < Deploy store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON before_create :create_remote_site!, :create_njalla_records! - before_destroy :delete_remote_site! + before_destroy :delete_remote_site!, :delete_njalla_records! DEPENDENCIES = %i[deploy_local] @@ -165,6 +165,14 @@ class DeployDistributedPress < Deploy nil end + def delete_njalla_records! + %w[a ns cname].each do |type| + next if (id = remote_info.dig('njalla', type, 'id')).blank? + + njalla.remove_record(id: id.to_i) + end + end + # Actualizar registros en Njalla # # @return [Njalla::V1::Domain] From d2e4fe09646e7b337868bf6711e2a3e5062a426b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 13:58:10 -0300 Subject: [PATCH 222/235] fix: los registros en njalla no siempre son necesarios --- app/models/deploy_distributed_press.rb | 36 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 9f78ba28..b77dfe19 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -34,8 +34,12 @@ class DeployDistributedPress < Deploy create_njalla_records! save - if remote_site_id.blank? || remote_info['njalla'].blank? - raise DeployJob::DeployException, '' + if remote_site_id.blank? + raise DeployJob::DeployException, 'El sitio no se creó en Distributed Press' + end + + if create_njalla_records? && remote_info['njalla'].blank? + raise DeployJob::DeployException, 'No se pudieron crear los registros necesarios en Njalla' end site_client.tap do |c| @@ -129,17 +133,20 @@ class DeployDistributedPress < Deploy # Crea los registros en Njalla # + # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay + # que eliminarlo. + # # @return [nil] def create_njalla_records! - # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay - # que eliminarlo. - unless site.name.end_with? '.' - self.remote_info ||= {} - self.remote_info['njalla'] ||= {} - self.remote_info['njalla']['a'] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['cname'] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['ns'] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h - end + return unless create_njalla_records? + + self.remote_info ||= {} + self.remote_info['njalla'] ||= {} + self.remote_info['njalla']['a'] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['cname'] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info['njalla']['ns'] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + + nil rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) self.remote_info['njalla'] = nil @@ -166,6 +173,8 @@ class DeployDistributedPress < Deploy end def delete_njalla_records! + return unless create_njalla_records? + %w[a ns cname].each do |type| next if (id = remote_info.dig('njalla', type, 'id')).blank? @@ -184,4 +193,9 @@ class DeployDistributedPress < Deploy Njalla::V1::Domain.new(domain: Site.domain, client: client) end end + + # Detecta si tenemos que crear registros en Njalla + def create_njalla_records? + !site.name.end_with?('.') + end end From 943bf7b5bdafd2080736d8cdf4774ee6632d5b91 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 14:38:04 -0300 Subject: [PATCH 223/235] fix: no pisar las datos de njalla con los de distributed press --- app/models/deploy_distributed_press.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index b77dfe19..081ceeb5 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -38,7 +38,7 @@ class DeployDistributedPress < Deploy raise DeployJob::DeployException, 'El sitio no se creó en Distributed Press' end - if create_njalla_records? && remote_info['njalla'].blank? + if create_njalla_records? && remote_info[:njalla].blank? raise DeployJob::DeployException, 'No se pudieron crear los registros necesarios en Njalla' end @@ -52,7 +52,8 @@ class DeployDistributedPress < Deploy end end - update remote_info: c.show(publishing_site).to_h + self.remote_info[:distributed_press] = c.show(publishing_site).to_h + save status = c.publish(publishing_site, deploy_local.destination) @@ -77,7 +78,7 @@ class DeployDistributedPress < Deploy # Devuelve las URLs de todos los protocolos def urls - remote_info[:links].values.map do |protocol| + remote_info.dig(:distributed_press, :links).values.map do |protocol| [ protocol[:link], protocol[:gateway] ] end.flatten.compact.select do |link| link.include? '://' @@ -124,7 +125,8 @@ class DeployDistributedPress < Deploy created_site = site_client.create(create_site) self.remote_site_id = created_site[:id] - self.remote_info = created_site.to_h + self.remote_info ||= {} + self.remote_info[:distributed_press] = created_site.to_h nil rescue DistributedPress::V1::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) @@ -141,15 +143,15 @@ class DeployDistributedPress < Deploy return unless create_njalla_records? self.remote_info ||= {} - self.remote_info['njalla'] ||= {} - self.remote_info['njalla']['a'] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['cname'] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info['njalla']['ns'] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h + self.remote_info[:njalla] ||= {} + self.remote_info[:njalla][:a] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info[:njalla][:cname] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h + self.remote_info[:njalla][:ns] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h nil rescue HTTParty::Error => e ExceptionNotifier.notify_exception(e, data: { site: site.name }) - self.remote_info['njalla'] = nil + self.remote_info.delete :njalla ensure nil end From a56acfd6da2aec2c3e5b913c91bae4de229be5ec Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 14:44:48 -0300 Subject: [PATCH 224/235] =?UTF-8?q?fix:=20obtener=20los=20links=20luego=20?= =?UTF-8?q?de=20la=20publicaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_distributed_press.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 081ceeb5..d8fd3f61 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -52,11 +52,13 @@ class DeployDistributedPress < Deploy end end - self.remote_info[:distributed_press] = c.show(publishing_site).to_h - save - status = c.publish(publishing_site, deploy_local.destination) + if status + self.remote_info[:distributed_press] = c.show(publishing_site).to_h + save + end + publisher.logger.close stdout.join end From ab126038afe4a9352c82002d58687bb5074142bf Mon Sep 17 00:00:00 2001 From: f Date: Fri, 31 Mar 2023 14:49:17 -0300 Subject: [PATCH 225/235] feat: devolver las urls con protocolos --- app/models/deploy_distributed_press.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index d8fd3f61..32a3049e 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -80,6 +80,12 @@ class DeployDistributedPress < Deploy # Devuelve las URLs de todos los protocolos def urls + protocol_urls + gateway_urls + end + + private + + def gateway_urls remote_info.dig(:distributed_press, :links).values.map do |protocol| [ protocol[:link], protocol[:gateway] ] end.flatten.compact.select do |link| @@ -87,7 +93,13 @@ class DeployDistributedPress < Deploy end end - private + def protocol_urls + remote_info.dig(:distributed_press, :protocols).select do |_, enabled| + enabled + end.map do |protocol, _| + "#{protocol}://#{site.hostname}" + end + end # El cliente de la API # From 87d51e88562faf61eb81a3a3833a2799813d86a0 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 17:31:35 -0300 Subject: [PATCH 226/235] feat: pedir consentimiento #12795 --- app/views/bootstrap/_custom_checkbox.haml | 6 ++++++ app/views/devise/registrations/new.haml | 18 +++++++++++++++++- config/locales/devise.views.en.yml | 19 +++++++++++++++++++ config/locales/devise.views.es.yml | 18 ++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/views/bootstrap/_custom_checkbox.haml diff --git a/app/views/bootstrap/_custom_checkbox.haml b/app/views/bootstrap/_custom_checkbox.haml new file mode 100644 index 00000000..0c3ff3a6 --- /dev/null +++ b/app/views/bootstrap/_custom_checkbox.haml @@ -0,0 +1,6 @@ +- help_id = "#{id}_help" + +.custom-control.custom-checkbox + %input.custom-control-input{ id: id, type: 'checkbox', name: name, value: value, required: required } + %label.custom-control-label{ for: id, aria: { describedby: help_id } }= content + %small.form-text.text-muted{ id: help_id }= yield diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml index e6bda964..75015831 100644 --- a/app/views/devise/registrations/new.haml +++ b/app/views/devise/registrations/new.haml @@ -4,7 +4,7 @@ = render 'devise/shared/error_messages', resource: resource .row.align-items-center.justify-content-center.full-height - .col-md-5.align-self-center + .col-md-6.align-self-center %h2= t('.sign_up') %p= t('.help') @@ -39,6 +39,22 @@ min: @minimum_password_length, aria: { describedby: 'minimum-password-length' }, placeholder: t("#{password}_confirmation") + + - if params[:consent] + .form-group + - %i[privacy_policy_accepted terms_of_service_accepted code_of_conduct_accepted available_for_feedback_accepted].each do |field| + - required = t(".#{field}.required", default: '').present? + - id = "usuarie_#{field}" + - name = "usuarie[#{field}]" + - content = t(".#{field}.label") + - href = t(".#{field}.href", default: '') + - help_content = t(".#{field}.help") + = render 'bootstrap/custom_checkbox', id: id, name: name, content: content, required: required, value: "1" do + - if href.present? + = link_to help_content, href, target: '_blank', rel: 'noopener' + - else + = help_content + .actions = f.submit t('.sign_up'), class: 'btn btn-lg btn-block' diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index 793f3a0a..3dd666b1 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -104,6 +104,25 @@ en: new: sign_up: Sign up help: We only ask for an e-mail address and a password. The password is safely stored, no one else besides you knows it! You'll also receive an e-mail to confirm your account. + privacy_policy_accepted: + label: "I know about Sutty's privacy policy" + help: "Read privacy policy" + href: "https://sutty.nl/en/privacy-policy/" + required: true + terms_of_service_accepted: + label: "My sites won't promote hate towards minorities" + help: "Read terms of service" + href: "https://sutty.nl/en/terms-of-service/" + required: true + code_of_conduct_accepted: + label: "My sites are inclusive spaces" + help: "Read codes for sharing" + href: "https://sutty.nl/en/code-of-conduct/" + required: true + available_for_feedback_accepted: + label: "I'm available to provide feedback" + help: "We may contact you occasionaly" + required: false signed_up: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." signed_up_but_inactive: You have signed up successfully. However, we could not sign you in because your account is not yet activated. signed_up_but_locked: You have signed up successfully. However, we could not sign you in because your account is locked. diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index b745fc5f..c955373f 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -104,6 +104,24 @@ es: new: sign_up: Registrarme help: Para registrarte solo pedimos una dirección de correo y una contraseña. La contraseña se almacena de forma segura, ¡nadie más que vos la sabe! Recibirás un correo de confirmación de cuenta. + privacy_policy_accepted: + label: "Conozco la política de privacidad de Sutty" + help: "Leer política de privacidad" + href: "https://sutty.nl/politica-de-privacidad/" + required: "true" + terms_of_service_accepted: + label: "Mis sitios no promueven el odio a minorías" + help: "Leer términos de servicio" + href: "https://sutty.nl/terminos-de-servicio/" + required: "true" + code_of_conduct_accepted: + label: "Mis sitios son espacios inclusivos" + help: "Leer códigos para compartir" + href: "https://sutty.nl/codigo-de-convivencia/" + required: "true" + available_for_feedback_accepted: + label: "Estoy disponible para ofrecer retroalimentación" + help: "Te contactaremos ocasionalmente" signed_up: "Hemos enviado un mensaje con un enlace de confirmación a tu correo electrónico. Por favor, abrí el enlace para terminar de activar tu cuenta." signed_up_but_inactive: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque tu cuenta aún no está activada. signed_up_but_locked: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque que tu cuenta está bloqueada. From 8f0f260a4f9bd345eddcf66ab079da054d9d2a00 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 18:18:53 -0300 Subject: [PATCH 227/235] feat: almacenar los campos --- app/models/concerns/usuarie/consent.rb | 26 +++++++++++++++++++ app/models/usuarie.rb | 2 ++ app/views/devise/registrations/new.haml | 2 +- .../20230328200129_add_consent_to_usuaries.rb | 12 +++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 app/models/concerns/usuarie/consent.rb create mode 100644 db/migrate/20230328200129_add_consent_to_usuaries.rb diff --git a/app/models/concerns/usuarie/consent.rb b/app/models/concerns/usuarie/consent.rb new file mode 100644 index 00000000..14e67fbc --- /dev/null +++ b/app/models/concerns/usuarie/consent.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class Usuarie + # Gestiona los campos de consentimiento + module Consent + extend ActiveSupport::Concern + + included do + CONSENT_FIELDS = %i[privacy_policy_accepted terms_of_service_accepted code_of_conduct_accepted available_for_feedback_accepted] + + CONSENT_FIELDS.each do |field| + attribute field, :boolean + end + + before_save :update_consent_fields! + + private + + def update_consent_fields! + CONSENT_FIELDS.each do |field| + send(:"#{field}_at=", Time.now) if send(field).present? + end + end + end + end +end diff --git a/app/models/usuarie.rb b/app/models/usuarie.rb index 7b83ee75..9b9fd4e6 100644 --- a/app/models/usuarie.rb +++ b/app/models/usuarie.rb @@ -2,6 +2,8 @@ # Usuarie de la plataforma class Usuarie < ApplicationRecord + include Usuarie::Consent + devise :invitable, :database_authenticatable, :recoverable, :rememberable, :validatable, :confirmable, :lockable, :registerable diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml index 75015831..04e81917 100644 --- a/app/views/devise/registrations/new.haml +++ b/app/views/devise/registrations/new.haml @@ -42,7 +42,7 @@ - if params[:consent] .form-group - - %i[privacy_policy_accepted terms_of_service_accepted code_of_conduct_accepted available_for_feedback_accepted].each do |field| + - Usuarie::CONSENT_FIELDS.each do |field| - required = t(".#{field}.required", default: '').present? - id = "usuarie_#{field}" - name = "usuarie[#{field}]" diff --git a/db/migrate/20230328200129_add_consent_to_usuaries.rb b/db/migrate/20230328200129_add_consent_to_usuaries.rb new file mode 100644 index 00000000..1e85864d --- /dev/null +++ b/db/migrate/20230328200129_add_consent_to_usuaries.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Agrega consentimientos a les usuaries. No usamos un loop de +# Usuarie::CONSENT_FIELDS porque quizás agreguemos campos luego. +class AddConsentToUsuaries < ActiveRecord::Migration[6.1] + def change + add_column :usuaries, :privacy_policy_accepted_at, :datetime + add_column :usuaries, :terms_of_service_accepted_at, :datetime + add_column :usuaries, :code_of_conduct_accepted_at, :datetime + add_column :usuaries, :available_for_feedback_accepted_at, :datetime + end +end From 492d238f579b02f6a0ffdbe78e71f4b00c554ae8 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 18:33:19 -0300 Subject: [PATCH 228/235] =?UTF-8?q?BREAKING=20CHANGE:=20eliminar=20campo?= =?UTF-8?q?=20que=20no=20se=20us=C3=B3=20nunca?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...remove_acepta_politicas_de_privacidad_from_usuaries.rb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 db/migrate/20230328213242_remove_acepta_politicas_de_privacidad_from_usuaries.rb diff --git a/db/migrate/20230328213242_remove_acepta_politicas_de_privacidad_from_usuaries.rb b/db/migrate/20230328213242_remove_acepta_politicas_de_privacidad_from_usuaries.rb new file mode 100644 index 00000000..7ca562bf --- /dev/null +++ b/db/migrate/20230328213242_remove_acepta_politicas_de_privacidad_from_usuaries.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Elimina un campo que nunca se usó +class RemoveAceptaPoliticasDePrivacidadFromUsuaries < ActiveRecord::Migration[6.1] + def change + remove_column :usuaries, :acepta_politicas_de_privacidad, :boolean, default: false + end +end From c66d1f0f087310085da99f8e76fb7389d783cbdc Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 15:50:45 -0300 Subject: [PATCH 229/235] =?UTF-8?q?fix:=20mejorar=20la=20redacci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/devise.views.en.yml | 6 +++--- config/locales/devise.views.es.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/locales/devise.views.en.yml b/config/locales/devise.views.en.yml index 3dd666b1..a524cf7c 100644 --- a/config/locales/devise.views.en.yml +++ b/config/locales/devise.views.en.yml @@ -105,17 +105,17 @@ en: sign_up: Sign up help: We only ask for an e-mail address and a password. The password is safely stored, no one else besides you knows it! You'll also receive an e-mail to confirm your account. privacy_policy_accepted: - label: "I know about Sutty's privacy policy" + label: "I understand and accept the privacy policy" help: "Read privacy policy" href: "https://sutty.nl/en/privacy-policy/" required: true terms_of_service_accepted: - label: "My sites won't promote hate towards minorities" + label: "My sites won't promote hate speech" help: "Read terms of service" href: "https://sutty.nl/en/terms-of-service/" required: true code_of_conduct_accepted: - label: "My sites are inclusive spaces" + label: "I want a more inclusive Internet" help: "Read codes for sharing" href: "https://sutty.nl/en/code-of-conduct/" required: true diff --git a/config/locales/devise.views.es.yml b/config/locales/devise.views.es.yml index c955373f..4575c628 100644 --- a/config/locales/devise.views.es.yml +++ b/config/locales/devise.views.es.yml @@ -105,17 +105,17 @@ es: sign_up: Registrarme help: Para registrarte solo pedimos una dirección de correo y una contraseña. La contraseña se almacena de forma segura, ¡nadie más que vos la sabe! Recibirás un correo de confirmación de cuenta. privacy_policy_accepted: - label: "Conozco la política de privacidad de Sutty" + label: "Comprendo y acepto la política de privacidad" help: "Leer política de privacidad" href: "https://sutty.nl/politica-de-privacidad/" required: "true" terms_of_service_accepted: - label: "Mis sitios no promueven el odio a minorías" + label: "Mis sitios no promueven el discurso de odio" help: "Leer términos de servicio" href: "https://sutty.nl/terminos-de-servicio/" required: "true" code_of_conduct_accepted: - label: "Mis sitios son espacios inclusivos" + label: "Quiero una Internet más inclusiva" help: "Leer códigos para compartir" href: "https://sutty.nl/codigo-de-convivencia/" required: "true" From 414fd7348d7b5b3d9801ee7f8068c193b12d3df8 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 29 Mar 2023 15:51:10 -0300 Subject: [PATCH 230/235] fix: activarlo --- app/views/devise/registrations/new.haml | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml index 04e81917..26fc8e18 100644 --- a/app/views/devise/registrations/new.haml +++ b/app/views/devise/registrations/new.haml @@ -40,20 +40,19 @@ aria: { describedby: 'minimum-password-length' }, placeholder: t("#{password}_confirmation") - - if params[:consent] - .form-group - - Usuarie::CONSENT_FIELDS.each do |field| - - required = t(".#{field}.required", default: '').present? - - id = "usuarie_#{field}" - - name = "usuarie[#{field}]" - - content = t(".#{field}.label") - - href = t(".#{field}.href", default: '') - - help_content = t(".#{field}.help") - = render 'bootstrap/custom_checkbox', id: id, name: name, content: content, required: required, value: "1" do - - if href.present? - = link_to help_content, href, target: '_blank', rel: 'noopener' - - else - = help_content + .form-group + - Usuarie::CONSENT_FIELDS.each do |field| + - required = t(".#{field}.required", default: '').present? + - id = "usuarie_#{field}" + - name = "usuarie[#{field}]" + - content = t(".#{field}.label") + - href = t(".#{field}.href", default: '') + - help_content = t(".#{field}.help") + = render 'bootstrap/custom_checkbox', id: id, name: name, content: content, required: required, value: "1" do + - if href.present? + = link_to help_content, href, target: '_blank', rel: 'noopener' + - else + = help_content .actions = f.submit t('.sign_up'), From 252652c94b2bff95ad0304422b73d7c19a6efa13 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 15 Mar 2022 16:03:16 -0300 Subject: [PATCH 231/235] poder ver la salida si lo ejecutamos desde la terminal --- app/models/deploy_local.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 71c23b36..bfde29f7 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -117,14 +117,6 @@ class DeployLocal < Deploy run %(gem install bundler --no-document), output: output end - def pnpm_lock - File.join(site.path, 'pnpm-lock.yaml') - end - - def pnpm_lock? - File.exist? pnpm_lock - end - # Corre yarn dentro del repositorio def yarn(output: false) return true unless yarn_lock? From 718463f0eae2255e7cb33cddb72a6ab4364b6405 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 15:28:46 -0300 Subject: [PATCH 232/235] feat: generar direcciones tor a demanda #12773 --- app/lib/hidden_service_client.rb | 13 +++++++++++++ app/models/deploy_hidden_service.rb | 21 ++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 app/lib/hidden_service_client.rb diff --git a/app/lib/hidden_service_client.rb b/app/lib/hidden_service_client.rb new file mode 100644 index 00000000..5715a869 --- /dev/null +++ b/app/lib/hidden_service_client.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'httparty' + +class HiddenServiceClient + include HTTParty + + base_uri ENV.fetch('HIDDEN_SERVICE', 'http://tor:3000') + + def create(name) + self.class.get("/#{name}").body + end +end diff --git a/app/models/deploy_hidden_service.rb b/app/models/deploy_hidden_service.rb index 79ff1bae..aa495baf 100644 --- a/app/models/deploy_hidden_service.rb +++ b/app/models/deploy_hidden_service.rb @@ -2,8 +2,12 @@ # Genera una versión onion class DeployHiddenService < DeployWww + store :values, accessors: %i[onion], coder: JSON + + before_create :create_hidden_service! + def fqdn - values[:onion].tap do |onion| + onion.tap do |onion| raise ArgumentError, 'Aun no se generó la dirección .onion' if onion.blank? end end @@ -11,4 +15,19 @@ class DeployHiddenService < DeployWww def url "http://#{fqdn}" end + + private + + def create_hidden_service! + onion_address = HiddenServiceClient.new.create(site.name) + + if ONION_RE =~ onion_address + self.onion = onion_address + + usuarie = GitAuthor.new email: "tor@#{Site.domain}", name: 'Tor' + params = { onion: onion_address, deploy: self } + + SiteService.new(site: site, usuarie: usuarie, params: params).add_onion + end + end end From 487765f7d88356b4d33242ca95c4487bb6488917 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 16:21:29 -0300 Subject: [PATCH 233/235] =?UTF-8?q?feat:=20validar=20y=20agregar=20la=20di?= =?UTF-8?q?recci=C3=B3n=20a=20la=20configuraci=C3=B3n=20del=20sitio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_hidden_service.rb | 2 ++ app/services/site_service.rb | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/models/deploy_hidden_service.rb b/app/models/deploy_hidden_service.rb index aa495baf..3356e815 100644 --- a/app/models/deploy_hidden_service.rb +++ b/app/models/deploy_hidden_service.rb @@ -6,6 +6,8 @@ class DeployHiddenService < DeployWww before_create :create_hidden_service! + ONION_RE = /\A[a-z0-9]{56}\.onion\z/.freeze + def fqdn onion.tap do |onion| raise ArgumentError, 'Aun no se generó la dirección .onion' if onion.blank? diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 848f3cfc..8ecc3f56 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -64,14 +64,11 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # Agregar una dirección oculta de Tor al DeployHiddenService y a la # configuración del Site. def add_onion - onion = params[:onion].strip - deploy = DeployHiddenService.find_by(site: site) + onion = params[:onion] + deploy = params[:deploy] return false unless !onion.blank? && deploy - deploy.values[:onion] = onion - deploy.save - site.config['onion-location'] = onion site.config.write From 0002ed53a940f69da649ab3ebe4c1b90bb8c3433 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 16:22:02 -0300 Subject: [PATCH 234/235] BREAKING CHANGE: deprecar la api de onion --- app/controllers/api/v1/sites_controller.rb | 25 ---------------------- config/routes.rb | 2 -- 2 files changed, 27 deletions(-) diff --git a/app/controllers/api/v1/sites_controller.rb b/app/controllers/api/v1/sites_controller.rb index 10a92907..ae64cf74 100644 --- a/app/controllers/api/v1/sites_controller.rb +++ b/app/controllers/api/v1/sites_controller.rb @@ -12,31 +12,6 @@ module Api render json: sites_names + alternative_names + api_names + www_names end - # Sitios con hidden service de Tor - # - # @return [Array] lista de nombres de sitios sin onion aun - def hidden_services - render json: DeployHiddenService.where(values: nil).includes(:site).pluck(:name) - end - - # Tor va a enviar el onion junto con el nombre del sitio y tenemos - # que guardarlo en su deploy_hidden_service. - # - # @params [String] name - # @params [String] onion - def add_onion - site = Site.find_by(name: params[:name]) - - if site - usuarie = GitAuthor.new email: "tor@#{Site.domain}", name: 'Tor' - service = SiteService.new site: site, usuarie: usuarie, - params: params - service.add_onion - end - - head :ok - end - private def canonicalize(name) diff --git a/config/routes.rb b/config/routes.rb index a132135a..511ca654 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,8 +11,6 @@ Rails.application.routes.draw do namespace :v1 do resources :csp_reports, only: %i[create] - get :'sites/hidden_services', to: 'sites#hidden_services' - post :'sites/add_onion', to: 'sites#add_onion' resources :sites, only: %i[index], constraints: { site_id: /[a-z0-9\-.]+/, id: /[a-z0-9\-.]+/ } do get :'invitades/cookie', to: 'invitades#cookie' post :'posts/:layout', to: 'posts#create', as: :posts From 2f745886f5240a7b4f524155f505900ef54932fd Mon Sep 17 00:00:00 2001 From: f Date: Tue, 28 Mar 2023 16:22:58 -0300 Subject: [PATCH 235/235] =?UTF-8?q?fix:=20reintentar=20si=20fall=C3=B3=20l?= =?UTF-8?q?a=20generaci=C3=B3n=20en=20el=20pasado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_hidden_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/deploy_hidden_service.rb b/app/models/deploy_hidden_service.rb index 3356e815..25c0c217 100644 --- a/app/models/deploy_hidden_service.rb +++ b/app/models/deploy_hidden_service.rb @@ -9,6 +9,8 @@ class DeployHiddenService < DeployWww ONION_RE = /\A[a-z0-9]{56}\.onion\z/.freeze def fqdn + create_hidden_service! if onion.blank? + onion.tap do |onion| raise ArgumentError, 'Aun no se generó la dirección .onion' if onion.blank? end