From 39ffe9e926b2f2722d1e5bb83661ba65d3b77b66 Mon Sep 17 00:00:00 2001 From: Maki Date: Thu, 3 Jun 2021 16:09:26 -0300 Subject: [PATCH 001/146] edit_posts recuperado #1823 --- config/locales/es.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/locales/es.yml b/config/locales/es.yml index 1ce50b09..4361f790 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -180,6 +180,8 @@ es: category: 'Categoría' sites: index: 'Este es el listado de sitios que puedes editar.' + edit_posts: 'Aquí verás el listado de todos los artículos y podrás +- editarlos o crear nuevos' enqueued: 'El sitio está en la cola de espera para ser generado. Una vez que este proceso termine, recibirás un correo indicando el estado y si todo fue bien, se publicarán los cambios en tu sitio From a2669e0aa44a3bcd568535d937a143abe47b26ed Mon Sep 17 00:00:00 2001 From: f Date: Tue, 15 Jun 2021 17:07:52 -0300 Subject: [PATCH 002/146] =?UTF-8?q?actualizaci=C3=B3n=20de=20cuidados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 69 +++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 942d7d6f..e0c19860 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,11 +89,11 @@ GEM jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) ast (2.4.2) - autoprefixer-rails (10.2.5.0) - execjs (< 2.8.0) + autoprefixer-rails (10.2.5.1) + execjs (> 0) bcrypt (3.1.16-x86_64-linux-musl) bcrypt_pbkdf (1.1.0-x86_64-linux-musl) - benchmark-ips (2.8.4) + benchmark-ips (2.9.1) bindex (0.8.1-x86_64-linux-musl) blazer (2.4.2) activerecord (>= 5) @@ -104,7 +104,7 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) - brakeman (5.0.1) + brakeman (5.0.4) builder (3.2.4) capybara (2.18.0) addressable @@ -119,9 +119,9 @@ GEM colorator (1.1.0) commonmarker (0.21.2-x86_64-linux-musl) ruby-enum (~> 0.5) - concurrent-ruby (1.1.8) - concurrent-ruby-ext (1.1.8-x86_64-linux-musl) - concurrent-ruby (= 1.1.8) + concurrent-ruby (1.1.9) + concurrent-ruby-ext (1.1.9-x86_64-linux-musl) + concurrent-ruby (= 1.1.9) crass (1.0.6) database_cleaner (2.0.1) database_cleaner-active_record (~> 2.0.0) @@ -157,7 +157,7 @@ GEM dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - down (5.2.1) + down (5.2.2) addressable (~> 2.5) ed25519 (1.2.4-x86_64-linux-musl) editorial-autogestiva-jekyll-theme (0.3.4) @@ -188,7 +188,7 @@ GEM exception_notification (4.4.3) actionmailer (>= 4.0, < 7) activesupport (>= 4.0, < 7) - execjs (2.7.0) + execjs (2.8.1) factory_bot (6.2.0) activesupport (>= 5.0.0) factory_bot_rails (6.2.0) @@ -196,7 +196,7 @@ GEM railties (>= 5.0.0) fast_blank (1.0.0-x86_64-linux-musl) fast_jsonparser (0.5.0-x86_64-linux-musl) - ffi (1.15.0-x86_64-linux-musl) + ffi (1.15.1-x86_64-linux-musl) flamegraph (0.9.5) forwardable-extended (2.6.0) friendly_id (5.4.2) @@ -285,8 +285,6 @@ GEM jekyll-locales (0.1.12) jekyll-lunr (0.2.0) loofah (~> 2.4) - jekyll-node-modules (0.1.0) - jekyll (~> 4) jekyll-order (0.1.4) jekyll-relative-urls (0.0.6) jekyll (~> 4) @@ -328,7 +326,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.9.1) + loofah (2.10.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -343,7 +341,6 @@ GEM mini_histogram (0.3.1) mini_magick (4.11.0) mini_mime (1.0.3) - mini_portile2 (2.5.1) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) @@ -356,8 +353,7 @@ GEM net-ssh (6.1.0) netaddr (2.0.4) nio4r (2.5.7-x86_64-linux-musl) - nokogiri (1.11.5-x86_64-linux-musl) - mini_portile2 (~> 2.5.0) + nokogiri (1.11.7-x86_64-linux) racc (~> 1.4) orm_adapter (0.5.0) parallel (1.20.1) @@ -373,7 +369,7 @@ GEM coderay (~> 1.1) method_source (~> 1.0) public_suffix (4.0.6) - puma (5.3.1-x86_64-linux-musl) + puma (5.3.2-x86_64-linux-musl) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) @@ -383,11 +379,11 @@ GEM rack (>= 2.0.0) rack-mini-profiler (2.3.2) rack (>= 1.2.0) - rack-proxy (0.6.5) + rack-proxy (0.7.0) rack rack-test (1.1.0) rack (>= 1.0, < 3) - radios-comunitarias-jekyll-theme (0.1.4) + radios-comunitarias-jekyll-theme (0.1.5) jekyll (~> 4.0) jekyll-data (~> 1.1) jekyll-feed (~> 0.9) @@ -434,29 +430,30 @@ GEM rb-fsevent (0.11.0) rb-inotify (0.10.1) ffi (~> 1.0) - recursero-jekyll-theme (0.1.3) - jekyll (~> 4.0) + recursero-jekyll-theme (0.2.0) + jekyll (~> 4) + jekyll-commonmark (~> 1.3) jekyll-data (~> 1.1) - jekyll-feed (~> 0.9) + jekyll-dotenv (>= 0.2) + jekyll-feed (~> 0.15) + jekyll-ignore-layouts (~> 0) jekyll-images (~> 0.2) jekyll-include-cache (~> 0) - jekyll-linked-posts (~> 0.2) + jekyll-linked-posts (~> 0) jekyll-locales (~> 0.1) jekyll-lunr (~> 0.1) - jekyll-node-modules (~> 0.1) - jekyll-order (~> 0.1) - jekyll-relative-urls (~> 0.0) - jekyll-seo-tag (~> 2.1) - jekyll-turbolinks (~> 0) + jekyll-order (~> 0) + jekyll-relative-urls (~> 0) + jekyll-seo-tag (~> 2) jekyll-unique-urls (~> 0.1) sutty-archives (~> 2.2) - sutty-liquid (~> 0.1) - redis (4.2.5) + sutty-liquid (~> 0) + redis (4.3.1) redis-actionpack (5.2.0) actionpack (>= 5, < 7) redis-rack (>= 2.1.0, < 3) redis-store (>= 1.1.0, < 2) - redis-activesupport (5.2.0) + redis-activesupport (5.2.1) activesupport (>= 3, < 7) redis-store (>= 1.3, < 2) redis-rack (2.1.3) @@ -476,16 +473,16 @@ GEM railties (>= 5.0) rexml (3.2.5) rouge (3.26.0) - rubocop (1.15.0) + rubocop (1.17.0) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 1.5.0, < 2.0) + rubocop-ast (>= 1.7.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.5.0) + rubocop-ast (1.7.0) parser (>= 3.0.1.1) rubocop-rails (2.10.1) activesupport (>= 4.2.0) @@ -571,7 +568,7 @@ GEM jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - symbol-fstring (1.0.0-x86_64-linux-musl) + symbol-fstring (1.0.2-x86_64-linux-musl) sysexits (1.2.0) temple (0.8.2) terminal-table (2.0.0) @@ -606,7 +603,7 @@ GEM railties (>= 5.2) semantic_range (>= 2.3.0) webrick (1.7.0) - websocket-driver (0.7.3-x86_64-linux-musl) + websocket-driver (0.7.5-x86_64-linux-musl) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) From f19bfe153931d6100b7da2dfe70438e809f33bad Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 28 Jun 2021 10:18:20 -0300 Subject: [PATCH 003/146] una linea --- config/locales/es.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/locales/es.yml b/config/locales/es.yml index 4361f790..0d16f3f9 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -180,8 +180,7 @@ es: category: 'Categoría' sites: index: 'Este es el listado de sitios que puedes editar.' - edit_posts: 'Aquí verás el listado de todos los artículos y podrás -- editarlos o crear nuevos' + edit_posts: 'Aquí verás el listado de todos los artículos y podrás editarlos o crear nuevos' enqueued: 'El sitio está en la cola de espera para ser generado. Una vez que este proceso termine, recibirás un correo indicando el estado y si todo fue bien, se publicarán los cambios en tu sitio From 2ceeeff86c23dcdd32d2c05d3164c11c6e3712fe Mon Sep 17 00:00:00 2001 From: f Date: Sat, 10 Jul 2021 20:03:19 -0300 Subject: [PATCH 004/146] Mejorar el entorno de desarrollo fixes #1190 fixes #732 --- .env.example | 2 + Makefile | 180 +++++++++++++++++++++++++-------------------------- README.md | 21 ++++++ 3 files changed, 112 insertions(+), 91 deletions(-) diff --git a/.env.example b/.env.example index a1348593..a62e2b0a 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +DELEGATE=athshe.sutty.nl +HAINISH=../haini.sh/haini.sh DATABASE= RAILS_ENV= IMAP_SERVER= diff --git a/Makefile b/Makefile index c083ddf8..a4480476 100644 --- a/Makefile +++ b/Makefile @@ -1,134 +1,111 @@ -.SHELL := /bin/bash -# Incluir las variables de entorno -mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) -root_dir := $(patsubst %/,%,$(dir $(mkfile_path))) -include $(root_dir)/.env +SHELL := /bin/bash +.DEFAULT_GOAL := help -delegate := athshe +# Copiar el archivo de configuración y avisar cuando hay que +# actualizarlo. +.env: .env.example + @test -f $@ || cp -v $< $@ + @test -f $@ && echo "Revisa $@ para actualizarlo con respecto a $<" + @test -f $@ && diff -auN --color $@ $< -assets := package.json yarn.lock $(shell find app/assets/ app/javascript/ -type f) +include .env -alpine_version := 3.13 -hain ?= ../haini.sh/haini.sh +export -env ?= staging +args ?= ## Argumentos para Hain +commit ?= origin/rails ## Commit desde el que actualizar +env ?= staging ## Entorno del nodo delegado +sutty ?= $(SUTTY) ## Dirección local +delegate ?= $(DELEGATE) ## Cambia el nodo delegado +hain ?= $(HAINISH) ## Ubicación de Hainish +# El nodo delegado tiene dos entornos, production y staging. +# Dependiendo del entorno que elijamos, se van a generar los assets y el +# contenedor y subirse a un servidor u otro. No utilizamos CI/CD (aún). +# +# Production es el entorno de panel.sutty.nl ifeq ($(env),production) container ?= sutty +## TODO: Cambiar a otra cosa branch ?= rails public ?= public endif +# Staging es el entorno de panel.staging.sutty.nl ifeq ($(env),staging) container := staging branch := staging public := staging endif -export +help: always ## Ayuda + @echo -e "Sutty\n" | sed -re "s/^.*/\x1B[38;5;197m&\x1B[0m/" + @echo -e "Servidor: https://panel.$(SUTTY_WITH_PORT)/\n" + @echo -e "Uso: make TAREA args=\"ARGUMENTOS\"\n" + @echo -e "Tareas:\n" + @grep -E "^[a-z\-]+:.*##" Makefile | sed -re "s/(.*):.*##(.*)/\1;\2/" | column -s ";" -t | sed -re "s/^([^ ]+) /\x1B[38;5;197m\1\x1B[0m/" + @echo -e "\nArgumentos:\n" + @grep -E "^[a-z\-]+ \?=.*##" Makefile | sed -re "s/(.*) \?=.*##(.*)/\1;\2/" | column -s ";" -t | sed -re "s/^([^ ]+) /\x1B[38;5;197m\1\x1B[0m/" -public/packs/manifest.json.br: $(assets) - $(hain) 'cd /Sutty/sutty; PANEL_URL=https://panel.sutty.nl RAILS_ENV=production NODE_ENV=production bundle exec rake assets:precompile assets:clean' +assets: node_modules public/packs/manifest.json.br ## Compilar los assets -assets: public/packs/manifest.json.br +test: always ## Ejecutar los tests + $(MAKE) rake args="test RAILS_ENV=test $(args)" -tests := $(shell find test/ -name "*_test.rb") -$(tests): always - $(hain) 'cd /Sutty/sutty; bundle exec rake test TEST="$@" RAILS_ENV=test' - -test: always - $(hain) 'cd /Sutty/sutty; RAILS_ENV=test bundle exec rake test' - -postgresql: /etc/hosts +postgresql: /etc/hosts ## Iniciar la base de datos pgrep postgres >/dev/null || $(hain) postgresql -serve: /etc/hosts postgresql +serve-js: /etc/hosts node_modules ## Iniciar el servidor de desarrollo de Javascript + $(hain) 'bundle exec ./bin/webpack-dev-server' + +serve: /etc/hosts postgresql Gemfile.lock ## Iniciar el servidor de desarrollo de Rails $(MAKE) rails args=server -# make rails args="db:migrate" -rails: +rails: ## Tareas de Rails $(MAKE) bundle args="exec rails $(args)" -rake: +rake: ## Tareas de Rake $(MAKE) bundle args="exec rake $(args)" -bundle: - $(hain) 'cd /Sutty/sutty; bundle $(args)' +bundle: ## Tareas de bundler + $(hain) 'bundle $(args)' -yarn: +rubocop: ## Yutea el código que está por ser commiteado + git status --porcelain \ + | grep -E "^(A|M)" \ + | sed "s/^...//" \ + | grep ".rb$$" \ + | ../haini.sh/haini.sh "xargs -r ./bin/rubocop --auto-correct" + +audit: ## Encuentra dependencias con vulnerabilidades + $(hain) 'gem install bundler-audit' + $(hain) 'bundle audit --update' + +brakeman: ## Busca posibles vulnerabilidades en Sutty + $(MAKE) bundle args='exec brakeman' + +yarn: ## Tareas de yarn $(hain) 'yarn $(args)' -# Servir JS con el dev server. -# Esto acelera la compilación del javascript, tiene que correrse por separado -# de serve. -serve-js: /etc/hosts - $(hain) 'cd /Sutty/sutty; bundle exec ./bin/webpack-dev-server' +clean: ## Limpieza + rm -rf _sites/test-* _deploy/test-* log/*.log tmp/cache tmp/letter_opener tmp/miniprofiler tmp/storage -# Limpiar los archivos de testeo -clean: - rm -rf _sites/test-* _deploy/test-* - -# Generar la imagen Docker -build: assets +build: Gemfile.lock ## Generar la imagen Docker time docker build --build-arg="BRANCH=$(branch)" --build-arg="RAILS_MASTER_KEY=`cat config/master.key`" -t sutty/$(container) . docker tag sutty/$(container):latest sutty:keep + @echo -e "\a" -save: - time docker save sutty/$(container):latest | ssh root@$(delegate).sutty.nl docker load +save: ## Subir la imagen Docker al nodo delegado + time docker save sutty/$(container):latest | ssh root@$(delegate) docker load date +%F | xargs -I {} git tag -f $(container)-{} @echo -e "\a" -# proyectos. -../gems/: - mkdir -p $@ - -# Crear el directorio donde se almacenan las gemas binarias -# TODO: Mover a un proyecto propio, porque lo utilizamos en todos los -gem_dir := $(shell readlink -f ../gems) -gem_cache_dir := $(gem_dir)/cache -gem_binary_dir := $(gem_dir)/$(alpine_version) -ifeq ($(MAKECMDGOALS),build-gems) -gems := $(shell bundle show --paths | xargs -I {} sh -c 'find {}/ext/ -name extconf.rb &>/dev/null && basename {}') -gems := $(patsubst %-x86_64-linux,%,$(gems)) -gems := $(patsubst %,$(gem_cache_dir)/%.gem,$(gems)) -gems_musl := $(patsubst $(gem_cache_dir)/%.gem,$(gem_binary_dir)/%-x86_64-linux-musl.gem,$(gems)) -endif - -$(gem_binary_dir)/%-x86_64-linux-musl.gem: - @docker run \ - -v $(gem_dir):/srv/gems \ - -v `readlink -f ~/.ccache`:/home/builder/.ccache \ - -e HTTP_BASIC_USER=$(HTTP_BASIC_USER) \ - -e HTTP_BASIC_PASSWORD=$(HTTP_BASIC_PASSWORD) \ - -e GEM=`echo $(notdir $*) | sed -re "s/-[^-]+$$//"` \ - -e VERSION=`echo $(notdir $*) | sed -re "s/.*-([^-]+)$$/\1/"` \ - -e JOBS=2 \ - --rm -it \ - sutty/gem-compiler:latest || echo "No se pudo compilar $*" - -# Compilar todas las gemas binarias y subirlas a gems.sutty.nl para que -# al crear el contenedor no tengamos que compilarlas cada vez -build-gems: $(gems_musl) - -cached_gems = $(wildcard $(gem_dir)/cache/*.gem) -rebuild_gems = $(patsubst $(gem_dir)/cache/%.gem,$(gem_dir)/$(alpine_version)/%-x86_64-linux-musl.gem,$(cached_gems)) -rebuild-gems: $(rebuild_gems) - -dirs := $(patsubst %,root/%,data sites deploy public) - -$(dirs): - mkdir -p $@ - -ota: assets +ota-js: assets ## Actualizar Javascript en el nodo delegado sudo chgrp -R 82 public/ - rsync -avi --delete-after public/ $(delegate):/srv/sutty/srv/http/data/_$(public)/ - ssh $(delegate) docker exec $(container) sh -c "cat /srv/http/tmp/puma.pid | xargs -r kill -USR2" + rsync -avi --delete-after public/ root@$(delegate):/srv/sutty/srv/http/data/_$(public)/ + ssh root@$(delegate) docker exec $(container) sh -c "cat /srv/http/tmp/puma.pid | xargs -r kill -USR2" -# Hotfixes -# -# TODO: Reemplazar esto por git pull en el contenedor -commit ?= origin/rails -ota-rb: +ota: ## Actualizar Rails en el nodo delegado umask 022; git format-patch $(commit) scp ./0*.patch $(delegate):/tmp/ ssh $(delegate) mkdir -p /tmp/patches-$(commit)/ @@ -140,6 +117,19 @@ ota-rb: ssh $(delegate) docker exec $(container) ota $(commit) rm ./0*.patch +# Todos los archivos de assets. Si alguno cambia, se van a recompilar +# los assets que luego se suben al nodo delegado. +assets := package.json yarn.lock $(shell find app/assets/ app/javascript/ -type f) +public/packs/manifest.json.br: $(assets) + $(hain) 'PANEL_URL=https://panel.sutty.nl RAILS_ENV=production NODE_ENV=production bundle exec rake assets:precompile assets:clean' + +# Correr un test en particular por ejemplo +# `make test/models/usuarie_test.rb` +tests := $(shell find test/ -name "*_test.rb") +$(tests): always + $(MAKE) test args="TEST=$@" + +# Agrega las direcciones locales al sistema /etc/hosts: always @echo "Chequeando si es necesario agregar el dominio local $(SUTTY)" @grep -q " $(SUTTY)$$" $@ || echo -e "127.0.0.1 $(SUTTY)\n::1 $(SUTTY)" | sudo tee -a $@ @@ -147,4 +137,12 @@ ota-rb: @grep -q " panel.$(SUTTY)$$" $@ || echo -e "127.0.0.1 panel.$(SUTTY)\n::1 panel.$(SUTTY)" | sudo tee -a $@ @grep -q " postgresql.$(SUTTY)$$" $@ || echo -e "127.0.0.1 postgresql.$(SUTTY)\n::1 postgresql.$(SUTTY)" | sudo tee -a $@ +# Instala las dependencias de Javascript +node_modules: package.json + $(MAKE) yarn + +# Instala las dependencias de Rails +Gemfile.lock: Gemfile + $(MAKE) bundle args=install + .PHONY: always diff --git a/README.md b/README.md index ef889f9b..25d0d31c 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,17 @@ Este repositorio es la plataforma _Ruby on Rails_ para alojar el Para más información visita el [sitio de Sutty](https://sutty.nl/). +### Desarrollar + +Todas las tareas se gestionan con `make`, por favor instala GNU Make +antes de comenzar. + +```bash +make help +``` + +[Leer la documentación](https://docs.sutty.nl/) + ## English Sutty is a platform for hosting safer, faster and more resilient @@ -25,3 +36,13 @@ This repository is the Ruby on Rails platform that hosts the self-managed [panel](https://panel.sutty.nl/). For more information, visit [Sutty's website](https://sutty.nl/en/). + +### Development + +Every task is run via `make`, please install GNU Make before developing. + +```bash +make help +``` + +[Read the documentation](https://docs.sutty.nl/en/) From cf67dbb0c3b98106c4540e9eaeabafceff805e0c Mon Sep 17 00:00:00 2001 From: f Date: Mon, 12 Jul 2021 16:52:44 -0300 Subject: [PATCH 005/146] Devolver el tipo de dato correcto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Como MetadataBelongsTo desciende de MetadataArray, al cambiar métodos de MetadataArray tenemos efectos secundarios. Esto es un hotfix, la solución correcta sería reimplementar MetadataBelongsTo para que deje de ser un Array. --- app/models/metadata_belongs_to.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index 1438c8db..be1fa670 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -13,6 +13,13 @@ class MetadataBelongsTo < MetadataRelatedPosts '' end + # Obtiene el valor desde el documento. + # + # @return [String] + def document_value + document.data[name.to_s] + end + def validate super From 68bd68a2ee2cac6e990f49f1266b612e771fd4d3 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 13 Jul 2021 17:22:05 -0300 Subject: [PATCH 006/146] =?UTF-8?q?actualizaci=C3=B3n=20de=20cuidados,=20r?= =?UTF-8?q?esuelve=20un=20cve=20en=20addressable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 162 +++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index aed60b18..33fba3a0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,66 +18,66 @@ GIT GEM remote: https://gems.sutty.nl/ specs: - actioncable (6.1.3.2) - actionpack (= 6.1.3.2) - activesupport (= 6.1.3.2) + actioncable (6.1.4) + actionpack (= 6.1.4) + activesupport (= 6.1.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.3.2) - actionpack (= 6.1.3.2) - activejob (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionmailbox (6.1.4) + actionpack (= 6.1.4) + activejob (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) mail (>= 2.7.1) - actionmailer (6.1.3.2) - actionpack (= 6.1.3.2) - actionview (= 6.1.3.2) - activejob (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionmailer (6.1.4) + actionpack (= 6.1.4) + actionview (= 6.1.4) + activejob (= 6.1.4) + activesupport (= 6.1.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.3.2) - actionview (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionpack (6.1.4) + actionview (= 6.1.4) + activesupport (= 6.1.4) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.3.2) - actionpack (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + actiontext (6.1.4) + actionpack (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) nokogiri (>= 1.8.5) - actionview (6.1.3.2) - activesupport (= 6.1.3.2) + actionview (6.1.4) + activesupport (= 6.1.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.3.2) - activesupport (= 6.1.3.2) + activejob (6.1.4) + activesupport (= 6.1.4) globalid (>= 0.3.6) - activemodel (6.1.3.2) - activesupport (= 6.1.3.2) - activerecord (6.1.3.2) - activemodel (= 6.1.3.2) - activesupport (= 6.1.3.2) - activestorage (6.1.3.2) - actionpack (= 6.1.3.2) - activejob (= 6.1.3.2) - activerecord (= 6.1.3.2) - activesupport (= 6.1.3.2) + activemodel (6.1.4) + activesupport (= 6.1.4) + activerecord (6.1.4) + activemodel (= 6.1.4) + activesupport (= 6.1.4) + activestorage (6.1.4) + actionpack (= 6.1.4) + activejob (= 6.1.4) + activerecord (= 6.1.4) + activesupport (= 6.1.4) marcel (~> 1.0.0) - mini_mime (~> 1.0.2) - activesupport (6.1.3.2) + mini_mime (>= 1.1.0) + activesupport (6.1.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) adhesiones-jekyll-theme (0.2.1) jekyll (~> 4.0) @@ -113,7 +113,7 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (>= 2.0, < 4.0) - chartkick (4.0.4) + chartkick (4.0.5) childprocess (3.0.0) coderay (1.1.3) colorator (1.1.0) @@ -130,7 +130,7 @@ GEM database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) dead_end (1.1.7) - derailed_benchmarks (2.1.0) + derailed_benchmarks (2.1.1) benchmark-ips (~> 2) dead_end get_process_mem (~> 0) @@ -148,8 +148,8 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-i18n (1.9.4) - devise (>= 4.7.1) + devise-i18n (1.10.0) + devise (>= 4.8.0) devise_invitable (2.0.5) actionmailer (>= 5.0) devise (>= 4.6) @@ -196,7 +196,7 @@ GEM railties (>= 5.0.0) fast_blank (1.0.0-x86_64-linux-musl) fast_jsonparser (0.5.0-x86_64-linux-musl) - ffi (1.15.1-x86_64-linux-musl) + ffi (1.15.3-x86_64-linux-musl) flamegraph (0.9.5) forwardable-extended (2.6.0) friendly_id (5.4.2) @@ -214,7 +214,7 @@ GEM tilt haml-lint (0.999.999) haml_lint - haml_lint (0.37.0) + haml_lint (0.37.1) haml (>= 4.0, < 5.3) parallel (~> 1.10) rainbow @@ -264,8 +264,8 @@ GEM rouge (~> 3.0) safe_yaml (~> 1.0) terminal-table (~> 2.0) - jekyll-commonmark (1.3.1) - commonmarker (~> 0.14) + jekyll-commonmark (1.3.2) + commonmarker (~> 0.14, < 0.22) jekyll (>= 3.7, < 5.0) jekyll-data (1.1.2) jekyll (>= 3.3, < 5.0.0) @@ -284,10 +284,10 @@ GEM ruby-vips (~> 2) jekyll-include-cache (0.2.1) jekyll (>= 3.7, < 5.0) - jekyll-linked-posts (0.2.0) + jekyll-linked-posts (0.4.0) jekyll (~> 4) jekyll-locales (0.1.12) - jekyll-lunr (0.2.0) + jekyll-lunr (0.3.0) loofah (~> 2.4) jekyll-order (0.1.4) jekyll-relative-urls (0.0.6) @@ -296,7 +296,7 @@ GEM sassc (> 2.0.1, < 3.0) jekyll-seo-tag (2.7.1) jekyll (>= 3.8, < 5.0) - jekyll-spree-client (0.1.14) + jekyll-spree-client (0.1.15) fast_blank (~> 1) spree-api-client (~> 0.2) jekyll-turbolinks (0.0.5) @@ -324,7 +324,7 @@ GEM ruby_dep (~> 1.2) loaf (0.10.0) railties (>= 3.2) - lockbox (0.6.4) + lockbox (0.6.5) lograge (0.11.2) actionpack (>= 4) activesupport (>= 4) @@ -341,10 +341,10 @@ GEM method_source (1.0.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2021.0225) + mime-types-data (3.2021.0704) mini_histogram (0.3.1) mini_magick (4.11.0) - mini_mime (1.0.3) + mini_mime (1.1.0) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) @@ -361,7 +361,7 @@ GEM racc (~> 1.4) orm_adapter (0.5.0) parallel (1.20.1) - parser (3.0.1.1) + parser (3.0.2.0) ast (~> 2.4.1) pathutil (0.16.2) forwardable-extended (~> 2.6) @@ -370,7 +370,7 @@ GEM activerecord (>= 5.2) activesupport (>= 5.2) popper_js (1.16.0) - prometheus_exporter (0.7.0) + prometheus_exporter (0.8.0) webrick pry (0.14.1) coderay (~> 1.1) @@ -401,20 +401,20 @@ GEM jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) jekyll-turbolinks (~> 0) - rails (6.1.3.2) - actioncable (= 6.1.3.2) - actionmailbox (= 6.1.3.2) - actionmailer (= 6.1.3.2) - actionpack (= 6.1.3.2) - actiontext (= 6.1.3.2) - actionview (= 6.1.3.2) - activejob (= 6.1.3.2) - activemodel (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + rails (6.1.4) + actioncable (= 6.1.4) + actionmailbox (= 6.1.4) + actionmailer (= 6.1.4) + actionpack (= 6.1.4) + actiontext (= 6.1.4) + actionview (= 6.1.4) + activejob (= 6.1.4) + activemodel (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) bundler (>= 1.15.0) - railties (= 6.1.3.2) + railties (= 6.1.4) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) @@ -426,14 +426,14 @@ GEM railties (>= 6.0.0, < 7) rails_warden (0.6.0) warden (>= 1.2.0) - railties (6.1.3.2) - actionpack (= 6.1.3.2) - activesupport (= 6.1.3.2) + railties (6.1.4) + actionpack (= 6.1.4) + activesupport (= 6.1.4) method_source - rake (>= 0.8.7) + rake (>= 0.13) thor (~> 1.0) rainbow (3.0.0) - rake (13.0.3) + rake (13.0.6) rb-fsevent (0.11.0) rb-inotify (0.10.1) ffi (~> 1.0) @@ -480,7 +480,7 @@ GEM railties (>= 5.0) rexml (3.2.5) rouge (3.26.0) - rubocop (1.17.0) + rubocop (1.18.3) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) @@ -491,7 +491,7 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.7.0) parser (>= 3.0.1.1) - rubocop-rails (2.10.1) + rubocop-rails (2.11.3) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) @@ -506,10 +506,10 @@ GEM ruby_parser (~> 3.1) sexp_processor (~> 4.6) ruby_dep (1.5.0) - ruby_parser (3.15.1) - sexp_processor (~> 4.9) - rubyzip (2.3.0) - rugged (1.1.0-x86_64-linux-musl) + ruby_parser (3.16.0) + sexp_processor (~> 4.15, >= 4.15.1) + rubyzip (2.3.2) + rugged (1.1.1-x86_64-linux-musl) safe_yaml (1.0.6) safely_block (0.3.0) errbase (>= 0.1.1) @@ -525,7 +525,7 @@ GEM childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) semantic_range (3.0.0) - sexp_processor (4.15.2) + sexp_processor (4.15.3) share-to-fediverse-jekyll-theme (0.1.4) jekyll (~> 4.0) jekyll-data (~> 1.1) @@ -537,7 +537,7 @@ GEM simpleidn (0.2.1) unf (~> 0.1.4) sourcemap (0.1.1) - spree-api-client (0.2.1) + spree-api-client (0.2.2) fast_blank (~> 1) httparty (~> 0.18.0) spring (2.1.1) From c9de4f71984ba3f357b23bc6ac008b2a1911410c Mon Sep 17 00:00:00 2001 From: f Date: Tue, 13 Jul 2021 17:24:09 -0300 Subject: [PATCH 007/146] si estamos actualizando desde origin/rails hay que ignorar el directorio --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c083ddf8..6f04c74f 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,7 @@ ota-rb: ssh $(delegate) mkdir -p /tmp/patches-$(commit)/ scp ./0*.patch $(delegate):/tmp/patches-$(commit)/ scp ./ota.sh $(delegate):/tmp/ - ssh $(delegate) docker cp /tmp/patches-$(commit) $(container):/tmp/ + ssh $(delegate) docker cp /tmp/patches-$(shell echo $(commit) | cut -d / -f 1) $(container):/tmp/ ssh $(delegate) docker cp /tmp/ota.sh $(container):/usr/local/bin/ota ssh $(delegate) docker exec $(container) apk add --no-cache patch ssh $(delegate) docker exec $(container) ota $(commit) From 8f88023d52257fba2152dfcd8bc4bc62ea57214f Mon Sep 17 00:00:00 2001 From: f Date: Thu, 22 Jul 2021 16:16:10 -0300 Subject: [PATCH 008/146] El espacio es importante --- Makefile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index a4480476..0bb5f582 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,13 @@ include .env export -args ?= ## Argumentos para Hain -commit ?= origin/rails ## Commit desde el que actualizar -env ?= staging ## Entorno del nodo delegado -sutty ?= $(SUTTY) ## Dirección local -delegate ?= $(DELEGATE) ## Cambia el nodo delegado -hain ?= $(HAINISH) ## Ubicación de Hainish +# XXX: El espacio antes del comentario cuenta como espacio +args ?=## Argumentos para Hain +commit ?= origin/rails## Commit desde el que actualizar +env ?= staging## Entorno del nodo delegado +sutty ?= $(SUTTY)## Dirección local +delegate ?= $(DELEGATE)## Cambia el nodo delegado +hain ?= $(HAINISH)## Ubicación de Hainish # El nodo delegado tiene dos entornos, production y staging. # Dependiendo del entorno que elijamos, se van a generar los assets y el From d474b819ad60ebe24e3f3ba63616bfe2300c6d5c Mon Sep 17 00:00:00 2001 From: f Date: Thu, 22 Jul 2021 16:19:25 -0300 Subject: [PATCH 009/146] agregar request_uri a los logs sutty/containers/nginx!1 --- .../20210722191718_add_request_uri_to_access_logs.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 db/migrate/20210722191718_add_request_uri_to_access_logs.rb diff --git a/db/migrate/20210722191718_add_request_uri_to_access_logs.rb b/db/migrate/20210722191718_add_request_uri_to_access_logs.rb new file mode 100644 index 00000000..3d225aed --- /dev/null +++ b/db/migrate/20210722191718_add_request_uri_to_access_logs.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Agrega la columna de request_uri a la tabla de logs +class AddRequestUriToAccessLogs < ActiveRecord::Migration[6.1] + def change + return unless Rails.env.production? + + add_column :access_logs, :request_uri, :string, default: '' + end +end From d456feac8e70418f52c962e82a40b58559858a4e Mon Sep 17 00:00:00 2001 From: f Date: Thu, 29 Jul 2021 14:46:29 -0300 Subject: [PATCH 010/146] =?UTF-8?q?Cancelar=20la=20tarea=20pendiente=20si?= =?UTF-8?q?=20tom=C3=B3=20mas=20de=2010=20minutos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Si la tarea se reintentó durante 10 minutos, lo más probable es que haya quedado trabada en algún lado. Este cambio permite volver a compilar sitios al cambiar el estado a espera y cancelarse a sí misma. --- app/jobs/deploy_job.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index f1ceca9e..70997ce1 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -5,13 +5,23 @@ class DeployJob < ApplicationJob class DeployException < StandardError; end # rubocop:disable Metrics/MethodLength - def perform(site, notify = true) + def perform(site, notify = true, time = Time.now) ActiveRecord::Base.connection_pool.with_connection do @site = Site.find(site) - # Si ya hay una tarea corriendo, aplazar esta + # Si ya hay una tarea corriendo, aplazar esta. Si estuvo + # esperando más de 10 minutos, recuperar el estado anterior. + # + # Como el trabajo actual se aplaza al siguiente, arrastrar la + # hora original para poder ir haciendo timeouts. if @site.building? - DeployJob.perform_in(60, site, notify) + if 10.minutes.ago >= time + @site.update status: 'waiting' + raise DeployException, + "#{@site.name} la tarea estuvo más de 10 minutos esperando, volviendo al estado original" + end + + DeployJob.perform_in(60, site, notify, time) return end @@ -29,8 +39,11 @@ class DeployJob < ApplicationJob end deploy_others - notify_usuaries if notify + + # Volver a la espera @site.update status: 'waiting' + + notify_usuaries if notify end end # rubocop:enable Metrics/MethodLength From 4c84389b3561f8b34831736f196a9729f96f9bbb Mon Sep 17 00:00:00 2001 From: Nulo <5151-Nulo@users.noreply.0xacab.org> Date: Mon, 2 Aug 2021 16:17:30 +0000 Subject: [PATCH 011/146] Apply 3 suggestion(s) to 1 file(s) --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0bb5f582..03fd395d 100644 --- a/Makefile +++ b/Makefile @@ -62,13 +62,13 @@ serve-js: /etc/hosts node_modules ## Iniciar el servidor de desarrollo de Javasc serve: /etc/hosts postgresql Gemfile.lock ## Iniciar el servidor de desarrollo de Rails $(MAKE) rails args=server -rails: ## Tareas de Rails +rails: ## Corre rails dentro del entorno de desarrollo (pasar argumentos con args=). $(MAKE) bundle args="exec rails $(args)" -rake: ## Tareas de Rake +rake: ## Corre rake dentro del entorno de desarrollo (pasar argumentos con args=). $(MAKE) bundle args="exec rake $(args)" -bundle: ## Tareas de bundler +bundle: ## Corre bundle dentro del entorno de desarrollo (pasar argumentos con args=). $(hain) 'bundle $(args)' rubocop: ## Yutea el código que está por ser commiteado From 9f84c14a69e3102d96087f589d1fa1bc18b6a877 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 7 Aug 2021 15:55:00 -0300 Subject: [PATCH 012/146] Soportar sitios sin yarn.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Como el chequeo devuelve nil, un sitio sin yarn.lock nunca se compilaría. --- 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 02b837f0..c063b7bc 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -80,7 +80,7 @@ class DeployLocal < Deploy # Corre yarn dentro del repositorio def yarn - return unless yarn_lock? + return true unless yarn_lock? run 'yarn' end From 0bd8a2243e88db85da363ad2101056c9361aeec2 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 11 Aug 2021 10:25:05 -0300 Subject: [PATCH 013/146] Solo permitir URLs web al sanitizar fixes #2382 --- app/models/metadata_content.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_content.rb b/app/models/metadata_content.rb index 437a0dd9..9d3a1040 100644 --- a/app/models/metadata_content.rb +++ b/app/models/metadata_content.rb @@ -56,7 +56,7 @@ class MetadataContent < MetadataTemplate uri = URI element['src'] # No permitimos recursos externos - element.remove unless uri.hostname.end_with? Site.domain + element.remove unless uri.scheme == 'https' && uri.hostname.end_with?(Site.domain) rescue URI::Error element.remove end From 9ccc1be89834df97127370bb6f3552a3ef1003d8 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 28 Aug 2021 12:56:04 -0300 Subject: [PATCH 014/146] =?UTF-8?q?actualizaci=C3=B3n=20de=20cuidados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 + Gemfile.lock | 175 ++++++++++++++++++++++++++------------------------- 2 files changed, 91 insertions(+), 86 deletions(-) diff --git a/Gemfile b/Gemfile index 4256e307..cb78d4c3 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,8 @@ gem 'sassc-rails' gem 'uglifier', '>= 1.3.0' gem 'bootstrap', '~> 4' +gem 'nokogiri', '~>1.11.0' + # Turbolinks makes navigating your web application faster. Read more: # https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' diff --git a/Gemfile.lock b/Gemfile.lock index 33fba3a0..8ce97f31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,60 +18,60 @@ GIT GEM remote: https://gems.sutty.nl/ specs: - actioncable (6.1.4) - actionpack (= 6.1.4) - activesupport (= 6.1.4) + actioncable (6.1.4.1) + actionpack (= 6.1.4.1) + activesupport (= 6.1.4.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.4) - actionpack (= 6.1.4) - activejob (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + actionmailbox (6.1.4.1) + actionpack (= 6.1.4.1) + activejob (= 6.1.4.1) + activerecord (= 6.1.4.1) + activestorage (= 6.1.4.1) + activesupport (= 6.1.4.1) mail (>= 2.7.1) - actionmailer (6.1.4) - actionpack (= 6.1.4) - actionview (= 6.1.4) - activejob (= 6.1.4) - activesupport (= 6.1.4) + actionmailer (6.1.4.1) + actionpack (= 6.1.4.1) + actionview (= 6.1.4.1) + activejob (= 6.1.4.1) + activesupport (= 6.1.4.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.4) - actionview (= 6.1.4) - activesupport (= 6.1.4) + actionpack (6.1.4.1) + actionview (= 6.1.4.1) + activesupport (= 6.1.4.1) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.4) - actionpack (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + actiontext (6.1.4.1) + actionpack (= 6.1.4.1) + activerecord (= 6.1.4.1) + activestorage (= 6.1.4.1) + activesupport (= 6.1.4.1) nokogiri (>= 1.8.5) - actionview (6.1.4) - activesupport (= 6.1.4) + actionview (6.1.4.1) + activesupport (= 6.1.4.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.4) - activesupport (= 6.1.4) + activejob (6.1.4.1) + activesupport (= 6.1.4.1) globalid (>= 0.3.6) - activemodel (6.1.4) - activesupport (= 6.1.4) - activerecord (6.1.4) - activemodel (= 6.1.4) - activesupport (= 6.1.4) - activestorage (6.1.4) - actionpack (= 6.1.4) - activejob (= 6.1.4) - activerecord (= 6.1.4) - activesupport (= 6.1.4) + activemodel (6.1.4.1) + activesupport (= 6.1.4.1) + activerecord (6.1.4.1) + activemodel (= 6.1.4.1) + activesupport (= 6.1.4.1) + activestorage (6.1.4.1) + actionpack (= 6.1.4.1) + activejob (= 6.1.4.1) + activerecord (= 6.1.4.1) + activesupport (= 6.1.4.1) marcel (~> 1.0.0) mini_mime (>= 1.1.0) - activesupport (6.1.4) + activesupport (6.1.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -89,13 +89,13 @@ GEM jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) ast (2.4.2) - autoprefixer-rails (10.2.5.1) - execjs (> 0) + autoprefixer-rails (10.3.1.0) + execjs (~> 2) bcrypt (3.1.16-x86_64-linux-musl) bcrypt_pbkdf (1.1.0-x86_64-linux-musl) benchmark-ips (2.9.1) bindex (0.8.1-x86_64-linux-musl) - blazer (2.4.2) + blazer (2.4.3) activerecord (>= 5) chartkick (>= 3.2) railties (>= 5) @@ -104,7 +104,7 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) - brakeman (5.0.4) + brakeman (5.1.1) builder (3.2.4) capybara (2.18.0) addressable @@ -157,8 +157,8 @@ GEM dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - down (5.2.2) - addressable (~> 2.5) + down (5.2.3) + addressable (~> 2.8) ed25519 (1.2.4-x86_64-linux-musl) editorial-autogestiva-jekyll-theme (0.3.4) jekyll (~> 4) @@ -194,7 +194,7 @@ GEM factory_bot_rails (6.2.0) factory_bot (~> 6.2.0) railties (>= 5.0.0) - fast_blank (1.0.0-x86_64-linux-musl) + fast_blank (1.0.1-x86_64-linux-musl) fast_jsonparser (0.5.0-x86_64-linux-musl) ffi (1.15.3-x86_64-linux-musl) flamegraph (0.9.5) @@ -203,13 +203,13 @@ GEM activerecord (>= 4.0.0) get_process_mem (0.2.7) ffi (~> 1.0) - globalid (0.4.2) - activesupport (>= 4.2.0) + globalid (0.5.2) + activesupport (>= 5.0) hairtrigger (0.2.24) activerecord (>= 5.0, < 7) ruby2ruby (~> 2.4) ruby_parser (~> 3.10) - haml (5.2.1) + haml (5.2.2) temple (>= 0.8.0) tilt haml-lint (0.999.999) @@ -220,7 +220,7 @@ GEM rainbow rubocop (>= 0.50.0) sysexits (~> 1.1) - hamlit (2.15.0-x86_64-linux-musl) + hamlit (2.15.1-x86_64-linux-musl) temple (>= 0.8.2) thor tilt @@ -276,7 +276,7 @@ GEM jekyll (>= 3.7, < 5.0) jekyll-hardlinks (0.1.2) jekyll (~> 4) - jekyll-ignore-layouts (0.1.0) + jekyll-ignore-layouts (0.1.2) jekyll (~> 4) jekyll-images (0.2.7) jekyll (~> 4) @@ -284,7 +284,7 @@ GEM ruby-vips (~> 2) jekyll-include-cache (0.2.1) jekyll (>= 3.7, < 5.0) - jekyll-linked-posts (0.4.0) + jekyll-linked-posts (0.4.2) jekyll (~> 4) jekyll-locales (0.1.12) jekyll-lunr (0.3.0) @@ -296,9 +296,9 @@ GEM sassc (> 2.0.1, < 3.0) jekyll-seo-tag (2.7.1) jekyll (>= 3.8, < 5.0) - jekyll-spree-client (0.1.15) + jekyll-spree-client (0.1.17) fast_blank (~> 1) - spree-api-client (~> 0.2) + spree-api-client (>= 0.2.3) jekyll-turbolinks (0.0.5) jekyll (~> 4) turbolinks-source (~> 5) @@ -306,7 +306,7 @@ GEM jekyll (~> 4) jekyll-watch (2.2.1) listen (~> 3.0) - jekyll-write-and-commit-changes (0.1.2) + jekyll-write-and-commit-changes (0.2.0) jekyll (~> 4) rugged (~> 1) kramdown (2.3.1) @@ -330,7 +330,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.10.0) + loofah (2.12.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -344,20 +344,22 @@ GEM mime-types-data (3.2021.0704) mini_histogram (0.3.1) mini_magick (4.11.0) - mini_mime (1.1.0) + mini_mime (1.1.1) + mini_portile2 (2.5.3) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.4) - mobility (1.1.2) + mobility (1.1.3) i18n (>= 0.6.10, < 2) request_store (~> 1.0) multi_xml (0.6.0) net-ssh (6.1.0) netaddr (2.0.4) - nio4r (2.5.7-x86_64-linux-musl) - nokogiri (1.11.7-x86_64-linux) + nio4r (2.5.8-x86_64-linux-musl) + nokogiri (1.11.7-x86_64-linux-musl) + mini_portile2 (~> 2.5.0) racc (~> 1.4) orm_adapter (0.5.0) parallel (1.20.1) @@ -370,15 +372,15 @@ GEM activerecord (>= 5.2) activesupport (>= 5.2) popper_js (1.16.0) - prometheus_exporter (0.8.0) + prometheus_exporter (0.8.1) webrick pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) public_suffix (4.0.6) - puma (5.3.2-x86_64-linux-musl) + puma (5.4.0-x86_64-linux-musl) nio4r (~> 2.0) - pundit (2.1.0) + pundit (2.1.1) activesupport (>= 3.0.0) racc (1.5.2-x86_64-linux-musl) rack (2.2.3) @@ -401,34 +403,34 @@ GEM jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) jekyll-turbolinks (~> 0) - rails (6.1.4) - actioncable (= 6.1.4) - actionmailbox (= 6.1.4) - actionmailer (= 6.1.4) - actionpack (= 6.1.4) - actiontext (= 6.1.4) - actionview (= 6.1.4) - activejob (= 6.1.4) - activemodel (= 6.1.4) - activerecord (= 6.1.4) - activestorage (= 6.1.4) - activesupport (= 6.1.4) + rails (6.1.4.1) + actioncable (= 6.1.4.1) + actionmailbox (= 6.1.4.1) + actionmailer (= 6.1.4.1) + actionpack (= 6.1.4.1) + actiontext (= 6.1.4.1) + actionview (= 6.1.4.1) + activejob (= 6.1.4.1) + activemodel (= 6.1.4.1) + activerecord (= 6.1.4.1) + activestorage (= 6.1.4.1) + activesupport (= 6.1.4.1) bundler (>= 1.15.0) - railties (= 6.1.4) + railties (= 6.1.4.1) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.2) loofah (~> 2.3) rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) rails_warden (0.6.0) warden (>= 1.2.0) - railties (6.1.4) - actionpack (= 6.1.4) - activesupport (= 6.1.4) + railties (6.1.4.1) + actionpack (= 6.1.4.1) + activesupport (= 6.1.4.1) method_source rake (>= 0.13) thor (~> 1.0) @@ -455,7 +457,7 @@ GEM jekyll-unique-urls (~> 0.1) sutty-archives (~> 2.2) sutty-liquid (~> 0) - redis (4.3.1) + redis (4.4.0) redis-actionpack (5.2.0) actionpack (>= 5, < 7) redis-rack (>= 2.1.0, < 3) @@ -480,16 +482,16 @@ GEM railties (>= 5.0) rexml (3.2.5) rouge (3.26.0) - rubocop (1.18.3) + rubocop (1.20.0) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 1.7.0, < 2.0) + rubocop-ast (>= 1.9.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.7.0) + rubocop-ast (1.11.0) parser (>= 3.0.1.1) rubocop-rails (2.11.3) activesupport (>= 4.2.0) @@ -500,13 +502,13 @@ GEM ruby-filemagic (0.7.2-x86_64-linux-musl) ruby-progressbar (1.11.0) ruby-statistics (2.1.3) - ruby-vips (2.1.2) + ruby-vips (2.1.3) ffi (~> 1.12) ruby2ruby (2.4.4) ruby_parser (~> 3.1) sexp_processor (~> 4.6) ruby_dep (1.5.0) - ruby_parser (3.16.0) + ruby_parser (3.17.0) sexp_processor (~> 4.15, >= 4.15.1) rubyzip (2.3.2) rugged (1.1.1-x86_64-linux-musl) @@ -537,7 +539,7 @@ GEM simpleidn (0.2.1) unf (~> 0.1.4) sourcemap (0.1.1) - spree-api-client (0.2.2) + spree-api-client (0.2.3) fast_blank (~> 1) httparty (~> 0.18.0) spring (2.1.1) @@ -610,7 +612,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webpacker (5.4.0) + webpacker (5.4.2) activesupport (>= 5.2) rack-proxy (>= 0.6.1) railties (>= 5.2) @@ -677,6 +679,7 @@ DEPENDENCIES minima mobility net-ssh + nokogiri (~> 1.11.0) pg pg_search prometheus_exporter From be549c5cd518b942ff65abf31ffe8969ddfb6f1f Mon Sep 17 00:00:00 2001 From: f Date: Sat, 28 Aug 2021 13:02:12 -0300 Subject: [PATCH 015/146] ruby 2.7.4 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0b3253b4..59352b61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ ENV RAILS_MASTER_KEY=$RAILS_MASTER_KEY RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake RUN apk add --no-cache postgresql-libs git yarn brotli libssh2 python3 -RUN test "2.7.3" = `ruby -e 'puts RUBY_VERSION'` +RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` # https://github.com/rubygems/rubygems/issues/2918 # https://gitlab.alpinelinux.org/alpine/aports/issues/10808 @@ -85,7 +85,7 @@ RUN apk add --no-cache ffmpeg imagemagick pandoc tectonic oxipng jemalloc RUN apk add --no-cache git-lfs openssh-client patch # Chequear que la versión de ruby sea la correcta -RUN test "2.7.3" = `ruby -e 'puts RUBY_VERSION'` +RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` # https://github.com/rubygems/rubygems/issues/2918 # https://gitlab.alpinelinux.org/alpine/aports/issues/10808 From 094a8092de7721edab16cfb052db058dbe3464cd Mon Sep 17 00:00:00 2001 From: f Date: Fri, 3 Sep 2021 15:23:11 -0300 Subject: [PATCH 016/146] Agregar rollups --- Gemfile | 1 + Gemfile.lock | 10 +++++++++- db/migrate/20210807003928_create_rollups.rb | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20210807003928_create_rollups.rb diff --git a/Gemfile b/Gemfile index 4256e307..2f5446a0 100644 --- a/Gemfile +++ b/Gemfile @@ -58,6 +58,7 @@ gem 'rails-i18n' gem 'rails_warden' gem 'redis', require: %w[redis redis/connection/hiredis] gem 'redis-rails' +gem 'rollups' gem 'rubyzip' gem 'rugged' gem 'concurrent-ruby-ext' diff --git a/Gemfile.lock b/Gemfile.lock index 33fba3a0..6c873d9b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -205,6 +205,8 @@ GEM ffi (~> 1.0) globalid (0.4.2) activesupport (>= 4.2.0) + groupdate (5.2.2) + activesupport (>= 5) hairtrigger (0.2.24) activerecord (>= 5.0, < 7) ruby2ruby (~> 2.4) @@ -345,6 +347,7 @@ GEM mini_histogram (0.3.1) mini_magick (4.11.0) mini_mime (1.1.0) + mini_portile2 (2.5.3) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) @@ -357,7 +360,8 @@ GEM net-ssh (6.1.0) netaddr (2.0.4) nio4r (2.5.7-x86_64-linux-musl) - nokogiri (1.11.7-x86_64-linux) + nokogiri (1.11.7-x86_64-linux-musl) + mini_portile2 (~> 2.5.0) racc (~> 1.4) orm_adapter (0.5.0) parallel (1.20.1) @@ -479,6 +483,9 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.5) + rollups (0.1.2) + activesupport (>= 5.1) + groupdate (>= 5.2) rouge (3.26.0) rubocop (1.18.3) parallel (~> 1.10) @@ -692,6 +699,7 @@ DEPENDENCIES recursero-jekyll-theme redis redis-rails + rollups rubocop-rails rubyzip rugged diff --git a/db/migrate/20210807003928_create_rollups.rb b/db/migrate/20210807003928_create_rollups.rb new file mode 100644 index 00000000..932513a4 --- /dev/null +++ b/db/migrate/20210807003928_create_rollups.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# Crear la tabla de Rollups +class CreateRollups < ActiveRecord::Migration[6.1] + def change + create_table :rollups do |t| + t.string :name, null: false + t.string :interval, null: false + t.datetime :time, null: false + t.jsonb :dimensions, null: false, default: {} + t.float :value + end + add_index :rollups, %i[name interval time dimensions], unique: true + end +end From 604c16bfb8947b42634bc3f2f8c30f168fecee13 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 3 Sep 2021 15:28:45 -0300 Subject: [PATCH 017/146] Agregar created_at a access_logs para poder agrupar por fecha --- ...10807004941_add_create_at_to_access_logs.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/migrate/20210807004941_add_create_at_to_access_logs.rb diff --git a/db/migrate/20210807004941_add_create_at_to_access_logs.rb b/db/migrate/20210807004941_add_create_at_to_access_logs.rb new file mode 100644 index 00000000..0e106061 --- /dev/null +++ b/db/migrate/20210807004941_add_create_at_to_access_logs.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Cambia los msec a datetime para poder agregar por tiempos +class AddCreateAtToAccessLogs < ActiveRecord::Migration[6.1] + def up + add_column :access_logs, :created_at, :datetime, precision: 6 + + create_trigger(compatibility: 1).on(:access_logs).before(:insert) do + 'new.created_at := to_timestamp(new.msec)' + end + + ActiveRecord::Base.connection.execute('update access_logs set created_at = to_timestamp(msec);') + end + + def down + remove_column :access_logs, :created_at + end +end From 016da2852926436142e89fcdf1f80c840496a084 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 3 Sep 2021 15:53:45 -0300 Subject: [PATCH 018/146] Inflexiones para Rollup --- config/initializers/inflections.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 35b309ea..0e18b987 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -11,6 +11,8 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.singular 'licencias', 'licencia' inflect.plural 'rol', 'roles' inflect.singular 'roles', 'rol' + inflect.plural 'rollup', 'rollups' + inflect.singular 'rollups', 'rollup' end ActiveSupport::Inflector.inflections(:es) do |inflect| @@ -24,4 +26,6 @@ ActiveSupport::Inflector.inflections(:es) do |inflect| inflect.singular 'roles', 'rol' inflect.plural 'licencia', 'licencias' inflect.singular 'licencias', 'licencia' + inflect.plural 'rollup', 'rollups' + inflect.singular 'rollups', 'rollup' end From 4e4b5888a35e403133c8d9a0934a09cd6520f9ae Mon Sep 17 00:00:00 2001 From: f Date: Fri, 3 Sep 2021 15:55:30 -0300 Subject: [PATCH 019/146] Peticiones completas --- app/models/access_log.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/access_log.rb b/app/models/access_log.rb index 85cd4c36..0dceb7d7 100644 --- a/app/models/access_log.rb +++ b/app/models/access_log.rb @@ -1,4 +1,9 @@ # frozen_string_literal: true class AccessLog < ApplicationRecord + # Las peticiones completas son las que terminaron bien y se + # respondieron con 200 OK o 304 Not Modified + # + # @see {https://en.wikipedia.org/wiki/List_of_HTTP_status_codes} + scope :completed_requests, -> { where(request_method: 'GET', request_completion: 'OK', status: [200, 304]) } end From 1623ab73dea22fbc63abf759245627926b2a5b63 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 11 Sep 2021 17:00:28 -0300 Subject: [PATCH 020/146] Soportar un campo con una lista de valores predefinidos y elegir uno --- app/models/metadata_predefined_value.rb | 24 +++++++++++++++++++ .../posts/attribute_ro/_predefined_value.haml | 3 +++ .../posts/attributes/_predefined_value.haml | 7 ++++++ 3 files changed, 34 insertions(+) create mode 100644 app/models/metadata_predefined_value.rb create mode 100644 app/views/posts/attribute_ro/_predefined_value.haml create mode 100644 app/views/posts/attributes/_predefined_value.haml diff --git a/app/models/metadata_predefined_value.rb b/app/models/metadata_predefined_value.rb new file mode 100644 index 00000000..9cf36382 --- /dev/null +++ b/app/models/metadata_predefined_value.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Un campo de texto seleccionado de una lista de valores posibles +class MetadataPredefinedValue < MetadataString + # Obtiene todos los valores desde el layout, en un formato compatible + # con options_for_select. + # + # @return [Hash] + def values + @values ||= layout.dig(:metadata, name, 'values', I18n.locale.to_s)&.invert || {} + end + + private + + # Solo permite almacenar los valores predefinidos. + # + # @return [String] + def sanitize(string) + v = super string + return '' unless values.values.include? v + + v + end +end diff --git a/app/views/posts/attribute_ro/_predefined_value.haml b/app/views/posts/attribute_ro/_predefined_value.haml new file mode 100644 index 00000000..67642e2c --- /dev/null +++ b/app/views/posts/attribute_ro/_predefined_value.haml @@ -0,0 +1,3 @@ +%tr{ id: attribute } + %th= post_label_t(attribute, post: post) + %td{ dir: dir, lang: locale }= metadata.value diff --git a/app/views/posts/attributes/_predefined_value.haml b/app/views/posts/attributes/_predefined_value.haml new file mode 100644 index 00000000..b0d21f35 --- /dev/null +++ b/app/views/posts/attributes/_predefined_value.haml @@ -0,0 +1,7 @@ +.form-group + = label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post) + = select_tag(plain_field_name_for(base, attribute), + options_for_select(metadata.values, metadata.value), + **field_options(attribute, metadata), include_blank: t('.empty')) + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata From 9b8c09cb004581d2add73638edb3e1b5f7825eda Mon Sep 17 00:00:00 2001 From: f Date: Sat, 11 Sep 2021 17:06:27 -0300 Subject: [PATCH 021/146] =?UTF-8?q?Soportar=20campos=20n=C3=BAmericos=20co?= =?UTF-8?q?n=20decimales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_float.rb | 31 ++++++++++++++++++++++++ app/views/posts/attribute_ro/_float.haml | 3 +++ app/views/posts/attributes/_float.haml | 6 +++++ 3 files changed, 40 insertions(+) create mode 100644 app/models/metadata_float.rb create mode 100644 app/views/posts/attribute_ro/_float.haml create mode 100644 app/views/posts/attributes/_float.haml diff --git a/app/models/metadata_float.rb b/app/models/metadata_float.rb new file mode 100644 index 00000000..b4288a3b --- /dev/null +++ b/app/models/metadata_float.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# Un campo numérico de punto flotante +class MetadataFloat < MetadataTemplate + # Nada + def default_value + super || nil + end + + def save + return true unless changed? + + self[:value] = value.to_f + self[:value] = encrypt(value) if private? + + true + end + + # Indicarle al navegador que acepte números decimales + # + # @return [Float] + def step + 0.05 + end + + private + + def decrypt(value) + super(value).to_f + end +end diff --git a/app/views/posts/attribute_ro/_float.haml b/app/views/posts/attribute_ro/_float.haml new file mode 100644 index 00000000..67642e2c --- /dev/null +++ b/app/views/posts/attribute_ro/_float.haml @@ -0,0 +1,3 @@ +%tr{ id: attribute } + %th= post_label_t(attribute, post: post) + %td{ dir: dir, lang: locale }= metadata.value diff --git a/app/views/posts/attributes/_float.haml b/app/views/posts/attributes/_float.haml new file mode 100644 index 00000000..6239c613 --- /dev/null +++ b/app/views/posts/attributes/_float.haml @@ -0,0 +1,6 @@ +.form-group + = label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post) + = number_field base, attribute, value: metadata.value, step: metadata.step, + **field_options(attribute, metadata) + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata From a242ceee68c7058ca55fa35eb3721b2cb104b364 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 11 Sep 2021 17:26:44 -0300 Subject: [PATCH 022/146] Siempre guardar el valor de los campos booleanos --- app/models/metadata_boolean.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/metadata_boolean.rb b/app/models/metadata_boolean.rb index 5e4b456f..53a763fd 100644 --- a/app/models/metadata_boolean.rb +++ b/app/models/metadata_boolean.rb @@ -31,6 +31,11 @@ class MetadataBoolean < MetadataTemplate self[:value] = true_values.include? self[:value] end + # Siempre guardar el valor de este campo a menos que sea nulo + def empty? + !value.nil? + end + private # Los valores que evalúan a verdadero From 47096f20b7dd8c96aaa8cdf334e3698d92d10f37 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 11 Sep 2021 19:43:27 -0300 Subject: [PATCH 023/146] =?UTF-8?q?Traducci=C3=B3n=20de=20valores=20vac?= =?UTF-8?q?=C3=ADos?= 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, 4 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index fc194eab..058456b1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -413,6 +413,8 @@ en: destroy: Remove image belongs_to: empty: "(Empty)" + predefined_value: + empty: "(Empty)" draft: label: Draft reorder: diff --git a/config/locales/es.yml b/config/locales/es.yml index e8185391..f5c13c8b 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -421,6 +421,8 @@ es: destroy: 'Eliminar imagen' belongs_to: empty: "(Vacío)" + predefined_value: + empty: "(Vacío)" draft: label: Borrador reorder: From ed213cda9f040e0e8f6d9de29e1da9609a0c3415 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 11 Sep 2021 20:17:35 -0300 Subject: [PATCH 024/146] =?UTF-8?q?Actualizaci=C3=B3n=20de=20cuidados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8ce97f31..8846d2a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,7 +89,7 @@ GEM jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) ast (2.4.2) - autoprefixer-rails (10.3.1.0) + autoprefixer-rails (10.3.3.0) execjs (~> 2) bcrypt (3.1.16-x86_64-linux-musl) bcrypt_pbkdf (1.1.0-x86_64-linux-musl) @@ -196,7 +196,7 @@ GEM railties (>= 5.0.0) fast_blank (1.0.1-x86_64-linux-musl) fast_jsonparser (0.5.0-x86_64-linux-musl) - ffi (1.15.3-x86_64-linux-musl) + ffi (1.15.4-x86_64-linux-musl) flamegraph (0.9.5) forwardable-extended (2.6.0) friendly_id (5.4.2) @@ -296,7 +296,7 @@ GEM sassc (> 2.0.1, < 3.0) jekyll-seo-tag (2.7.1) jekyll (>= 3.8, < 5.0) - jekyll-spree-client (0.1.17) + jekyll-spree-client (0.1.18) fast_blank (~> 1) spree-api-client (>= 0.2.3) jekyll-turbolinks (0.0.5) @@ -341,7 +341,7 @@ GEM method_source (1.0.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2021.0704) + mime-types-data (3.2021.0901) mini_histogram (0.3.1) mini_magick (4.11.0) mini_mime (1.1.1) @@ -386,7 +386,7 @@ GEM rack (2.2.3) rack-cors (1.1.1) rack (>= 2.0.0) - rack-mini-profiler (2.3.2) + rack-mini-profiler (2.3.3) rack (>= 1.2.0) rack-proxy (0.7.0) rack @@ -493,7 +493,7 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.11.0) parser (>= 3.0.1.1) - rubocop-rails (2.11.3) + rubocop-rails (2.12.2) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) @@ -511,7 +511,7 @@ GEM ruby_parser (3.17.0) sexp_processor (~> 4.15, >= 4.15.1) rubyzip (2.3.2) - rugged (1.1.1-x86_64-linux-musl) + rugged (1.2.0-x86_64-linux-musl) safe_yaml (1.0.6) safely_block (0.3.0) errbase (>= 0.1.1) From c601845a27c5f1a7244c4b88b3736cd115b498ff Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 19:50:24 -0300 Subject: [PATCH 025/146] Garantizar que todas las lecturas se hacen dentro del directorio del sitio fixes ##2667 fixes ##2655 fixes ##2640 fixes #2675 fixes #2653 fixes #2635 fixes #2624 fixes #2626 fixes #2627 fixes #2629 fixes #2634 fixes #2636 fixes #2637 fixes #2641 fixes #2642 fixes #2643 fixes #2644 fixes #2645 fixes #2646 fixes #2648 fixes #2649 fixes #2650 fixes #2651 fixes #2654 fixes #2657 fixes #2672 fixes #2676 fixes #2677 fixes #2678 fixes #2681 fixes #2682 fixes #2687 fixes #2688 fixes #2689 fixes #2691 fixes #2692 fixes #2693 --- app/models/site.rb | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 58f20745..ddfe2bc9 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -65,9 +65,6 @@ class Site < ApplicationRecord accepts_nested_attributes_for :deploys, allow_destroy: true - # El sitio en Jekyll - attr_reader :jekyll - # XXX: Es importante incluir luego de los callbacks de :load_jekyll include Site::Index @@ -180,29 +177,28 @@ class Site < ApplicationRecord # Trae los datos del directorio _data dentro del sitio def data - unless @jekyll.data.present? - @jekyll.reader.read_data - - # Define los valores por defecto según la llave buscada - @jekyll.data.default_proc = proc do |data, key| - data[key] = case key - when 'layout' then {} - end + unless jekyll.data.present? + run_in_path do + jekyll.reader.read_data + jekyll.data['layouts'] ||= {} end end - @jekyll.data + jekyll.data end # Traer las colecciones. Todos los artículos van a estar dentro de # colecciones. def collections unless @read - @jekyll.reader.read_collections + run_in_path do + jekyll.reader.read_collections + end + @read = true end - @jekyll.collections + jekyll.collections end # Traer la configuración de forma modificable @@ -290,7 +286,9 @@ class Site < ApplicationRecord # # @return [Hash] def theme_layouts - @jekyll.reader.read_layouts + run_in_path do + jekyll.reader.read_layouts + end end # Trae todos los valores disponibles para un campo @@ -332,6 +330,12 @@ class Site < ApplicationRecord status == 'building' end + def jekyll + run_in_path do + @jekyll ||= Jekyll::Site.new(configuration) + end + end + # Cargar el sitio Jekyll # # TODO: En lugar de leer todo junto de una vez, extraer la carga de @@ -345,10 +349,7 @@ class Site < ApplicationRecord def reload_jekyll! reset - - Dir.chdir(path) do - @jekyll = Jekyll::Site.new(configuration) - end + jekyll end def reload @@ -526,4 +527,8 @@ class Site < ApplicationRecord errors.add(:design_id, I18n.t('activerecord.errors.models.site.attributes.design_id.layout_incompatible.error')) end + + def run_in_path(&block) + Dir.chdir path, &block + end end From 5a324ae71f29616b4661c6b364ee5a3282a5dd14 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 21:00:10 -0300 Subject: [PATCH 026/146] No cortar las columnas --- app/views/posts/index.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 8b776590..c00d59af 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -112,11 +112,11 @@ %span{ lang: post.locale, dir: dir }= category = '/' unless post.front_matter['categories'].last == category - %td + %td.text-nowrap = post.created_at.strftime('%F') %br/ = post.order - %td + %td.text-nowrap - if @usuarie || policy(post).edit? = link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-block' - if @usuarie || policy(post).destroy? From 859b8518c0f722cfd06aaab0bc59259870c67609 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 21:00:48 -0300 Subject: [PATCH 027/146] =?UTF-8?q?Mostrar=20el=20tipo=20de=20art=C3=ADcul?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/posts/index.haml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index c00d59af..5c47f679 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -104,13 +104,13 @@ %span{ lang: post.locale, dir: dir }= post.title - if post.front_matter['draft'].present? %span.badge.badge-primary= I18n.t('posts.attributes.draft.label') - - if post.front_matter['categories'].present? - %br - %small - - post.front_matter['categories'].each do |category| - = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do - %span{ lang: post.locale, dir: dir }= category - = '/' unless post.front_matter['categories'].last == category + %br + %small + = link_to @site.layouts[post.layout].humanized_name, site_posts_path(@site, **@filter_params.merge(layout: post.layout)) + - post.front_matter['categories']&.each do |category| + = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do + %span{ lang: post.locale, dir: dir }= category + = '/' unless post.front_matter['categories'].last == category %td.text-nowrap = post.created_at.strftime('%F') From 8e1f5c5558627efa0721703591d940aa288f9b85 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 21:02:09 -0300 Subject: [PATCH 028/146] =?UTF-8?q?Paginaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 1 + Gemfile.lock | 17 ++++++++++++++++- app/controllers/posts_controller.rb | 4 ++-- config/routes.rb | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 4256e307..db06827d 100644 --- a/Gemfile +++ b/Gemfile @@ -67,6 +67,7 @@ gem 'terminal-table' gem 'validates_hostname' gem 'webpacker' gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git' +gem 'kaminari' # database gem 'hairtrigger' diff --git a/Gemfile.lock b/Gemfile.lock index 33fba3a0..e08bcb05 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -309,6 +309,18 @@ GEM jekyll-write-and-commit-changes (0.1.2) jekyll (~> 4) rugged (~> 1) + kaminari (1.2.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) + actionview + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) + activerecord + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) @@ -345,6 +357,7 @@ GEM mini_histogram (0.3.1) mini_magick (4.11.0) mini_mime (1.1.0) + mini_portile2 (2.5.3) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) @@ -357,7 +370,8 @@ GEM net-ssh (6.1.0) netaddr (2.0.4) nio4r (2.5.7-x86_64-linux-musl) - nokogiri (1.11.7-x86_64-linux) + nokogiri (1.11.7-x86_64-linux-musl) + mini_portile2 (~> 2.5.0) racc (~> 1.4) orm_adapter (0.5.0) parallel (1.20.1) @@ -667,6 +681,7 @@ DEPENDENCIES jekyll-data! jekyll-images jekyll-include-cache + kaminari letter_opener listen (>= 3.0.5, < 3.2) loaf diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 3ef26720..05ae2736 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -24,7 +24,7 @@ class PostsController < ApplicationController # más simple saber si hubo cambios. if stale?([current_usuarie, site, filter_params]) # Todos los artículos de este sitio para el idioma actual - @posts = site.indexed_posts.where(locale: locale) + @posts = site.indexed_posts.where(locale: locale).page(filter_params.delete(:page)) # De este tipo @posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout] # Que estén dentro de la categoría @@ -154,7 +154,7 @@ class PostsController < ApplicationController # # @return [Hash] def filter_params - @filter_params ||= params.permit(:q, :category, :layout).to_h.select { |_, v| v.present? } + @filter_params ||= params.permit(:q, :category, :layout, :page).to_h.select { |_, v| v.present? } end def site diff --git a/config/routes.rb b/config/routes.rb index 2c5f1c60..15ee4150 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,7 @@ Rails.application.routes.draw do scope '(:locale)' do post :'posts/reorder', to: 'posts#reorder' resources :posts do + get 'p/:page', action: :index, on: :collection get :preview, to: 'posts#preview' end end From f90c92dc26ff5e69385153ee1547c461d44210a1 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 21:03:07 -0300 Subject: [PATCH 029/146] =?UTF-8?q?Poder=20navegar=20p=C3=A1ginas=20en=20l?= =?UTF-8?q?a=20lista=20de=20art=C3=ADculos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/posts/index.haml | 22 ++++++++++++++-------- config/locales/en.yml | 2 ++ config/locales/es.yml | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 5c47f679..654210f2 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -72,14 +72,20 @@ %thead %tr %th.border-0.background-white.position-sticky{ style: 'top: 0; z-index: 2', colspan: '4' } - = submit_tag t('posts.reorder.submit'), class: 'btn' - %button.btn{ data: { action: 'reorder#unselect' } } - = t('posts.reorder.unselect') - %span.badge{ data: { target: 'reorder.counter' } } 0 - %button.btn{ data: { action: 'reorder#up' } }= t('posts.reorder.up') - %button.btn{ data: { action: 'reorder#down' } }= t('posts.reorder.down') - %button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top') - %button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom') + .d-flex.flex-row.justify-content-between + %div + = submit_tag t('posts.reorder.submit'), class: 'btn' + %button.btn{ data: { action: 'reorder#unselect' } } + = t('posts.reorder.unselect') + %span.badge{ data: { target: 'reorder.counter' } } 0 + %button.btn{ data: { action: 'reorder#up' } }= t('posts.reorder.up') + %button.btn{ data: { action: 'reorder#down' } }= t('posts.reorder.down') + %button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top') + %button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom') + + %div + = link_to_prev_page @posts, t('posts.prev'), class: 'btn' + = link_to_next_page @posts, t('posts.next'), class: 'btn' %tbody - dir = t("locales.#{@locale}.dir") - size = @posts.size diff --git a/config/locales/en.yml b/config/locales/en.yml index fc194eab..e950fc32 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -376,6 +376,8 @@ en: en: 'English' ar: 'Arabic' posts: + prev: Previous page + next: Next page empty: "There are no results for those search parameters." caption: Post list attribute_ro: diff --git a/config/locales/es.yml b/config/locales/es.yml index e8185391..459d643b 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -384,6 +384,8 @@ es: en: 'inglés' ar: 'árabe' posts: + prev: Página anterior + next: Página siguiente empty: No hay artículos con estos parámetros de búsqueda. caption: Lista de artículos attribute_ro: From 0dece732aadc407b10674158fd86a4460e42e622 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Sep 2021 21:03:28 -0300 Subject: [PATCH 030/146] =?UTF-8?q?Al=20buscar=20eliminar=20la=20paginaci?= =?UTF-8?q?=C3=B3n?= 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 654210f2..90e30966 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -40,7 +40,7 @@ %section.col = render 'layouts/flash' .d-flex.justify-content-between.align-items-center.pl-2-plus.pr-2-plus.mb-2 - %form + %form{ action: site_posts_path } - @filter_params.each do |param, value| - next if param == 'q' %input{ type: 'hidden', name: param, value: value } From 5c2e5fd62ee217880f8881f338a2db8130d37b06 Mon Sep 17 00:00:00 2001 From: f Date: Sun, 26 Sep 2021 19:29:03 -0300 Subject: [PATCH 031/146] =?UTF-8?q?Agregar=20=C3=ADndices=20=C3=BAnicos=20?= =?UTF-8?q?que=20pens=C3=A1bamos=20que=20ten=C3=ADamos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `unique: true` es un parámetro de `add_index` no de `add_column`. --- db/migrate/20210926205448_add_uniqueness.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 db/migrate/20210926205448_add_uniqueness.rb diff --git a/db/migrate/20210926205448_add_uniqueness.rb b/db/migrate/20210926205448_add_uniqueness.rb new file mode 100644 index 00000000..7399ba4c --- /dev/null +++ b/db/migrate/20210926205448_add_uniqueness.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Agrega índices únicos que pensábamos que ya existían. +class AddUniqueness < ActiveRecord::Migration[6.1] + def change + add_index :designs, :name, unique: true + add_index :designs, :gem, unique: true + add_index :licencias, :name, unique: true + end +end From 662b5eeec4da85d4ae9fdd89f21e13501d6ff940 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 4 Oct 2021 14:48:19 -0300 Subject: [PATCH 032/146] guardar y mostrar la url actual en el campo permalink --- app/models/metadata_permalink.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/metadata_permalink.rb b/app/models/metadata_permalink.rb index 58feb9e5..dc65aa86 100644 --- a/app/models/metadata_permalink.rb +++ b/app/models/metadata_permalink.rb @@ -2,6 +2,12 @@ # Este metadato permite generar rutas manuales. class MetadataPermalink < MetadataString + # El valor por defecto una vez creado es la URL que le asigne Jekyll, + # de forma que nunca cambia aunque se cambie el título. + def default_value + document.url unless post.new? + end + # Los permalinks nunca pueden ser privados def private? false From f8b1752c04f08e6599ffd461d6cce3e0f33e1643 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 4 Oct 2021 14:49:14 -0300 Subject: [PATCH 033/146] cambio texto cerrar sesion #2896 --- 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 fc194eab..28678b2f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -163,7 +163,7 @@ en: signature: 'With love, Sutty' breadcrumb: title: 'Your location in Sutty' - logout: Exit + logout: Log out mutual_aid: Mutual aid collaborations: collaborate: diff --git a/config/locales/es.yml b/config/locales/es.yml index e8185391..ee55d9e7 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -163,7 +163,7 @@ es: signature: 'Con cariño, Sutty' breadcrumb: title: 'Tu ubicación en Sutty' - logout: Salir + logout: Cerrar sesión mutual_aid: Ayuda mutua collaborations: collaborate: From 930f88903e5c73c0f5936f3124c34c9605bca837 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 7 Oct 2021 15:24:21 -0300 Subject: [PATCH 034/146] =?UTF-8?q?instalar=20chartkick=20para=20generar?= =?UTF-8?q?=20gr=C3=A1ficos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 1 + Gemfile.lock | 1 + package.json | 4 +++- yarn.lock | 24 ++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 2f5446a0..b5e8664b 100644 --- a/Gemfile +++ b/Gemfile @@ -28,6 +28,7 @@ gem 'jbuilder', '~> 2.5' # Use ActiveModel has_secure_password gem 'bcrypt', '~> 3.1.7' gem 'blazer' +gem 'chartkick' gem 'commonmarker' gem 'devise' gem 'devise-i18n' diff --git a/Gemfile.lock b/Gemfile.lock index 6c873d9b..9d1f512b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -642,6 +642,7 @@ DEPENDENCIES bootstrap (~> 4) brakeman capybara (~> 2.13) + chartkick commonmarker concurrent-ruby-ext database_cleaner diff --git a/package.json b/package.json index 0a2458a6..184f7ebb 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "zepto": "^1.2.0" }, "devDependencies": { - "@types/rails__activestorage": "^6.0.0" + "@types/rails__activestorage": "^6.0.0", + "chart.js": "^3.5.1", + "chartkick": "^4.0.5" } } diff --git a/yarn.lock b/yarn.lock index 11ff78cb..68b7fd23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2119,6 +2119,25 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chart.js@>=3.0.2, chart.js@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.5.1.tgz#73e24d23a4134a70ccdb5e79a917f156b6f3644a" + integrity sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ== + +chartjs-adapter-date-fns@>=2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-2.0.0.tgz#5e53b2f660b993698f936f509c86dddf9ed44c6b" + integrity sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw== + +chartkick@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/chartkick/-/chartkick-4.0.5.tgz#310a60c931e8ceedc39adee2ef8e9d1e474cb0e6" + integrity sha512-xKak4Fsgfvp1hj/LykRKkniDMaZASx2A4TdVc/sfsiNFFNf1m+D7PGwP1vgj1UsbsCjOCSfGWWyJpOYxkUCBug== + optionalDependencies: + chart.js ">=3.0.2" + chartjs-adapter-date-fns ">=2.0.0" + date-fns ">=2.0.0" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2744,6 +2763,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@>=2.0.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.24.0.tgz#7d86dc0d93c87b76b63d213b4413337cfd1c105d" + integrity sha512-6ujwvwgPID6zbI0o7UbURi2vlLDR9uP26+tW6Lg+Ji3w7dd0i3DOcjcClLjLPranT60SSEFBwdSyYwn/ZkPIuw== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" From a7ae7f8e8d7cec044d2d01a49b51bc100e629e23 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 16:31:02 -0300 Subject: [PATCH 035/146] ver cantidad de visitas --- app/controllers/stats_controller.rb | 64 ++++++++++++++++++++++++++--- app/javascript/packs/application.js | 1 + app/policies/site_stat_policy.rb | 4 ++ app/views/stats/index.haml | 19 ++++----- config/locales/en.yml | 9 ++++ config/locales/es.yml | 13 ++++++ config/routes.rb | 1 + 7 files changed, 94 insertions(+), 17 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 07baaf1a..07be68c4 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -5,14 +5,68 @@ class StatsController < ApplicationController include Pundit before_action :authenticate_usuarie! + INTERVALS = %i[hour day week month].freeze + + # XXX: Permitir a Chart.js inyectar su propio CSS + content_security_policy only: :index do |policy| + policy.style_src :self, :unsafe_inline + policy.script_src :self, :unsafe_inline + end + def index @site = find_site authorize SiteStat.new(@site) - # Solo queremos el promedio de tiempo de compilación, no de - # instalación de dependencias. - stats = @site.build_stats.jekyll - @build_avg = stats.average(:seconds).to_f.round(2) - @build_max = stats.maximum(:seconds).to_f.round(2) + @chart_params = { interval: interval } + hostnames + end + + # Genera un gráfico de visitas por dominio asociado a este sitio + def host + @site = find_site + authorize SiteStat.new(@site) + + @stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| + series.each do |serie| + serie[:name] = serie.dig(:dimensions, 'host') + serie[:data].transform_values! do |value| + value * nodes + end + end + end + + render json: @stats + end + + private + + # TODO: Eliminar cuando mergeemos referer-origin + def hostnames + @hostnames ||= [@site.hostname, @site.alternative_hostnames].flatten + end + + # Obtiene y valida los intervalos + # + # @return [Symbol] + def interval + @interval ||= begin + i = params[:interval].to_sym + INTERVALS.include?(i) ? i : :day + end + end + + # Obtiene la cantidad de nodos de Sutty, para poder calcular la + # cantidad de visitas. + # + # Como repartimos las visitas por nodo rotando las IPs en el + # nameserver y los resolvedores de DNS eligen un nameserver + # aleatoriamente, la cantidad de visitas se reparte + # equitativamente. + # + # XXX: Remover cuando podamos centralizar los AccessLog + # + # @return [Integer] + def nodes + @nodes ||= ENV.fetch('NODES', 1).to_i end end diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 6aa3a2e1..492ca736 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -18,6 +18,7 @@ import 'etc' import Rails from '@rails/ujs' import Turbolinks from 'turbolinks' import * as ActiveStorage from '@rails/activestorage' +import 'chartkick/chart.js' Rails.start() Turbolinks.start() diff --git a/app/policies/site_stat_policy.rb b/app/policies/site_stat_policy.rb index a797034c..d11be95d 100644 --- a/app/policies/site_stat_policy.rb +++ b/app/policies/site_stat_policy.rb @@ -12,4 +12,8 @@ class SiteStatPolicy def index? site_stat.site.usuarie? usuarie end + + def host? + index? + end end diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index f49cdd15..b5943690 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -1,17 +1,12 @@ -= render 'layouts/breadcrumb', - crumbs: [link_to(t('sites.index.title'), sites_path), - link_to(@site.name, site_path(@site)), t('.title')] - .row .col %h1= t('.title') %p.lead= t('.help') - %table.table.table-condensed - %tbody - %tr - %td= t('.build.average') - %td= distance_of_time_in_words_if_more_than_a_minute @build_avg - %tr - %td= t('.build.maximum') - %td= distance_of_time_in_words_if_more_than_a_minute @build_max + .mb-3 + - StatsController::INTERVALS.each do |interval| + = link_to t(".#{interval}"), site_stats_path(interval: interval), class: 'btn' + + .mb-3 + %h2= t('.host', count: @hostnames.size) + = line_chart site_stats_host_path(@chart_params), locale: 'es' diff --git a/config/locales/en.yml b/config/locales/en.yml index fc194eab..96250301 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -255,6 +255,15 @@ en: build: average: 'Average building time' maximum: 'Maximum building time' + hour: 'Hourly' + day: 'Daily' + week: 'Weekly' + month: 'Monthly' + year: 'Yearly' + host: + zero: 'Site visits' + one: 'Site visits' + other: 'Visits by site name' sites: donations: url: 'https://donaciones.sutty.nl/en/' diff --git a/config/locales/es.yml b/config/locales/es.yml index e8185391..7fcebcbe 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -260,6 +260,15 @@ es: build: average: 'Tiempo promedio de generación' maximum: 'Tiempo máximo de generación' + hour: 'Por hora' + day: 'Diarias' + week: 'Semanales' + month: 'Mensuales' + year: 'Anuales' + host: + zero: 'Visitas del sitio' + one: 'Visitas del sitio' + other: 'Visitas por nombre del sitio' sites: donations: url: 'https://donaciones.sutty.nl/' @@ -584,3 +593,7 @@ es: edit: 'Editando' usuaries: index: 'Usuaries' + day: 'Día' + week: 'Semana' + month: 'Mes' + year: 'Año' diff --git a/config/routes.rb b/config/routes.rb index 2c5f1c60..0af58080 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -75,5 +75,6 @@ Rails.application.routes.draw do post 'reorder_posts', to: 'sites#reorder_posts' resources :stats, only: [:index] + get :'stats/host', to: 'stats#host' end end From df2b66afe85d806e32aee341fdc4beb5ee5cd873 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:21:09 -0300 Subject: [PATCH 036/146] =?UTF-8?q?llevar=20el=20registro=20de=20las=20rec?= =?UTF-8?q?olecciones=20de=20estad=C3=ADsticas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/stat.rb | 3 +++ db/migrate/20211008201239_create_stats.rb | 12 ++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 app/models/stat.rb create mode 100644 db/migrate/20211008201239_create_stats.rb diff --git a/app/models/stat.rb b/app/models/stat.rb new file mode 100644 index 00000000..cf717b05 --- /dev/null +++ b/app/models/stat.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +class Stat < ApplicationRecord; end diff --git a/db/migrate/20211008201239_create_stats.rb b/db/migrate/20211008201239_create_stats.rb new file mode 100644 index 00000000..e1aff8f6 --- /dev/null +++ b/db/migrate/20211008201239_create_stats.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Una tabla que lleva el recuento de recolección de estadísticas, solo +# es necesario para saber cuándo se hicieron, si se hicieron y usar como +# caché. +class CreateStats < ActiveRecord::Migration[6.1] + def change + create_table :stats do |t| + t.timestamps + end + end +end From a2e4e0ab89910f85632ad231bbc2bdc01e69836b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:24:19 -0300 Subject: [PATCH 037/146] =?UTF-8?q?informar=20hace=20cu=C3=A1nto=20se=20ac?= =?UTF-8?q?tualizaron=20los=20datos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 5 +++++ app/views/stats/index.haml | 5 +++++ config/locales/en.yml | 4 +--- config/locales/es.yml | 4 +--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 07be68c4..8d1575bd 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -19,6 +19,7 @@ class StatsController < ApplicationController @chart_params = { interval: interval } hostnames + last_stat end # Genera un gráfico de visitas por dominio asociado a este sitio @@ -40,6 +41,10 @@ class StatsController < ApplicationController private + def last_stat + @last_stat ||= Stat.last + end + # TODO: Eliminar cuando mergeemos referer-origin def hostnames @hostnames ||= [@site.hostname, @site.alternative_hostnames].flatten diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index b5943690..e77454b1 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -2,6 +2,11 @@ .col %h1= t('.title') %p.lead= t('.help') + %p + %small + = t('.last_update') + %time{ datetime: @last_stat.created_at } + "#{time_ago_in_words @last_stat.created_at}." .mb-3 - StatsController::INTERVALS.each do |interval| diff --git a/config/locales/en.yml b/config/locales/en.yml index 96250301..623d8c2e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -252,9 +252,7 @@ en: help: | These statistics show information about how your site is generated and how many resources it uses. - build: - average: 'Average building time' - maximum: 'Maximum building time' + last_update: 'Updated every hour. Last update on ' hour: 'Hourly' day: 'Daily' week: 'Weekly' diff --git a/config/locales/es.yml b/config/locales/es.yml index 7fcebcbe..4085a862 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -257,9 +257,7 @@ es: help: | Las estadísticas visibilizan información sobre cómo se genera y cuántos recursos utiliza tu sitio. - build: - average: 'Tiempo promedio de generación' - maximum: 'Tiempo máximo de generación' + last_update: 'Actualizadas cada hora. Última actualización hace ' hour: 'Por hora' day: 'Diarias' week: 'Semanales' From cfb2d7a61d1c29da08d9dd000d7d9039fe2af54e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:33:31 -0300 Subject: [PATCH 038/146] todas las peticiones necesitan une usuarie --- app/controllers/stats_controller.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 8d1575bd..0c185329 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -4,6 +4,7 @@ class StatsController < ApplicationController include Pundit before_action :authenticate_usuarie! + before_action :authorize_stats INTERVALS = %i[hour day week month].freeze @@ -14,9 +15,6 @@ class StatsController < ApplicationController end def index - @site = find_site - authorize SiteStat.new(@site) - @chart_params = { interval: interval } hostnames last_stat @@ -24,8 +22,6 @@ class StatsController < ApplicationController # Genera un gráfico de visitas por dominio asociado a este sitio def host - @site = find_site - authorize SiteStat.new(@site) @stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| series.each do |serie| @@ -45,6 +41,11 @@ class StatsController < ApplicationController @last_stat ||= Stat.last end + def authorize_stats + @site = find_site + authorize SiteStat.new(@site) + end + # TODO: Eliminar cuando mergeemos referer-origin def hostnames @hostnames ||= [@site.hostname, @site.alternative_hostnames].flatten From 38090d7de72d5cfdb1cad2e4349479ed17f04221 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:34:16 -0300 Subject: [PATCH 039/146] resaltar el intervalo seleccionado --- app/views/stats/index.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index e77454b1..63aa76cd 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -10,7 +10,7 @@ .mb-3 - StatsController::INTERVALS.each do |interval| - = link_to t(".#{interval}"), site_stats_path(interval: interval), class: 'btn' + = link_to t(".#{interval}"), site_stats_path(interval: interval), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" .mb-3 %h2= t('.host', count: @hostnames.size) From d2b1220df6f74ef46486beeb49ce9b1fd833658d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:35:40 -0300 Subject: [PATCH 040/146] informar cuando no hay datos --- app/controllers/stats_controller.rb | 24 ++++++++++++++++++++++++ config/locales/en.yml | 2 ++ config/locales/es.yml | 2 ++ 3 files changed, 28 insertions(+) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 0c185329..9cd1e5de 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -3,6 +3,8 @@ # Estadísticas del sitio class StatsController < ApplicationController include Pundit + include ActionView::Helpers::DateHelper + before_action :authenticate_usuarie! before_action :authorize_stats @@ -18,6 +20,7 @@ class StatsController < ApplicationController @chart_params = { interval: interval } hostnames last_stat + chart_options end # Genera un gráfico de visitas por dominio asociado a este sitio @@ -51,6 +54,27 @@ class StatsController < ApplicationController @hostnames ||= [@site.hostname, @site.alternative_hostnames].flatten end + # Opciones por defecto para los gráficos. + # + # La invitación a volver dentro de X tiempo es para dar un estimado de + # cuándo habrá información disponible, porque Rollup genera intervalos + # completos (¿aunque dice que no?) + # + # La diferencia se calcula sumando el intervalo a la hora de última + # toma de estadísticas y restando el tiempo que pasó desde ese + # momento. + def chart_options + time = last_stat.created_at + (1.send(interval)) + please_return_at = { please_return_at: distance_of_time_in_words(Time.now, time) } + + @chart_options ||= { + locale: I18n.locale, + empty: I18n.t('stats.index.empty', **please_return_at), + loading: I18n.t('stats.index.loading'), + html: %(
%{loading}
) + } + end + # Obtiene y valida los intervalos # # @return [Symbol] diff --git a/config/locales/en.yml b/config/locales/en.yml index 623d8c2e..58e0e726 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -253,6 +253,8 @@ en: These statistics show information about how your site is generated and how many resources it uses. last_update: 'Updated every hour. Last update on ' + empty: 'There is no enough information yet. We invite you to come back in %{please_return_at}!' + loading: 'Loading...' hour: 'Hourly' day: 'Daily' week: 'Weekly' diff --git a/config/locales/es.yml b/config/locales/es.yml index 4085a862..8df68896 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -258,6 +258,8 @@ es: Las estadísticas visibilizan información sobre cómo se genera y cuántos recursos utiliza tu sitio. last_update: 'Actualizadas cada hora. Última actualización hace ' + empty: 'Todavía no hay información suficiente. Te invitamos a volver en %{please_return_at} :)' + loading: 'Cargando...' hour: 'Por hora' day: 'Diarias' week: 'Semanales' From ef0055db0535492b62a95f6cd85970ead819ddb3 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:36:31 -0300 Subject: [PATCH 041/146] =?UTF-8?q?agrupar=20por=20a=C3=B1o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 9cd1e5de..a0937477 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -8,7 +8,7 @@ class StatsController < ApplicationController before_action :authenticate_usuarie! before_action :authorize_stats - INTERVALS = %i[hour day week month].freeze + INTERVALS = %i[hour day week month year].freeze # XXX: Permitir a Chart.js inyectar su propio CSS content_security_policy only: :index do |policy| From 8e9401036ce4f3c64aff0db21263d13e56e14e3b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:38:02 -0300 Subject: [PATCH 042/146] =?UTF-8?q?cachear=20los=20resultados=20hasta=20la?= =?UTF-8?q?=20pr=C3=B3xima=20actualizaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index a0937477..0eae584b 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -25,17 +25,18 @@ class StatsController < ApplicationController # Genera un gráfico de visitas por dominio asociado a este sitio def host - - @stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| - series.each do |serie| - serie[:name] = serie.dig(:dimensions, 'host') - serie[:data].transform_values! do |value| - value * nodes + if stale? [last_stat, hostnames, interval] + stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| + series.each do |serie| + serie[:name] = serie.dig(:dimensions, 'host') + serie[:data].transform_values! do |value| + value * nodes + end end end end - render json: @stats + render json: stats end private From 224ea1ebc54ef6621614474eeaedd33f5dc633e3 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:39:55 -0300 Subject: [PATCH 043/146] =?UTF-8?q?mostrar=20gr=C3=A1ficos=20de=20recursos?= =?UTF-8?q?=20utilizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 25 +++++++++++++++++++++++-- app/views/stats/index.haml | 11 +++++++++-- config/locales/en.yml | 18 +++++++++++++++--- config/locales/es.yml | 18 +++++++++++++++--- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 0eae584b..d41573e2 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -9,6 +9,7 @@ class StatsController < ApplicationController before_action :authorize_stats INTERVALS = %i[hour day week month year].freeze + RESOURCES = %i[builds space_used build_time].freeze # XXX: Permitir a Chart.js inyectar su propio CSS content_security_policy only: :index do |policy| @@ -34,9 +35,22 @@ class StatsController < ApplicationController end end end - end - render json: stats + render json: stats + end + end + + def resources + if stale? [last_stat, interval, resource] + options = { + interval: interval, + dimensions: { + deploy_id: @site.deploys.where(type: 'DeployLocal').pluck(:id).first + } + } + + render json: Rollup.series(resource, **options) + end end private @@ -86,6 +100,13 @@ class StatsController < ApplicationController end end + def resource + @resource ||= begin + r = params[:resource].to_sym + RESOURCES.include?(r) ? r : :builds + end + end + # Obtiene la cantidad de nodos de Sutty, para poder calcular la # cantidad de visitas. # diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 63aa76cd..0251955e 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -13,5 +13,12 @@ = link_to t(".#{interval}"), site_stats_path(interval: interval), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" .mb-3 - %h2= t('.host', count: @hostnames.size) - = line_chart site_stats_host_path(@chart_params), locale: 'es' + %h2= t('.host.title', count: @hostnames.size) + %p.lead= t('.host.description') + = line_chart site_stats_host_path(@chart_params), **@chart_options + + - StatsController::RESOURCES.each do |resource| + .mb-3 + %h2= t(".resources.#{resource}.title") + %p.lead= t(".resources.#{resource}.description") + = line_chart site_stats_resources_path(resource: resource, **@chart_params), **@chart_options diff --git a/config/locales/en.yml b/config/locales/en.yml index 58e0e726..08313a03 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -261,9 +261,21 @@ en: month: 'Monthly' year: 'Yearly' host: - zero: 'Site visits' - one: 'Site visits' - other: 'Visits by site name' + title: + zero: 'Site visits' + one: 'Site visits' + other: 'Visits by site name' + description: 'Counts visited pages on your site, grouped by domain names in use.' + resources: + builds: + title: 'Site publication' + description: 'Times you published your site.' + space_used: + title: 'Server disk usage' + description: 'Average storage space used by your site.' + build_time: + title: 'Publication time' + description: 'Average time your site takes to build.' sites: donations: url: 'https://donaciones.sutty.nl/en/' diff --git a/config/locales/es.yml b/config/locales/es.yml index 8df68896..b1161287 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -266,9 +266,21 @@ es: month: 'Mensuales' year: 'Anuales' host: - zero: 'Visitas del sitio' - one: 'Visitas del sitio' - other: 'Visitas por nombre del sitio' + title: + zero: 'Visitas del sitio' + one: 'Visitas del sitio' + other: 'Visitas por nombre del sitio' + description: 'Cuenta la cantidad de páginas visitadas en tu sitio, dividida por los nombres de dominio en uso.' + resources: + builds: + title: 'Publicaciones del sitio' + description: 'Cantidad de veces que publicaste tu sitio.' + space_used: + title: 'Espacio utilizado en el servidor' + description: 'Espacio en disco que ocupa en promedio tu sitio.' + build_time: + title: 'Tiempo de publicación' + description: 'Tiempo promedio que toma en publicarse tu sitio.' sites: donations: url: 'https://donaciones.sutty.nl/' From 833213ec80c343379ccdd566aaa86e92e051b9ad Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:40:16 -0300 Subject: [PATCH 044/146] agregar opciones a cada recurso --- app/controllers/stats_controller.rb | 6 ++++++ app/views/stats/index.haml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index d41573e2..8045a653 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -10,6 +10,12 @@ class StatsController < ApplicationController INTERVALS = %i[hour day week month year].freeze RESOURCES = %i[builds space_used build_time].freeze + EXTRA_OPTIONS = { + builds: {}, + space_used: { bytes: true }, + build_time: {} + }.freeze + # XXX: Permitir a Chart.js inyectar su propio CSS content_security_policy only: :index do |policy| diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 0251955e..101dee1e 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -21,4 +21,4 @@ .mb-3 %h2= t(".resources.#{resource}.title") %p.lead= t(".resources.#{resource}.description") - = line_chart site_stats_resources_path(resource: resource, **@chart_params), **@chart_options + = line_chart site_stats_resources_path(resource: resource, **@chart_params), **@chart_options.merge(StatsController::EXTRA_OPTIONS[resource]) From 86f1ac450469cfce2d53be41b7f9d594e2d3a985 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:40:52 -0300 Subject: [PATCH 045/146] =?UTF-8?q?fixup!=20mostrar=20gr=C3=A1ficos=20de?= =?UTF-8?q?=20recursos=20utilizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/policies/site_stat_policy.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/policies/site_stat_policy.rb b/app/policies/site_stat_policy.rb index d11be95d..6c98c775 100644 --- a/app/policies/site_stat_policy.rb +++ b/app/policies/site_stat_policy.rb @@ -16,4 +16,8 @@ class SiteStatPolicy def host? index? end + + def resources? + index? + end end From 51c2fdf6d6899d5b931e2ac301007d33deb641b5 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:41:07 -0300 Subject: [PATCH 046/146] =?UTF-8?q?fixup!=20fixup!=20mostrar=20gr=C3=A1fic?= =?UTF-8?q?os=20de=20recursos=20utilizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index 0af58080..b59266fb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,5 +76,6 @@ Rails.application.routes.draw do resources :stats, only: [:index] get :'stats/host', to: 'stats#host' + get :'stats/resources', to: 'stats#resources' end end From 034245595587990cd73ca3a34e945d2127471c9d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 8 Oct 2021 18:42:34 -0300 Subject: [PATCH 047/146] =?UTF-8?q?encontrar=20p=C3=A1ginas=20y=20distingu?= =?UTF-8?q?ir=20si=20fueron=20cyborgs=20o=20no?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/access_log.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/models/access_log.rb b/app/models/access_log.rb index 0dceb7d7..3a066b33 100644 --- a/app/models/access_log.rb +++ b/app/models/access_log.rb @@ -6,4 +6,7 @@ class AccessLog < ApplicationRecord # # @see {https://en.wikipedia.org/wiki/List_of_HTTP_status_codes} scope :completed_requests, -> { where(request_method: 'GET', request_completion: 'OK', status: [200, 304]) } + scope :non_robots, -> { where(crawler: false) } + scope :robots, -> { where(crawler: true) } + scope :pages, -> { where(sent_http_content_type: ['text/html', 'text/html; charset=utf-8', 'text/html; charset=UTF-8']) } end From 306d1ed983f69456a219a6c5fae47ea5e98ff8b1 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 14:45:34 -0300 Subject: [PATCH 048/146] =?UTF-8?q?recolectar=20estad=C3=ADsticas=20una=20?= =?UTF-8?q?vez=20por=20hora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/stat_collection_job.rb | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 app/jobs/stat_collection_job.rb diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb new file mode 100644 index 00000000..c36d036c --- /dev/null +++ b/app/jobs/stat_collection_job.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +# Genera resúmenes de información para poder mostrar estadísticas y se +# corre regularmente a sí misma. +class StatCollectionJob < ApplicationJob + class CrontabException < StandardError; end + + # Descartar y notificar si pasó algo más. + # + # XXX: En realidad deberíamos seguir reintentando? + discard_on(Exception) do |_, error| + ExceptionNotifier.notify_exception error + end + + # Correr indefinidamente una vez por hora. + # + # XXX: El orden importa, si el descarte viene después, nunca se va a + # reintentar. + retry_on(StatCollectionJob::CrontabException, wait: 1.hour, attempts: Float::INFINITY) + + COLUMNS = %i[uri].freeze + + def perform(once: false) + Stat::INTERVALS.each do |interval| + options = { interval: interval } + + # Visitas por hostname + AccessLog.completed_requests.group(:host).rollup('host', **options) + + combined_columns **options + stats_by_site **options + end + + # Registrar que se hicieron todas las recolecciones + Stat.create! + + raise CrontabException unless once + end + + private + + # Combinación de columnas + def combined_columns(**options) + COLUMNS.each do |column| + AccessLog.completed_requests.group(:host, column).rollup("hostname|#{column}", **options) + end + end + + # Uso de recursos por cada sitio. + # + # XXX: En realidad se agrupan por el deploy_id, que siempre será el + # del DeployLocal. + def stats_by_site(**options) + Site.find_each do |site| + site.build_stats.jekyll.group(:deploy_id).rollup('builds', **options) + + site.build_stats.jekyll.group(:deploy_id).rollup('space_used', **options) do |rollup| + rollup.average(:bytes) + end + + site.build_stats.jekyll.group(:deploy_id).rollup('build_time', **options) do |rollup| + rollup.average(:seconds) + end + end + end +end From e35cbe79eb53f3dceb082865360e060c827a237c Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 14:46:58 -0300 Subject: [PATCH 049/146] =?UTF-8?q?recolectar=20visitas=20a=20p=C3=A1ginas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/stat_collection_job.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb index c36d036c..04f62b8a 100644 --- a/app/jobs/stat_collection_job.rb +++ b/app/jobs/stat_collection_job.rb @@ -25,10 +25,10 @@ class StatCollectionJob < ApplicationJob options = { interval: interval } # Visitas por hostname - AccessLog.completed_requests.group(:host).rollup('host', **options) + AccessLog.completed_requests.non_robots.pages.group(:host).rollup('host', **options) - combined_columns **options - stats_by_site **options + combined_columns(**options) + stats_by_site(**options) end # Registrar que se hicieron todas las recolecciones @@ -42,7 +42,7 @@ class StatCollectionJob < ApplicationJob # Combinación de columnas def combined_columns(**options) COLUMNS.each do |column| - AccessLog.completed_requests.group(:host, column).rollup("hostname|#{column}", **options) + AccessLog.completed_requests.non_robots.pages.group(:host, column).rollup("host|#{column}", **options) end end From 11568e6ce8e8471077278590cbd7de5a67b6003d Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 15:36:14 -0300 Subject: [PATCH 050/146] no distinguir entre todas las uris MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit para poder buscar descargas de archivos binarios después --- app/jobs/stat_collection_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb index 04f62b8a..5b7da160 100644 --- a/app/jobs/stat_collection_job.rb +++ b/app/jobs/stat_collection_job.rb @@ -42,7 +42,7 @@ class StatCollectionJob < ApplicationJob # Combinación de columnas def combined_columns(**options) COLUMNS.each do |column| - AccessLog.completed_requests.non_robots.pages.group(:host, column).rollup("host|#{column}", **options) + AccessLog.completed_requests.non_robots.group(:host, column).rollup("host|#{column}", **options) end end From c927a56befb1128deb3e631774e1084361c93744 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 15:47:42 -0300 Subject: [PATCH 051/146] ejecutar una vez por hora exacto --- app/jobs/stat_collection_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb index 5b7da160..6f8470b8 100644 --- a/app/jobs/stat_collection_job.rb +++ b/app/jobs/stat_collection_job.rb @@ -16,7 +16,7 @@ class StatCollectionJob < ApplicationJob # # XXX: El orden importa, si el descarte viene después, nunca se va a # reintentar. - retry_on(StatCollectionJob::CrontabException, wait: 1.hour, attempts: Float::INFINITY) + retry_on(StatCollectionJob::CrontabException, wait: 1.hour, attempts: Float::INFINITY, jitter: 0) COLUMNS = %i[uri].freeze From f36ea9629de280b7ef110d8d66d3f05097ce7520 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 15:50:38 -0300 Subject: [PATCH 052/146] centralizar valores --- app/controllers/stats_controller.rb | 9 +++------ app/models/stat.rb | 5 ++++- app/views/stats/index.haml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 8045a653..093fbe93 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -8,15 +8,12 @@ class StatsController < ApplicationController before_action :authenticate_usuarie! before_action :authorize_stats - INTERVALS = %i[hour day week month year].freeze - RESOURCES = %i[builds space_used build_time].freeze EXTRA_OPTIONS = { builds: {}, space_used: { bytes: true }, build_time: {} }.freeze - # XXX: Permitir a Chart.js inyectar su propio CSS content_security_policy only: :index do |policy| policy.style_src :self, :unsafe_inline @@ -85,7 +82,7 @@ class StatsController < ApplicationController # toma de estadísticas y restando el tiempo que pasó desde ese # momento. def chart_options - time = last_stat.created_at + (1.send(interval)) + time = last_stat.created_at + 1.try(interval) please_return_at = { please_return_at: distance_of_time_in_words(Time.now, time) } @chart_options ||= { @@ -102,14 +99,14 @@ class StatsController < ApplicationController def interval @interval ||= begin i = params[:interval].to_sym - INTERVALS.include?(i) ? i : :day + Stat::INTERVALS.include?(i) ? i : :day end end def resource @resource ||= begin r = params[:resource].to_sym - RESOURCES.include?(r) ? r : :builds + Stat::RESOURCES.include?(r) ? r : :builds end end diff --git a/app/models/stat.rb b/app/models/stat.rb index cf717b05..1e3af9e9 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -1,3 +1,6 @@ # frozen_string_literal: true -class Stat < ApplicationRecord; end +class Stat < ApplicationRecord + INTERVALS = %i[hour day week month year].freeze + RESOURCES = %i[builds space_used build_time].freeze +end diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 101dee1e..992200a4 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -9,7 +9,7 @@ "#{time_ago_in_words @last_stat.created_at}." .mb-3 - - StatsController::INTERVALS.each do |interval| + - Stat::INTERVALS.each do |interval| = link_to t(".#{interval}"), site_stats_path(interval: interval), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" .mb-3 @@ -17,7 +17,7 @@ %p.lead= t('.host.description') = line_chart site_stats_host_path(@chart_params), **@chart_options - - StatsController::RESOURCES.each do |resource| + - Stat::RESOURCES.each do |resource| .mb-3 %h2= t(".resources.#{resource}.title") %p.lead= t(".resources.#{resource}.description") From 5ca8e3c923e88bc696f5644f1053a50ddd345e0d Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 15:52:18 -0300 Subject: [PATCH 053/146] usar guards --- app/controllers/stats_controller.rb | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 093fbe93..1dc468bb 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -29,31 +29,31 @@ class StatsController < ApplicationController # Genera un gráfico de visitas por dominio asociado a este sitio def host - if stale? [last_stat, hostnames, interval] - stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| - series.each do |serie| - serie[:name] = serie.dig(:dimensions, 'host') - serie[:data].transform_values! do |value| - value * nodes - end + return unless stale? [last_stat, hostnames, interval] + + stats = Rollup.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series| + series.each do |serie| + serie[:name] = serie.dig(:dimensions, 'host') + serie[:data].transform_values! do |value| + value * nodes end end - - render json: stats end + + render json: stats end def resources - if stale? [last_stat, interval, resource] - options = { - interval: interval, - dimensions: { - deploy_id: @site.deploys.where(type: 'DeployLocal').pluck(:id).first - } - } + return unless stale? [last_stat, interval, resource] - render json: Rollup.series(resource, **options) - end + options = { + interval: interval, + dimensions: { + deploy_id: @site.deploys.where(type: 'DeployLocal').pluck(:id).first + } + } + + render json: Rollup.series(resource, **options) end private From 6c485e5e18abf29d3b3cea0de584503417006c6e Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 17:27:45 -0300 Subject: [PATCH 054/146] =?UTF-8?q?obtener=20estad=C3=ADsticas=20de=20cual?= =?UTF-8?q?quier=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 39 +++++++++++++++++++++++++++++ app/policies/site_stat_policy.rb | 4 +++ app/views/stats/index.haml | 18 ++++++++++++- config/locales/en.yml | 6 +++++ config/locales/es.yml | 10 +++++--- config/routes.rb | 1 + 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 1dc468bb..ca834ebd 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -25,6 +25,7 @@ class StatsController < ApplicationController hostnames last_stat chart_options + normalized_urls end # Genera un gráfico de visitas por dominio asociado a este sitio @@ -56,6 +57,22 @@ class StatsController < ApplicationController render json: Rollup.series(resource, **options) end + def uris + return unless stale? [last_stat, hostnames, interval, normalized_urls] + + options = { host: hostnames, uri: normalized_paths } + stats = Rollup.where_dimensions(**options).multi_series('host|uri', interval: interval).tap do |series| + series.each do |serie| + serie[:name] = serie.dig(:dimensions).slice('host', 'uri').values.join.sub('/index.html', '/') + serie[:data].transform_values! do |value| + value * nodes + end + end + end + + render json: stats + end + private def last_stat @@ -72,6 +89,28 @@ class StatsController < ApplicationController @hostnames ||= [@site.hostname, @site.alternative_hostnames].flatten end + # Normalizar las URLs + # + # @return [Array] + def normalized_urls + @normalized_urls ||= params.permit(:urls).try(:[], + :urls)&.split("\n")&.map(&:strip)&.select(&:present?)&.select do |uri| + uri.start_with? 'https://' + end&.map do |u| + # XXX: Eliminar + # @see {https://0xacab.org/sutty/containers/nginx/-/merge_requests/1} + next u unless u.end_with? '/' + + "#{u}index.html" + end&.uniq || [] + end + + def normalized_paths + @normalized_paths ||= normalized_urls.map do |u| + "/#{u.split('/', 4).last}" + end + end + # Opciones por defecto para los gráficos. # # La invitación a volver dentro de X tiempo es para dar un estimado de diff --git a/app/policies/site_stat_policy.rb b/app/policies/site_stat_policy.rb index 6c98c775..cb62b507 100644 --- a/app/policies/site_stat_policy.rb +++ b/app/policies/site_stat_policy.rb @@ -20,4 +20,8 @@ class SiteStatPolicy def resources? index? end + + def uris? + index? + end end diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 992200a4..1ce61a98 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -10,13 +10,29 @@ .mb-3 - Stat::INTERVALS.each do |interval| - = link_to t(".#{interval}"), site_stats_path(interval: interval), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" + = link_to t(".#{interval}"), site_stats_path(interval: interval, urls: params[:urls]), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" .mb-3 %h2= t('.host.title', count: @hostnames.size) %p.lead= t('.host.description') = line_chart site_stats_host_path(@chart_params), **@chart_options + .mb-3 + - original_urls = params[:urls]&.split("\n")&.map(&:strip) + - rows = original_urls.size.zero? ? 3 : original_urls.size + %h2= t('.urls.title') + %p.lead= t('.urls.description') + %form + %input{ type: 'hidden', name: 'interval', value: @interval } + .form-group + %label{ for: 'urls' }= t('.urls.label') + %textarea#urls.form-control{ name: 'urls', autocomplete: 'on', required: true, rows: rows, aria_describedby: 'help-urls' }= params[:urls] + %small#help-urls.feedback.form-text.text-muted= t('.urls.help') + .form-group + %button.btn{ type: 'submit' }= t('.urls.submit') + - if @normalized_urls.present? + = line_chart site_stats_uris_path(urls: params[:urls], **@chart_params), **@chart_options + - Stat::RESOURCES.each do |resource| .mb-3 %h2= t(".resources.#{resource}.title") diff --git a/config/locales/en.yml b/config/locales/en.yml index 08313a03..af864e7b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -266,6 +266,12 @@ en: one: 'Site visits' other: 'Visits by site name' description: 'Counts visited pages on your site, grouped by domain names in use.' + urls: + title: 'Visits by URL' + description: 'Counts visits or downloads on any URL.' + label: 'URLs ("links")' + help: 'Copy and paste a single URL per line' + submit: 'Get stats' resources: builds: title: 'Site publication' diff --git a/config/locales/es.yml b/config/locales/es.yml index b1161287..7d0fe2bb 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -271,6 +271,12 @@ es: one: 'Visitas del sitio' other: 'Visitas por nombre del sitio' description: 'Cuenta la cantidad de páginas visitadas en tu sitio, dividida por los nombres de dominio en uso.' + urls: + title: 'Visitas por dirección' + description: 'Cantidad de visitas o descargas por dirección.' + label: 'Direcciones web ("links", vínculos)' + help: 'Copia y pega una dirección por línea.' + submit: 'Obtener estadísticas' resources: builds: title: 'Publicaciones del sitio' @@ -605,7 +611,3 @@ es: edit: 'Editando' usuaries: index: 'Usuaries' - day: 'Día' - week: 'Semana' - month: 'Mes' - year: 'Año' diff --git a/config/routes.rb b/config/routes.rb index b59266fb..1b0f9e0b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,6 +76,7 @@ Rails.application.routes.draw do resources :stats, only: [:index] get :'stats/host', to: 'stats#host' + get :'stats/uris', to: 'stats#uris' get :'stats/resources', to: 'stats#resources' end end From 7ab2ec5933613ce23cff5ab17e9141e0cf65c7ac Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 17:28:26 -0300 Subject: [PATCH 055/146] =?UTF-8?q?no=20fallar=20si=20el=20intervalo=20est?= =?UTF-8?q?=C3=A1=20vac=C3=ADo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/stats_controller.rb | 2 +- app/views/stats/index.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index ca834ebd..a5ca04e1 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -137,7 +137,7 @@ class StatsController < ApplicationController # @return [Symbol] def interval @interval ||= begin - i = params[:interval].to_sym + i = params[:interval]&.to_sym Stat::INTERVALS.include?(i) ? i : :day end end diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 1ce61a98..d437aac1 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -10,7 +10,7 @@ .mb-3 - Stat::INTERVALS.each do |interval| - = link_to t(".#{interval}"), site_stats_path(interval: interval, urls: params[:urls]), class: "btn #{'btn-primary active' if params[:interval].to_sym == interval}" + = link_to t(".#{interval}"), site_stats_path(interval: interval, urls: params[:urls]), class: "btn #{'btn-primary active' if @interval == interval}" .mb-3 %h2= t('.host.title', count: @hostnames.size) From 5dad13bc3c4ff384ae44dc82ea9c9d5435d49832 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 17:28:56 -0300 Subject: [PATCH 056/146] =?UTF-8?q?m=C3=A1s=20espacio=20entre=20los=20gr?= =?UTF-8?q?=C3=A1ficos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/stats/index.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index d437aac1..e4ef5f61 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -8,16 +8,16 @@ %time{ datetime: @last_stat.created_at } "#{time_ago_in_words @last_stat.created_at}." - .mb-3 + .mb-5 - Stat::INTERVALS.each do |interval| = link_to t(".#{interval}"), site_stats_path(interval: interval, urls: params[:urls]), class: "btn #{'btn-primary active' if @interval == interval}" - .mb-3 + .mb-5 %h2= t('.host.title', count: @hostnames.size) %p.lead= t('.host.description') = line_chart site_stats_host_path(@chart_params), **@chart_options - .mb-3 + .mb-5 - original_urls = params[:urls]&.split("\n")&.map(&:strip) - rows = original_urls.size.zero? ? 3 : original_urls.size %h2= t('.urls.title') @@ -34,7 +34,7 @@ = line_chart site_stats_uris_path(urls: params[:urls], **@chart_params), **@chart_options - Stat::RESOURCES.each do |resource| - .mb-3 + .mb-5 %h2= t(".resources.#{resource}.title") %p.lead= t(".resources.#{resource}.description") = line_chart site_stats_resources_path(resource: resource, **@chart_params), **@chart_options.merge(StatsController::EXTRA_OPTIONS[resource]) From fd2e2509d0e5f681c8866cf1c4eecdd51aac2275 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 17:29:09 -0300 Subject: [PATCH 057/146] sin comillas --- app/views/stats/index.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index e4ef5f61..4119f8ae 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -6,7 +6,7 @@ %small = t('.last_update') %time{ datetime: @last_stat.created_at } - "#{time_ago_in_words @last_stat.created_at}." + #{time_ago_in_words @last_stat.created_at}. .mb-5 - Stat::INTERVALS.each do |interval| From 810f71e9c1348825303b990299ed7ad03e767bd7 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 18:25:43 -0300 Subject: [PATCH 058/146] =?UTF-8?q?contar=20por=20qu=C3=A9=20mostramos=20l?= =?UTF-8?q?os=20recursos=20usados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/stats/index.haml | 6 +++++- config/locales/en.yml | 6 ++++-- config/locales/es.yml | 10 ++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index 4119f8ae..e69c2546 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -33,8 +33,12 @@ - if @normalized_urls.present? = line_chart site_stats_uris_path(urls: params[:urls], **@chart_params), **@chart_options + .mb-5 + %h2= t('.resources.title') + %p.lead= t('.resources.description') + - Stat::RESOURCES.each do |resource| .mb-5 - %h2= t(".resources.#{resource}.title") + %h3= t(".resources.#{resource}.title") %p.lead= t(".resources.#{resource}.description") = line_chart site_stats_resources_path(resource: resource, **@chart_params), **@chart_options.merge(StatsController::EXTRA_OPTIONS[resource]) diff --git a/config/locales/en.yml b/config/locales/en.yml index af864e7b..be327035 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -264,15 +264,17 @@ en: title: zero: 'Site visits' one: 'Site visits' - other: 'Visits by site name' + other: 'Visits by domain name' description: 'Counts visited pages on your site, grouped by domain names in use.' urls: title: 'Visits by URL' description: 'Counts visits or downloads on any URL.' label: 'URLs ("links")' help: 'Copy and paste a single URL per line' - submit: 'Get stats' + submit: 'Update graph' resources: + title: 'Resource usage' + description: "In this section you can find statistics on your site's use of Sutty's shared resources" builds: title: 'Site publication' description: 'Times you published your site.' diff --git a/config/locales/es.yml b/config/locales/es.yml index 7d0fe2bb..774a8cfd 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -269,15 +269,17 @@ es: title: zero: 'Visitas del sitio' one: 'Visitas del sitio' - other: 'Visitas por nombre del sitio' - description: 'Cuenta la cantidad de páginas visitadas en tu sitio, dividida por los nombres de dominio en uso.' + other: 'Visitas agrupadas por nombre de dominio del sitio' + description: 'Cuenta la cantidad de páginas visitadas en tu sitio.' urls: title: 'Visitas por dirección' description: 'Cantidad de visitas o descargas por dirección.' - label: 'Direcciones web ("links", vínculos)' + label: 'Direcciones web (URL, "links", vínculos)' help: 'Copia y pega una dirección por línea.' - submit: 'Obtener estadísticas' + submit: 'Actualizar gráfico' resources: + title: 'Uso de recursos' + description: 'En esta sección podrás acceder a estadísticas del uso de recursos compartidos con otros sitios alojados en Sutty.' builds: title: 'Publicaciones del sitio' description: 'Cantidad de veces que publicaste tu sitio.' From ec775847b9dd8b446ee2947826452c6b5782d3d1 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 18:27:42 -0300 Subject: [PATCH 059/146] sugerir algunas URLs --- app/controllers/stats_controller.rb | 2 +- app/views/stats/index.haml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index a5ca04e1..3606f37e 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -102,7 +102,7 @@ class StatsController < ApplicationController next u unless u.end_with? '/' "#{u}index.html" - end&.uniq || [] + end&.uniq || [@site.url, @site.urls].flatten.uniq end def normalized_paths diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index e69c2546..fb5c0d52 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -18,15 +18,13 @@ = line_chart site_stats_host_path(@chart_params), **@chart_options .mb-5 - - original_urls = params[:urls]&.split("\n")&.map(&:strip) - - rows = original_urls.size.zero? ? 3 : original_urls.size %h2= t('.urls.title') %p.lead= t('.urls.description') %form %input{ type: 'hidden', name: 'interval', value: @interval } .form-group %label{ for: 'urls' }= t('.urls.label') - %textarea#urls.form-control{ name: 'urls', autocomplete: 'on', required: true, rows: rows, aria_describedby: 'help-urls' }= params[:urls] + %textarea#urls.form-control{ name: 'urls', autocomplete: 'on', required: true, rows: @normalized_urls.size, aria_describedby: 'help-urls' }= @normalized_urls.join("\n") %small#help-urls.feedback.form-text.text-muted= t('.urls.help') .form-group %button.btn{ type: 'submit' }= t('.urls.submit') From 356db8546522ac581254f11d2dcdd4419dfc6595 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 18:28:38 -0300 Subject: [PATCH 060/146] =?UTF-8?q?empezar=20a=20recolectar=20estad=C3=ADs?= =?UTF-8?q?ticas=20cuando=20se=20inicia=20el=20panel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/application.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/application.rb b/config/application.rb index 7326ae0f..4922b74f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -48,6 +48,11 @@ module Sutty EmailAddress::Config.error_messages translations.transform_keys(&:to_s), locale.to_s end + + # Empezar el recolector de datos en la próxima hora + now = Time.now + next_hour = now.at_beginning_of_hour + 1.hour + 1.minute + StatCollectionJob.perform_in(next_hour - now, once: false) end end end From aa86ead1124a6cfd865956d2a4d5bd8ace4f81de Mon Sep 17 00:00:00 2001 From: f Date: Sat, 9 Oct 2021 18:29:53 -0300 Subject: [PATCH 061/146] ruboyuta --- app/controllers/stats_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 3606f37e..3fe821ac 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -63,7 +63,7 @@ class StatsController < ApplicationController options = { host: hostnames, uri: normalized_paths } stats = Rollup.where_dimensions(**options).multi_series('host|uri', interval: interval).tap do |series| series.each do |serie| - serie[:name] = serie.dig(:dimensions).slice('host', 'uri').values.join.sub('/index.html', '/') + serie[:name] = serie[:dimensions].slice('host', 'uri').values.join.sub('/index.html', '/') serie[:data].transform_values! do |value| value * nodes end From d06edc2f62ce1e2e499684e3446d1a39c90d81f3 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 12:52:31 -0300 Subject: [PATCH 062/146] usar rollups desde git para poder hacer un rollup recursivo --- Gemfile | 2 +- Gemfile.lock | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index b5e8664b..a04353b2 100644 --- a/Gemfile +++ b/Gemfile @@ -59,7 +59,7 @@ gem 'rails-i18n' gem 'rails_warden' gem 'redis', require: %w[redis redis/connection/hiredis] gem 'redis-rails' -gem 'rollups' +gem 'rollups', git: 'https://github.com/ankane/rollup.git', branch: 'master' gem 'rubyzip' gem 'rugged' gem 'concurrent-ruby-ext' diff --git a/Gemfile.lock b/Gemfile.lock index 9d1f512b..c1f6925c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,6 +6,15 @@ GIT rails (>= 3.0) rake (>= 0.8.7) +GIT + remote: https://github.com/ankane/rollup.git + revision: 94ca777d54180c23e96ac4b4285cc9b405ccbd1a + branch: master + specs: + rollups (0.1.2) + activesupport (>= 5.1) + groupdate (>= 5.2) + GIT remote: https://github.com/fauno/email_address revision: 536b51f7071b68a55140c0c1726b4cd401d1c04d @@ -483,9 +492,6 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.5) - rollups (0.1.2) - activesupport (>= 5.1) - groupdate (>= 5.2) rouge (3.26.0) rubocop (1.18.3) parallel (~> 1.10) @@ -700,7 +706,7 @@ DEPENDENCIES recursero-jekyll-theme redis redis-rails - rollups + rollups! rubocop-rails rubyzip rugged From 245973b5196d478e64d7f3f14ae73fda72cd0e82 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 12:53:42 -0300 Subject: [PATCH 063/146] =?UTF-8?q?no=20fallar=20si=20todav=C3=ADa=20no=20?= =?UTF-8?q?hay=20stats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/stats/index.haml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml index fb5c0d52..bfcf33ef 100644 --- a/app/views/stats/index.haml +++ b/app/views/stats/index.haml @@ -2,11 +2,12 @@ .col %h1= t('.title') %p.lead= t('.help') - %p - %small - = t('.last_update') - %time{ datetime: @last_stat.created_at } - #{time_ago_in_words @last_stat.created_at}. + - if @last_stat + %p + %small + = t('.last_update') + %time{ datetime: @last_stat.created_at } + #{time_ago_in_words @last_stat.created_at}. .mb-5 - Stat::INTERVALS.each do |interval| From cc3535097e4924ed4d1ba87da04be769ba9b1b9e Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 12:57:11 -0300 Subject: [PATCH 064/146] =?UTF-8?q?todav=C3=ADa=20no=20empezar=20la=20reco?= =?UTF-8?q?lecci=C3=B3n=20autom=C3=A1tica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/application.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config/application.rb b/config/application.rb index 4922b74f..7326ae0f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -48,11 +48,6 @@ module Sutty EmailAddress::Config.error_messages translations.transform_keys(&:to_s), locale.to_s end - - # Empezar el recolector de datos en la próxima hora - now = Time.now - next_hour = now.at_beginning_of_hour + 1.hour + 1.minute - StatCollectionJob.perform_in(next_hour - now, once: false) end end end From 1497113f73a8f3cd5cb243b41236445f1667dfdc Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 12:58:19 -0300 Subject: [PATCH 065/146] usar menos intervalos las horas y semanas generan demasiados rollups --- app/models/stat.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/stat.rb b/app/models/stat.rb index 1e3af9e9..c986ba4b 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true class Stat < ApplicationRecord - INTERVALS = %i[hour day week month year].freeze + INTERVALS = %i[year month day].freeze RESOURCES = %i[builds space_used build_time].freeze end From 849ee4491c0579133f8134719510f079cff10b66 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 12:58:51 -0300 Subject: [PATCH 066/146] =?UTF-8?q?instalar=20las=20librer=C3=ADas=20en=20?= =?UTF-8?q?producci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 184f7ebb..d520c8f5 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "@rails/ujs": "^6.1.3-1", "@rails/webpacker": "5.2.1", "babel-loader": "^8.2.2", + "chart.js": "^3.5.1", + "chartkick": "^4.0.5", "circular-dependency-plugin": "^5.2.2", "commonmark": "^0.29.0", "fork-awesome": "^1.1.7", @@ -30,8 +32,6 @@ "zepto": "^1.2.0" }, "devDependencies": { - "@types/rails__activestorage": "^6.0.0", - "chart.js": "^3.5.1", - "chartkick": "^4.0.5" + "@types/rails__activestorage": "^6.0.0" } } From 9cf7c6286169ee4f5ee1cac1ea4f3f1ad8106a3d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 13:08:21 -0300 Subject: [PATCH 067/146] procesar uris a demanda --- app/jobs/uri_collection_job.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 app/jobs/uri_collection_job.rb diff --git a/app/jobs/uri_collection_job.rb b/app/jobs/uri_collection_job.rb new file mode 100644 index 00000000..79b83644 --- /dev/null +++ b/app/jobs/uri_collection_job.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Procesar una lista de URIs para una lista de dominios. Esto nos +# permite procesar estadísticas a demanada. +class UriCollectionJob < ApplicationJob + def perform(hostnames:, file:) + uris = File.read(file).split("\n") + + hostnames.each do |hostname| + uris.each do |uri| + break if File.exist? Rails.root.join('tmp', 'uri_collection_job_stop') + + AccessLog.where(host: hostname, uri: uri).completed_requests.non_robots.group(:host, :uri).rollup('host|uri', interval: 'day') + end + end + end +end From 8d38d0d2aedca550e5d8815f6d4b45c70138cfdc Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 13:14:19 -0300 Subject: [PATCH 068/146] =?UTF-8?q?recolecci=C3=B3n=20de=20estad=C3=ADstic?= =?UTF-8?q?as=20con=20mejor=20performance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/stat_collection_job.rb | 42 ++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb index 6f8470b8..a49a1635 100644 --- a/app/jobs/stat_collection_job.rb +++ b/app/jobs/stat_collection_job.rb @@ -21,14 +21,20 @@ class StatCollectionJob < ApplicationJob COLUMNS = %i[uri].freeze def perform(once: false) - Stat::INTERVALS.each do |interval| - options = { interval: interval } + Site.find_each do |site| + hostnames = [site.hostname, site.alternative_hostnames].flatten + + # Usamos el primero porque luego podemos hacer un rollup recursivo + options = { interval: Stat::INTERVALS.first } # Visitas por hostname - AccessLog.completed_requests.non_robots.pages.group(:host).rollup('host', **options) + hostnames.each do |hostname| + AccessLog.where(host: hostname).completed_requests.non_robots.pages.group(:host).rollup('host', **options) - combined_columns(**options) - stats_by_site(**options) + combined_columns(hostname, **options) + end + + stats_by_site(site, **options) end # Registrar que se hicieron todas las recolecciones @@ -40,9 +46,15 @@ class StatCollectionJob < ApplicationJob private # Combinación de columnas - def combined_columns(**options) + def combined_columns(hostname, **options) + where = { host: hostname } + COLUMNS.each do |column| - AccessLog.completed_requests.non_robots.group(:host, column).rollup("host|#{column}", **options) + AccessLog.where(host: hostname).pluck(Arel.sql("distinct #{column}")).each do |value| + where[column] = value + + AccessLog.where(**where).completed_requests.non_robots.group(:host, column).rollup("host|#{column}", **options) + end end end @@ -50,17 +62,15 @@ class StatCollectionJob < ApplicationJob # # XXX: En realidad se agrupan por el deploy_id, que siempre será el # del DeployLocal. - def stats_by_site(**options) - Site.find_each do |site| - site.build_stats.jekyll.group(:deploy_id).rollup('builds', **options) + def stats_by_site(site, **options) + site.build_stats.jekyll.group(:deploy_id).rollup('builds', **options) - site.build_stats.jekyll.group(:deploy_id).rollup('space_used', **options) do |rollup| - rollup.average(:bytes) - end + site.build_stats.jekyll.group(:deploy_id).rollup('space_used', **options) do |rollup| + rollup.average(:bytes) + end - site.build_stats.jekyll.group(:deploy_id).rollup('build_time', **options) do |rollup| - rollup.average(:seconds) - end + site.build_stats.jekyll.group(:deploy_id).rollup('build_time', **options) do |rollup| + rollup.average(:seconds) end end end From 7e1696204183e73afa307e27d77ecbfd87f7c5b8 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 20 Oct 2021 17:36:30 -0300 Subject: [PATCH 069/146] no fallar si no hay stat closes #3228 --- app/controllers/stats_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 3fe821ac..b9b93e9f 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -121,7 +121,7 @@ class StatsController < ApplicationController # toma de estadísticas y restando el tiempo que pasó desde ese # momento. def chart_options - time = last_stat.created_at + 1.try(interval) + time = (last_stat&.created_at || Time.now) + 1.try(interval) please_return_at = { please_return_at: distance_of_time_in_words(Time.now, time) } @chart_options ||= { From 090b6305251ecb068620eb0558659c4551d97d52 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 10:47:32 -0300 Subject: [PATCH 070/146] =?UTF-8?q?la=20l=C3=B3gica=20estaba=20invertida?= =?UTF-8?q?=20y=20los=20valores=20nunca=20llegaban=20al=20archivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_boolean.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_boolean.rb b/app/models/metadata_boolean.rb index 53a763fd..ed27ea92 100644 --- a/app/models/metadata_boolean.rb +++ b/app/models/metadata_boolean.rb @@ -33,7 +33,7 @@ class MetadataBoolean < MetadataTemplate # Siempre guardar el valor de este campo a menos que sea nulo def empty? - !value.nil? + value.nil? end private From d67d43ff1ea19f5acfb31d615cd4e0db97f98b5f Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 10:48:34 -0300 Subject: [PATCH 071/146] =?UTF-8?q?hacer=20m=C3=A1s=20claro=20el=20c=C3=B3?= =?UTF-8?q?digo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_boolean.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/metadata_boolean.rb b/app/models/metadata_boolean.rb index ed27ea92..90c002a7 100644 --- a/app/models/metadata_boolean.rb +++ b/app/models/metadata_boolean.rb @@ -25,10 +25,14 @@ class MetadataBoolean < MetadataTemplate # * false # * true def value - return document.data.fetch(name.to_s, default_value) if self[:value].nil? - return self[:value] unless self[:value].is_a? String - - self[:value] = true_values.include? self[:value] + case self[:value] + when NilClass + document.data.fetch(name.to_s, default_value) + when String + true_values.include? self[:value] + else + self[:value] + end end # Siempre guardar el valor de este campo a menos que sea nulo From 08e0a0ca9d7fe9ca76332e5ad895f155c7103803 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 10:49:02 -0300 Subject: [PATCH 072/146] traducir correctamente --- config/locales/en.yml | 4 ++-- config/locales/es.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 5f224ab6..43ab0d0a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -19,8 +19,8 @@ en: remember_me: 'Keeps session open for %{remember_for}' actions: sr-help: "After this form you'll find links to recover your account and other actions." - _true: Yes - _false: No + _true: 'Yes' + _false: 'No' svg: sutty: title: Sutty diff --git a/config/locales/es.yml b/config/locales/es.yml index ebf4da62..880b9e7c 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -19,8 +19,8 @@ es: remember_me: 'Mantiene la sesión abierta por %{remember_for}' actions: sr-help: 'Después del formulario encontrarás vínculos para recuperar tu cuenta, entre otras acciones.' - _true: Sí - _false: No + _true: 'Sí' + _false: 'No' svg: sutty: title: Sutty From 6349fd7b407a3f4c260ba061d8cbaf4bf63743cd Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 13:23:35 -0300 Subject: [PATCH 073/146] los url helpers necesitan hashes o params y params.to_h devuelve un hashwithindifferentaccess, lo que rompia las urls con locale --- app/controllers/posts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 05ae2736..6b69fd6a 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -154,7 +154,7 @@ class PostsController < ApplicationController # # @return [Hash] def filter_params - @filter_params ||= params.permit(:q, :category, :layout, :page).to_h.select { |_, v| v.present? } + @filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select { |_, v| v.present? } end def site From 3335d0d9eb3c75f20b48c427c2dd7a59b52c22dd Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 13:25:05 -0300 Subject: [PATCH 074/146] usar una guard como sugiere rubocop --- app/controllers/posts_controller.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 6b69fd6a..9d0ff8a8 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -22,21 +22,21 @@ class PostsController < ApplicationController # XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es # más simple saber si hubo cambios. - if stale?([current_usuarie, site, filter_params]) - # Todos los artículos de este sitio para el idioma actual - @posts = site.indexed_posts.where(locale: locale).page(filter_params.delete(:page)) - # De este tipo - @posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout] - # Que estén dentro de la categoría - @posts = @posts.in_category(filter_params[:category]) if filter_params[:category] - # Aplicar los parámetros de búsqueda - @posts = @posts.search(locale, filter_params[:q]) if filter_params[:q].present? - # A los que este usuarie tiene acceso - @posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve + return unless stale?([current_usuarie, site, filter_params]) - # Filtrar los posts que les invitades no pueden ver - @usuarie = site.usuarie? current_usuarie - end + # Todos los artículos de este sitio para el idioma actual + @posts = site.indexed_posts.where(locale: locale).page(filter_params.delete(:page)) + # De este tipo + @posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout] + # Que estén dentro de la categoría + @posts = @posts.in_category(filter_params[:category]) if filter_params[:category] + # Aplicar los parámetros de búsqueda + @posts = @posts.search(locale, filter_params[:q]) if filter_params[:q].present? + # A los que este usuarie tiene acceso + @posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve + + # Filtrar los posts que les invitades no pueden ver + @usuarie = site.usuarie? current_usuarie end def show From e3d2213afc0f97852df6ee40c42d70f47596f34f Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 13:44:34 -0300 Subject: [PATCH 075/146] especificar el idioma de un post nuevo --- app/controllers/posts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 9d0ff8a8..9820d71d 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -54,7 +54,7 @@ class PostsController < ApplicationController def new authorize Post - @post = site.posts.build(lang: locale, layout: params[:layout]) + @post = site.posts(lang: locale).build(layout: params[:layout]) breadcrumb I18n.t('loaf.breadcrumbs.posts.new', layout: @post.layout.humanized_name.downcase), '' end From 883182ffe2413b76c9f9756ddc8ad29cfca0c9ba Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 13:45:34 -0300 Subject: [PATCH 076/146] =?UTF-8?q?rutas=20m=C3=A1s=20espec=C3=ADficas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 15ee4150..5e172cda 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -57,7 +57,7 @@ Rails.application.routes.draw do # Gestionar artículos según idioma nested do - scope '(:locale)' do + scope '/(:locale)', constraint: /[a-z]{2}/ do post :'posts/reorder', to: 'posts#reorder' resources :posts do get 'p/:page', action: :index, on: :collection From 69ef571bdb4a4768c37865907fb07629fc017487 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 14:25:05 -0300 Subject: [PATCH 077/146] garantizar que sea una hash de simbolos --- app/controllers/posts_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 9820d71d..f3bc8aac 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -154,7 +154,9 @@ class PostsController < ApplicationController # # @return [Hash] def filter_params - @filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select { |_, v| v.present? } + @filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select do |_, v| + v.present? + end.transform_keys(&:to_sym) end def site From 9c4a0a86f3eeec8f578e3872096896a710e01632 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 14:40:55 -0300 Subject: [PATCH 078/146] deshabilitar el paginado temporalmente no permite mover posts entre paginas! --- app/controllers/posts_controller.rb | 4 ++-- app/views/posts/index.haml | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index f3bc8aac..dbdd4d0a 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -25,7 +25,7 @@ class PostsController < ApplicationController return unless stale?([current_usuarie, site, filter_params]) # Todos los artículos de este sitio para el idioma actual - @posts = site.indexed_posts.where(locale: locale).page(filter_params.delete(:page)) + @posts = site.indexed_posts.where(locale: locale) # De este tipo @posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout] # Que estén dentro de la categoría @@ -154,7 +154,7 @@ class PostsController < ApplicationController # # @return [Hash] def filter_params - @filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select do |_, v| + @filter_params ||= params.permit(:q, :category, :layout).to_hash.select do |_, v| v.present? end.transform_keys(&:to_sym) end diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 90e30966..5f613e3a 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -84,8 +84,6 @@ %button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom') %div - = link_to_prev_page @posts, t('posts.prev'), class: 'btn' - = link_to_next_page @posts, t('posts.next'), class: 'btn' %tbody - dir = t("locales.#{@locale}.dir") - size = @posts.size From 4456deff9c8eef185f370a57dac519ad0d8801b6 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 15:02:07 -0300 Subject: [PATCH 079/146] =?UTF-8?q?usar=20la=20traducci=C3=B3n=20del=20idi?= =?UTF-8?q?oma=20que=20viene=20del=20sitio?= 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 5f613e3a..ad07b9dc 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -51,7 +51,7 @@ - if @site.locales.size > 1 %nav#locales - @site.locales.each do |locale| - = link_to t("locales.#{locale}.name"), site_posts_path(@site, **@filter_params.merge(locale: locale)), + = link_to @site.data.dig(locale.to_s, 'locale') || locale, site_posts_path(@site, **@filter_params.merge(locale: locale)), class: "mr-2 mt-2 mb-2 #{locale == @locale ? 'active font-weight-bold' : ''}" .pl-2-plus - @filter_params.each do |param, value| From 7227ecfe2a1bfb99c19e5af8998b2253c323f348 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 20:53:25 -0300 Subject: [PATCH 080/146] solo instalar las gemas de assets en desarrollo --- .env.example | 1 + Gemfile | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index a62e2b0a..f79ff3a4 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ +RAILS_GROUPS=assets DELEGATE=athshe.sutty.nl HAINISH=../haini.sh/haini.sh DATABASE= diff --git a/Gemfile b/Gemfile index db06827d..01167fa1 100644 --- a/Gemfile +++ b/Gemfile @@ -11,13 +11,16 @@ gem 'dotenv-rails', require: 'dotenv/rails-now' gem 'rails', '~> 6' # Use Puma as the app server gem 'puma' -# See https://github.com/rails/execjs#readme for more supported runtimes -# gem 'therubyracer', platforms: :ruby -# Use SCSS for stylesheets -gem 'sassc-rails' -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' -gem 'bootstrap', '~> 4' + +# Solo incluir las gemas cuando estemos en desarrollo o compilando los +# assets. No es necesario instalarlas en producción. +# +# XXX: Supuestamente Rails ya soporta RAILS_GROUPS, pero Bundler no. +if ENV['RAILS_GROUPS']&.include? 'assets' + gem 'sassc-rails' + gem 'uglifier', '>= 1.3.0' + gem 'bootstrap', '~> 4' +end # Turbolinks makes navigating your web application faster. Read more: # https://github.com/turbolinks/turbolinks From fd784919df49d8703713b0f741521079de37fdc4 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 20:54:12 -0300 Subject: [PATCH 081/146] rails ya corre yarn antes de compilar --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 36139d7a..5aca94f8 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ help: always ## Ayuda @echo -e "\nArgumentos:\n" @grep -E "^[a-z\-]+ \?=.*##" Makefile | sed -re "s/(.*) \?=.*##(.*)/\1;\2/" | column -s ";" -t | sed -re "s/^([^ ]+) /\x1B[38;5;197m\1\x1B[0m/" -assets: node_modules public/packs/manifest.json.br ## Compilar los assets +assets: public/packs/manifest.json.br ## Compilar los assets test: always ## Ejecutar los tests $(MAKE) rake args="test RAILS_ENV=test $(args)" From 084bf8547f0202d5409d1c36a0cab71a40e7322f Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 20:54:50 -0300 Subject: [PATCH 082/146] ya no es necesario hacer limpieza en docker --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0b3253b4..07322903 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,10 +60,6 @@ RUN mv ../sutty/.bundle ./.bundle # Instalar secretos COPY --chown=app:root ./config/credentials.yml.enc ./config/ -# Eliminar la necesidad de un runtime JS en producción, porque los -# assets ya están pre-compilados. -RUN sed -re "/(sassc|uglifier|bootstrap|coffee-rails)/d" -i Gemfile -RUN bundle clean RUN rm -rf ./node_modules ./tmp/cache ./.git ./test ./doc # Eliminar archivos innecesarios USER root From 570761fab5efe47f0bbdf389550424c726dacc12 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 21 Oct 2021 20:55:40 -0300 Subject: [PATCH 083/146] =?UTF-8?q?actualizar=20contenedor=20con=20una=20v?= =?UTF-8?q?ersi=C3=B3n=20espec=C3=ADfica=20de=20bundler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 07322903..ee6ba871 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # el mismo repositorio de trabajo. Cuando tengamos CI/CD algunas cosas # como el tarball van a tener que cambiar porque ya vamos a haber hecho # un clone/pull limpio. -FROM alpine:3.13.5 AS build +FROM alpine:3.13.6 AS build MAINTAINER "f " ARG RAILS_MASTER_KEY @@ -14,10 +14,10 @@ ENV SECRET_KEY_BASE solo_es_necesaria_para_correr_rake ENV RAILS_ENV production ENV RAILS_MASTER_KEY=$RAILS_MASTER_KEY -RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake +RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-json ruby-bigdecimal ruby-rake RUN apk add --no-cache postgresql-libs git yarn brotli libssh2 python3 -RUN test "2.7.3" = `ruby -e 'puts RUBY_VERSION'` +RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` # https://github.com/rubygems/rubygems/issues/2918 # https://gitlab.alpinelinux.org/alpine/aports/issues/10808 @@ -29,7 +29,7 @@ RUN cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch RUN addgroup -g 82 -S www-data RUN adduser -s /bin/sh -G www-data -h /home/app -D app RUN install -dm750 -o app -g www-data /home/app/sutty -RUN gem install --no-document bundler +RUN gem install --no-document bundler:2.1.4 # Empezamos con la usuaria app USER app @@ -39,7 +39,8 @@ WORKDIR /home/app/sutty # Copiamos solo el Gemfile para poder instalar las gemas necesarias COPY --chown=app:www-data ./Gemfile . COPY --chown=app:www-data ./Gemfile.lock . -RUN bundle config set no-cache 'true' +RUN bundle config set no-cache true +RUN bundle config set specific_platform true RUN bundle install --path=./vendor --without='test development' # Vaciar la caché RUN rm vendor/ruby/2.7.0/cache/*.gem @@ -67,7 +68,7 @@ RUN apk add --no-cache findutils RUN find /home/app/checkout/vendor/ruby/2.7.0 -maxdepth 3 -type d -name test -o -name spec -o -name rubocop | xargs -r rm -rf # Contenedor final -FROM sutty/monit:latest +FROM registry.nulo.in/sutty/monit:3.13.6 ENV RAILS_ENV production # Pandoc @@ -75,13 +76,13 @@ RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/reposit # Instalar las dependencias, separamos la librería de base de datos para # poder reutilizar este primer paso desde otros contenedores -RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake ruby-irb +RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-json ruby-bigdecimal ruby-rake ruby-irb ruby-io-console ruby-etc RUN apk add --no-cache postgresql-libs libssh2 file rsync git jpegoptim vips RUN apk add --no-cache ffmpeg imagemagick pandoc tectonic oxipng jemalloc RUN apk add --no-cache git-lfs openssh-client patch # Chequear que la versión de ruby sea la correcta -RUN test "2.7.3" = `ruby -e 'puts RUBY_VERSION'` +RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` # https://github.com/rubygems/rubygems/issues/2918 # https://gitlab.alpinelinux.org/alpine/aports/issues/10808 @@ -93,7 +94,7 @@ RUN apk add --no-cache patch && cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/ru # principal RUN apk add --no-cache yarn # Instalar foreman para poder correr los servicios -RUN gem install --no-document --no-user-install bundler foreman +RUN gem install --no-document --no-user-install bundler:2.1.4 foreman # Agregar el grupo del servidor web y la usuaria RUN addgroup -g 82 -S www-data From 8bebe155f4bd355087fb6685b47f55709a2df48b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 22 Oct 2021 17:06:34 -0300 Subject: [PATCH 084/146] no hace falta subir los parches dos veces --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 36139d7a..592592bd 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,6 @@ ota-js: assets ## Actualizar Javascript en el nodo delegado ota: ## Actualizar Rails en el nodo delegado umask 022; git format-patch $(commit) - scp ./0*.patch $(delegate):/tmp/ ssh $(delegate) mkdir -p /tmp/patches-$(commit)/ scp ./0*.patch $(delegate):/tmp/patches-$(commit)/ scp ./ota.sh $(delegate):/tmp/ From 84e543ac078abfd77ecb8662a791ae67ba1eda01 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 22 Oct 2021 17:13:26 -0300 Subject: [PATCH 085/146] ignorar los cambios de licencia en idiomas no soportados --- 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 389549c3..5e2fc706 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -122,6 +122,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do # 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) From 21bf478af700b79806e133e7c698fd3ccbdf8c0e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 22 Oct 2021 17:36:00 -0300 Subject: [PATCH 086/146] actualizacion de cuidados --- Gemfile.lock | 65 ++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d8dd4fb4..67698998 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -93,9 +93,9 @@ GEM execjs (~> 2) bcrypt (3.1.16-x86_64-linux-musl) bcrypt_pbkdf (1.1.0-x86_64-linux-musl) - benchmark-ips (2.9.1) + benchmark-ips (2.9.2) bindex (0.8.1-x86_64-linux-musl) - blazer (2.4.3) + blazer (2.4.7) activerecord (>= 5) chartkick (>= 3.2) railties (>= 5) @@ -114,7 +114,7 @@ GEM rack-test (>= 0.5.4) xpath (>= 2.0, < 4.0) chartkick (4.0.5) - childprocess (3.0.0) + childprocess (4.1.0) coderay (1.1.3) colorator (1.1.0) commonmarker (0.21.2-x86_64-linux-musl) @@ -129,7 +129,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - dead_end (1.1.7) + dead_end (2.0.1) derailed_benchmarks (2.1.1) benchmark-ips (~> 2) dead_end @@ -157,7 +157,7 @@ GEM dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - down (5.2.3) + down (5.2.4) addressable (~> 2.8) ed25519 (1.2.4-x86_64-linux-musl) editorial-autogestiva-jekyll-theme (0.3.4) @@ -240,7 +240,7 @@ GEM concurrent-ruby (~> 1.0) icalendar (2.7.1) ice_cube (~> 0.16) - ice_cube (0.16.3) + ice_cube (0.16.4) image_processing (1.12.1) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) @@ -249,7 +249,7 @@ GEM nokogiri (>= 1.6) jbuilder (2.11.2) activesupport (>= 5.0.0) - jekyll (4.2.0) + jekyll (4.2.1) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) @@ -306,7 +306,7 @@ GEM jekyll (~> 4) jekyll-watch (2.2.1) listen (~> 3.0) - jekyll-write-and-commit-changes (0.2.0) + jekyll-write-and-commit-changes (0.2.1) jekyll (~> 4) rugged (~> 1) kaminari (1.2.1) @@ -336,7 +336,7 @@ GEM ruby_dep (~> 1.2) loaf (0.10.0) railties (>= 3.2) - lockbox (0.6.5) + lockbox (0.6.6) lograge (0.11.2) actionpack (>= 4) activesupport (>= 4) @@ -347,7 +347,7 @@ GEM nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) memory_profiler (1.0.0) mercenary (0.4.0) method_source (1.0.0) @@ -356,25 +356,25 @@ GEM mime-types-data (3.2021.0901) mini_histogram (0.3.1) mini_magick (4.11.0) - mini_mime (1.1.1) - mini_portile2 (2.5.3) + mini_mime (1.1.2) + mini_portile2 (2.6.1) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.4) - mobility (1.1.3) + mobility (1.2.2) i18n (>= 0.6.10, < 2) request_store (~> 1.0) multi_xml (0.6.0) net-ssh (6.1.0) - netaddr (2.0.4) + netaddr (2.0.5) nio4r (2.5.8-x86_64-linux-musl) - nokogiri (1.11.7-x86_64-linux-musl) - mini_portile2 (~> 2.5.0) + nokogiri (1.12.5-x86_64-linux-musl) + mini_portile2 (~> 2.6.1) racc (~> 1.4) orm_adapter (0.5.0) - parallel (1.20.1) + parallel (1.21.0) parser (3.0.2.0) ast (~> 2.4.1) pathutil (0.16.2) @@ -390,11 +390,11 @@ GEM coderay (~> 1.1) method_source (~> 1.0) public_suffix (4.0.6) - puma (5.4.0-x86_64-linux-musl) + puma (5.5.2-x86_64-linux-musl) nio4r (~> 2.0) pundit (2.1.1) activesupport (>= 3.0.0) - racc (1.5.2-x86_64-linux-musl) + racc (1.6.0-x86_64-linux-musl) rack (2.2.3) rack-cors (1.1.1) rack (>= 2.0.0) @@ -469,7 +469,7 @@ GEM jekyll-unique-urls (~> 0.1) sutty-archives (~> 2.2) sutty-liquid (~> 0) - redis (4.4.0) + redis (4.5.1) redis-actionpack (5.2.0) actionpack (>= 5, < 7) redis-rack (>= 2.1.0, < 3) @@ -493,19 +493,19 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.5) - rouge (3.26.0) - rubocop (1.20.0) + rouge (3.26.1) + rubocop (1.22.2) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 1.9.1, < 2.0) + rubocop-ast (>= 1.12.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.11.0) + rubocop-ast (1.12.0) parser (>= 3.0.1.1) - rubocop-rails (2.12.2) + rubocop-rails (2.12.4) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) @@ -513,7 +513,7 @@ GEM i18n ruby-filemagic (0.7.2-x86_64-linux-musl) ruby-progressbar (1.11.0) - ruby-statistics (2.1.3) + ruby-statistics (3.0.0) ruby-vips (2.1.3) ffi (~> 1.12) ruby2ruby (2.4.4) @@ -535,8 +535,9 @@ GEM sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + selenium-webdriver (4.0.3) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) semantic_range (3.0.0) sexp_processor (4.15.3) @@ -612,8 +613,8 @@ GEM execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext - unf_ext (0.0.7.7-x86_64-linux-musl) - unicode-display_width (1.7.0) + unf_ext (0.0.8-x86_64-linux-musl) + unicode-display_width (1.8.0) validates_hostname (1.0.11) activerecord (>= 3.0) activesupport (>= 3.0) @@ -624,7 +625,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webpacker (5.4.2) + webpacker (5.4.3) activesupport (>= 5.2) rack-proxy (>= 0.6.1) railties (>= 5.2) @@ -635,7 +636,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.2) + zeitwerk (2.5.1) PLATFORMS ruby From ab004fae700db1f3b72cd1a44ec403fdabb8c452 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 22 Oct 2021 18:21:47 -0300 Subject: [PATCH 087/146] decodificar las urls para poder buscarlas en el log --- app/controllers/stats_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index b9b93e9f..44073c1f 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -108,6 +108,8 @@ class StatsController < ApplicationController def normalized_paths @normalized_paths ||= normalized_urls.map do |u| "/#{u.split('/', 4).last}" + end.map do |u| + URI.decode_www_form_component u end end From c84462c4a8342ac9331718335c529d636ebb9298 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 26 Oct 2021 11:33:15 -0300 Subject: [PATCH 088/146] =?UTF-8?q?recolectar=20estad=C3=ADsticas=20usando?= =?UTF-8?q?=20menos=20recursos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/periodic_job.rb | 55 +++++++++++++++++ app/jobs/stat_collection_job.rb | 93 +++++++++++++---------------- app/jobs/uri_collection_job.rb | 101 ++++++++++++++++++++++++++++++-- app/models/site.rb | 1 + app/models/stat.rb | 6 +- 5 files changed, 198 insertions(+), 58 deletions(-) create mode 100644 app/jobs/periodic_job.rb diff --git a/app/jobs/periodic_job.rb b/app/jobs/periodic_job.rb new file mode 100644 index 00000000..8d9453a3 --- /dev/null +++ b/app/jobs/periodic_job.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# Una tarea que se corre periódicamente +class PeriodicJob < ApplicationJob + class RunAgainException < StandardError; end + + STARTING_INTERVAL = Stat::INTERVALS.first + + # Tener el sitio a mano + attr_reader :site + + # Descartar y notificar si pasó algo más. + # + # XXX: En realidad deberíamos seguir reintentando? + discard_on(StandardError) do |_, error| + ExceptionNotifier.notify_exception(error) + end + + # Correr indefinidamente una vez por hora. + # + # XXX: El orden importa, si el descarte viene después, nunca se va a + # reintentar. + retry_on(PeriodicJob::RunAgainException, wait: 1.try(STARTING_INTERVAL), attempts: Float::INFINITY, jitter: 0) + + private + + # Las clases que implementen esta tienen que usar este método al + # terminar. + def run_again! + raise PeriodicJob::RunAgainException, 'Reintentando' + end + + # El intervalo de inicio + # + # @return [Symbol] + def starting_interval + STARTING_INTERVAL + end + + # La última recolección de estadísticas o empezar desde el principio + # de los tiempos. + # + # @return [Stat] + def last_stat + @last_stat ||= site.stats.where(name: stat_name).last || + site.stats.build(created_at: Time.new(1970, 1, 1)) + end + + # Devuelve el comienzo del intervalo + # + # @return [Time] + def beginning_of_interval + @beginning_of_interval ||= last_stat.created_at.try(:"beginning_of_#{starting_interval}") + end +end diff --git a/app/jobs/stat_collection_job.rb b/app/jobs/stat_collection_job.rb index a49a1635..2aa8d702 100644 --- a/app/jobs/stat_collection_job.rb +++ b/app/jobs/stat_collection_job.rb @@ -3,74 +3,65 @@ # Genera resúmenes de información para poder mostrar estadísticas y se # corre regularmente a sí misma. class StatCollectionJob < ApplicationJob - class CrontabException < StandardError; end + STAT_NAME = 'stat_collection_job' - # Descartar y notificar si pasó algo más. - # - # XXX: En realidad deberíamos seguir reintentando? - discard_on(Exception) do |_, error| - ExceptionNotifier.notify_exception error - end + def perform(site_id:, once: true) + @site = Site.find site_id - # Correr indefinidamente una vez por hora. - # - # XXX: El orden importa, si el descarte viene después, nunca se va a - # reintentar. - retry_on(StatCollectionJob::CrontabException, wait: 1.hour, attempts: Float::INFINITY, jitter: 0) + scope.rollup('builds', **options) - COLUMNS = %i[uri].freeze + scope.rollup('space_used', **options) do |rollup| + rollup.average(:bytes) + end - def perform(once: false) - Site.find_each do |site| - hostnames = [site.hostname, site.alternative_hostnames].flatten + scope.rollup('build_time', **options) do |rollup| + rollup.average(:seconds) + end - # Usamos el primero porque luego podemos hacer un rollup recursivo - options = { interval: Stat::INTERVALS.first } + # XXX: Es correcto promediar promedios? + Stat::INTERVALS.reduce do |previous, current| + rollup(name: 'builds', interval_previous: previous, interval: current) + rollup(name: 'space_used', interval_previous: previous, interval: current, operation: :average) + rollup(name: 'build_time', interval_previous: previous, interval: current, operation: :average) - # Visitas por hostname - hostnames.each do |hostname| - AccessLog.where(host: hostname).completed_requests.non_robots.pages.group(:host).rollup('host', **options) - - combined_columns(hostname, **options) - end - - stats_by_site(site, **options) + current end # Registrar que se hicieron todas las recolecciones - Stat.create! + site.stats.create! name: STAT_NAME - raise CrontabException unless once + run_again! unless once end private - # Combinación de columnas - def combined_columns(hostname, **options) - where = { host: hostname } - - COLUMNS.each do |column| - AccessLog.where(host: hostname).pluck(Arel.sql("distinct #{column}")).each do |value| - where[column] = value - - AccessLog.where(**where).completed_requests.non_robots.group(:host, column).rollup("host|#{column}", **options) - end - end + # Genera un rollup recursivo en base al período anterior y aplica una + # operación. + # + # @return [NilClass] + def rollup(name:, interval_previous:, interval:, operation: :sum) + Rollup.where(name: name, interval: interval_previous) + .where_dimensions(site_id: site.id) + .group("dimensions->'site_id'") + .rollup(name, interval: interval, update: true) do |rollup| + rollup.try(:operation, :value) + end end - # Uso de recursos por cada sitio. + # Los registros a procesar # - # XXX: En realidad se agrupan por el deploy_id, que siempre será el - # del DeployLocal. - def stats_by_site(site, **options) - site.build_stats.jekyll.group(:deploy_id).rollup('builds', **options) + # @return [ActiveRecord::Relation] + def scope + @scope ||= site.build_stats + .jekyll + .where('created_at => ?', beginning_of_interval) + .group(:site_id) + end - site.build_stats.jekyll.group(:deploy_id).rollup('space_used', **options) do |rollup| - rollup.average(:bytes) - end - - site.build_stats.jekyll.group(:deploy_id).rollup('build_time', **options) do |rollup| - rollup.average(:seconds) - end + # Las opciones por defecto + # + # @return [Hash] + def options + @options ||= { interval: starting_interval, update: true } end end diff --git a/app/jobs/uri_collection_job.rb b/app/jobs/uri_collection_job.rb index 79b83644..9ec333cd 100644 --- a/app/jobs/uri_collection_job.rb +++ b/app/jobs/uri_collection_job.rb @@ -1,16 +1,105 @@ # frozen_string_literal: true # Procesar una lista de URIs para una lista de dominios. Esto nos -# permite procesar estadísticas a demanada. -class UriCollectionJob < ApplicationJob - def perform(hostnames:, file:) - uris = File.read(file).split("\n") +# permite procesar estadísticas a demanda. +# +# Hay varias cosas acá que van a convertirse en métodos propios, como la +# detección de URIs de un sitio (aunque la versión actual detecta todas +# las páginas y no solo las de posts como tenemos planeado, hay que +# resolver eso). +# +# Los hostnames de un sitio van a poder obtenerse a partir de +# Site#hostnames con la garantía de que son únicos. +class UriCollectionJob < PeriodicJob + # Ignoramos imágenes porque suelen ser demasiadas y no aportan a las + # estadísticas. + IMAGES = %w[.png .jpg .jpeg .gif .webp].freeze + STAT_NAME = 'uri_collection_job' + + def perform(site_id:, once: true) + @site = Site.find site_id hostnames.each do |hostname| uris.each do |uri| - break if File.exist? Rails.root.join('tmp', 'uri_collection_job_stop') + return if File.exist? Rails.root.join('tmp', 'uri_collection_job_stop') - AccessLog.where(host: hostname, uri: uri).completed_requests.non_robots.group(:host, :uri).rollup('host|uri', interval: 'day') + AccessLog.where(host: hostname, uri: uri) + .where('created_at >= ?', beginning_of_interval) + .completed_requests + .non_robots + .group(:host, :uri) + .rollup('host|uri', interval: starting_interval, update: true) + + # Reducir las estadísticas calculadas aplicando un rollup sobre el + # intervalo más amplio. + Stat::INTERVALS.reduce do |previous, current| + Rollup.where(name: 'host|uri', interval: previous) + .where_dimensions(host: hostname, uri: uri) + .group("dimensions->'host'", "dimensions->'uri'") + .rollup('host|uri', interval: current, update: true) do |rollup| + rollup.sum(:value) + end + + # Devolver el intervalo actual + current + end + end + end + + # Recordar la última vez que se corrió la tarea + site.stats.create! name: STAT_NAME + + run_again! unless once + end + + private + + def stat_name + STAT_NAME + end + + # @return [String] + # + # TODO: Cambiar al mergear origin-referer + def destination + @destination ||= site.deploys.find_by(type: 'DeployLocal').destination + end + + # TODO: Cambiar al mergear origin-referer + # + # @return [Array] + def hostnames + @hostnames ||= site.deploys.map do |deploy| + case deploy + when DeployLocal + site.hostname + when DeployWww + deploy.fqdn + when DeployAlternativeDomain + deploy.hostname.dup.tap do |h| + h.replace(h.end_with?('.') ? h[0..-2] : "#{h}.#{Site.domain}") + end + when DeployHiddenService + deploy.onion + end + end.compact + end + + # Recolecta todas las URIs menos imágenes + # + # @return [Array] + def uris + @uris ||= Dir.chdir destination do + (Dir.glob('**/*.html') + Dir.glob('public/**/*').reject do |p| + File.directory? p + end.reject do |p| + p = p.downcase + + IMAGES.any? do |i| + p.end_with? i + end + end).map do |uri| + "/#{uri}" end end end diff --git a/app/models/site.rb b/app/models/site.rb index ddfe2bc9..df92264a 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -37,6 +37,7 @@ class Site < ApplicationRecord belongs_to :design belongs_to :licencia + has_many :stats has_many :log_entries, dependent: :destroy has_many :deploys, dependent: :destroy has_many :build_stats, through: :deploys diff --git a/app/models/stat.rb b/app/models/stat.rb index c986ba4b..5f72ccd0 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true +# Registran cuándo fue la última recolección de datos. class Stat < ApplicationRecord - INTERVALS = %i[year month day].freeze + # XXX: Los intervalos van en orden de mayor especificidad a menor + INTERVALS = %i[day month year].freeze RESOURCES = %i[builds space_used build_time].freeze + + belongs_to :site end From 7a780188e4f85030d619014061e3ce09ef060b85 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 26 Oct 2021 16:19:42 -0300 Subject: [PATCH 089/146] asegurarse que siempre buscamos assets --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 01167fa1..981ce7fd 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,7 @@ gem 'puma' # assets. No es necesario instalarlas en producción. # # XXX: Supuestamente Rails ya soporta RAILS_GROUPS, pero Bundler no. -if ENV['RAILS_GROUPS']&.include? 'assets' +if ENV['RAILS_GROUPS']&.split(',')&.include? 'assets' gem 'sassc-rails' gem 'uglifier', '>= 1.3.0' gem 'bootstrap', '~> 4' From 25fe41bfa258d167c978152939bc65c9eb4c03b7 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 27 Oct 2021 10:12:28 -0300 Subject: [PATCH 090/146] enviar el idioma al reordenar! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit los tests envían el idioma pero no el panel --- app/views/posts/index.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index ad07b9dc..90d65670 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -67,6 +67,7 @@ %h2= t('posts.empty') - else = form_tag site_posts_reorder_path, method: :post do + %input{ type: 'hidden', name: 'post[lang]', value: @locale } %table.table{ data: { controller: 'reorder' } } %caption.sr-only= t('posts.caption') %thead From 09f5583d313801d42f5b930fd5eac28699302148 Mon Sep 17 00:00:00 2001 From: Nulo Date: Thu, 28 Oct 2021 15:32:13 -0300 Subject: [PATCH 091/146] Makefile: setear ENV_FILE en hain Requiere de https://0xacab.org/sutty/haini.sh/-/merge_requests/33. Pasa RAILS_GROUPS y otras variables. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 18914f43..1f0ca914 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ commit ?= origin/rails## Commit desde el que actualizar env ?= staging## Entorno del nodo delegado sutty ?= $(SUTTY)## Dirección local delegate ?= $(DELEGATE)## Cambia el nodo delegado -hain ?= $(HAINISH)## Ubicación de Hainish +hain ?= ENV_FILE=.env $(HAINISH)## Ubicación de Hainish # El nodo delegado tiene dos entornos, production y staging. # Dependiendo del entorno que elijamos, se van a generar los assets y el From 2844ca9f5f08c0d307734e5d52b2c7e63b989ec7 Mon Sep 17 00:00:00 2001 From: Nulo Date: Thu, 28 Oct 2021 16:06:31 -0300 Subject: [PATCH 092/146] .env.example: setear RAILS_ENV=development --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index f79ff3a4..fb086224 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ RAILS_GROUPS=assets DELEGATE=athshe.sutty.nl HAINISH=../haini.sh/haini.sh DATABASE= -RAILS_ENV= +RAILS_ENV=development IMAP_SERVER= DEFAULT_FROM= EXCEPTION_TO= From 21f650fc575656e174a22d36d3f89f6ea0e33f7f Mon Sep 17 00:00:00 2001 From: Nulo Date: Thu, 28 Oct 2021 16:13:39 -0300 Subject: [PATCH 093/146] Editor: forzar modo claro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Esto hace que sea legible y más usable cuando el modo oscuro está activado. https://0xacab.org/sutty/sutty/-/issues/2135 Idealmente, me gustaría tener modo oscuro real en el editor. --- app/assets/stylesheets/editor.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/assets/stylesheets/editor.scss b/app/assets/stylesheets/editor.scss index 5d218c7e..e0886533 100644 --- a/app/assets/stylesheets/editor.scss +++ b/app/assets/stylesheets/editor.scss @@ -2,6 +2,13 @@ box-sizing: border-box; *, *::before, *::after { box-sizing: inherit; } + // Arreglo temporal para que las cosas sean legibles en modo oscuro + --foreground: black; + --background: white; + --color: #f206f9; + background: var(--background); + color: var(--foreground); + h1, h2, h3, h4, h5, h6, p, li { min-height: 1.5rem; } From 66ec5269378c908f83975295d052fe07fd0a4203 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 4 Nov 2021 10:42:57 -0300 Subject: [PATCH 094/146] permitir descripciones mas cortas --- app/models/site.rb | 2 +- app/views/sites/_form.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index df92264a..5b78d625 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -26,7 +26,7 @@ class Site < ApplicationRecord validates :design_id, presence: true validates_inclusion_of :status, in: %w[waiting enqueued building] validates_presence_of :title - validates :description, length: { in: 50..160 } + validates :description, length: { in: 10..160 } validate :deploy_local_presence validate :compatible_layouts, on: :update diff --git a/app/views/sites/_form.haml b/app/views/sites/_form.haml index d26eeebf..6f15d570 100644 --- a/app/views/sites/_form.haml +++ b/app/views/sites/_form.haml @@ -39,7 +39,7 @@ %h2= f.label :description %p.lead= t('.help.description') = f.text_area :description, class: form_control(site, :description), - maxlength: 160, minlength: 50, required: true + maxlength: 160, minlength: 10, required: true - if invalid? site, :description .invalid-feedback= site.errors.messages[:description].join(', ') %hr/ From 6dcbe97ac6273fdf637f6143ecc1f88cb0255193 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 4 Nov 2021 10:58:49 -0300 Subject: [PATCH 095/146] permalinks relativos --- app/models/metadata_permalink.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_permalink.rb b/app/models/metadata_permalink.rb index dc65aa86..59b68461 100644 --- a/app/models/metadata_permalink.rb +++ b/app/models/metadata_permalink.rb @@ -5,7 +5,7 @@ class MetadataPermalink < MetadataString # El valor por defecto una vez creado es la URL que le asigne Jekyll, # de forma que nunca cambia aunque se cambie el título. def default_value - document.url unless post.new? + document.url.sub(%r{\A/}, '') unless post.new? end # Los permalinks nunca pueden ser privados From d85f21c3ca08161255c13ead2c756414b7122f50 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 25 Nov 2021 09:42:58 -0300 Subject: [PATCH 096/146] =?UTF-8?q?actualizaci=C3=B3n=20de=20cuidados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- Gemfile.lock | 68 ++++++++++++++++++++++++++-------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Gemfile b/Gemfile index 88dde566..2b304ee0 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,7 @@ if ENV['RAILS_GROUPS']&.split(',')&.include? 'assets' gem 'bootstrap', '~> 4' end -gem 'nokogiri', '~>1.11.0' +gem 'nokogiri' # Turbolinks makes navigating your web application faster. Read more: # https://github.com/turbolinks/turbolinks diff --git a/Gemfile.lock b/Gemfile.lock index 814175f0..9f0b56c5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,10 +8,10 @@ GIT GIT remote: https://github.com/ankane/rollup.git - revision: 94ca777d54180c23e96ac4b4285cc9b405ccbd1a + revision: 0ab6c603450175eb1004f7793e86486943cb9f72 branch: master specs: - rollups (0.1.2) + rollups (0.1.3) activesupport (>= 5.1) groupdate (>= 5.2) @@ -113,7 +113,7 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) - brakeman (5.1.1) + brakeman (5.1.2) builder (3.2.4) capybara (2.18.0) addressable @@ -122,7 +122,7 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (>= 2.0, < 4.0) - chartkick (4.0.5) + chartkick (4.1.2) childprocess (4.1.0) coderay (1.1.3) colorator (1.1.0) @@ -138,7 +138,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - dead_end (2.0.1) + dead_end (3.1.0) derailed_benchmarks (2.1.1) benchmark-ips (~> 2) dead_end @@ -157,7 +157,7 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-i18n (1.10.0) + devise-i18n (1.10.1) devise (>= 4.8.0) devise_invitable (2.0.5) actionmailer (>= 5.0) @@ -188,9 +188,9 @@ GEM jekyll-unique-urls (~> 0) jekyll-write-and-commit-changes (~> 0) sutty-liquid (~> 0) - em-websocket (0.5.2) + em-websocket (0.5.3) eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) + http_parser.rb (~> 0) errbase (0.2.1) erubi (1.10.0) eventmachine (1.2.7-x86_64-linux-musl) @@ -212,7 +212,7 @@ GEM activerecord (>= 4.0.0) get_process_mem (0.2.7) ffi (~> 1.0) - globalid (0.5.2) + globalid (0.6.0) activesupport (>= 5.0) groupdate (5.2.2) activesupport (>= 5) @@ -243,11 +243,11 @@ GEM heapy (0.2.0) thor hiredis (0.6.3-x86_64-linux-musl) - http_parser.rb (0.6.0-x86_64-linux-musl) + http_parser.rb (0.8.0-x86_64-linux-musl) httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.10) + i18n (1.8.11) concurrent-ruby (~> 1.0) icalendar (2.7.1) ice_cube (~> 0.16) @@ -258,7 +258,7 @@ GEM inline_svg (1.7.2) activesupport (>= 3.0) nokogiri (>= 1.6) - jbuilder (2.11.2) + jbuilder (2.11.3) activesupport (>= 5.0.0) jekyll (4.2.1) addressable (~> 2.4) @@ -289,7 +289,7 @@ GEM jekyll (~> 4) jekyll-ignore-layouts (0.1.2) jekyll (~> 4) - jekyll-images (0.2.7) + jekyll-images (0.3.0) jekyll (~> 4) ruby-filemagic (~> 0.7) ruby-vips (~> 2) @@ -297,7 +297,7 @@ GEM jekyll (>= 3.7, < 5.0) jekyll-linked-posts (0.4.2) jekyll (~> 4) - jekyll-locales (0.1.12) + jekyll-locales (0.1.13) jekyll-lunr (0.3.0) loofah (~> 2.4) jekyll-order (0.1.4) @@ -307,9 +307,9 @@ GEM sassc (> 2.0.1, < 3.0) jekyll-seo-tag (2.7.1) jekyll (>= 3.8, < 5.0) - jekyll-spree-client (0.1.18) + jekyll-spree-client (0.1.19) fast_blank (~> 1) - spree-api-client (>= 0.2.3) + spree-api-client (>= 0.2.4) jekyll-turbolinks (0.0.5) jekyll (~> 4) turbolinks-source (~> 5) @@ -362,9 +362,9 @@ GEM memory_profiler (1.0.0) mercenary (0.4.0) method_source (1.0.0) - mime-types (3.3.1) + mime-types (3.4.1) mime-types-data (~> 3.2015) - mime-types-data (3.2021.0901) + mime-types-data (3.2021.1115) mini_histogram (0.3.1) mini_magick (4.11.0) mini_mime (1.1.2) @@ -374,7 +374,7 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.4) - mobility (1.2.2) + mobility (1.2.3) i18n (>= 0.6.10, < 2) request_store (~> 1.0) multi_xml (0.6.0) @@ -395,7 +395,7 @@ GEM activerecord (>= 5.2) activesupport (>= 5.2) popper_js (1.16.0) - prometheus_exporter (0.8.1) + prometheus_exporter (1.0.0) webrick pry (0.14.1) coderay (~> 1.1) @@ -505,7 +505,7 @@ GEM railties (>= 5.0) rexml (3.2.5) rouge (3.26.1) - rubocop (1.22.2) + rubocop (1.23.0) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) @@ -514,7 +514,7 @@ GEM rubocop-ast (>= 1.12.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.12.0) + rubocop-ast (1.13.0) parser (>= 3.0.1.1) rubocop-rails (2.12.4) activesupport (>= 4.2.0) @@ -525,14 +525,14 @@ GEM ruby-filemagic (0.7.2-x86_64-linux-musl) ruby-progressbar (1.11.0) ruby-statistics (3.0.0) - ruby-vips (2.1.3) + ruby-vips (2.1.4) ffi (~> 1.12) ruby2ruby (2.4.4) ruby_parser (~> 3.1) sexp_processor (~> 4.6) ruby_dep (1.5.0) - ruby_parser (3.17.0) - sexp_processor (~> 4.15, >= 4.15.1) + ruby_parser (3.18.1) + sexp_processor (~> 4.16) rubyzip (2.3.2) rugged (1.2.0-x86_64-linux-musl) safe_yaml (1.0.6) @@ -546,12 +546,12 @@ GEM sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (4.0.3) + selenium-webdriver (4.1.0) childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) semantic_range (3.0.0) - sexp_processor (4.15.3) + sexp_processor (4.16.0) share-to-fediverse-jekyll-theme (0.1.4) jekyll (~> 4.0) jekyll-data (~> 1.1) @@ -563,7 +563,7 @@ GEM simpleidn (0.2.1) unf (~> 0.1.4) sourcemap (0.1.1) - spree-api-client (0.2.3) + spree-api-client (0.2.4) fast_blank (~> 1) httparty (~> 0.18.0) spring (2.1.1) @@ -573,9 +573,9 @@ GEM sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.1) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sqlite3 (1.4.2-x86_64-linux-musl) stackprof (0.2.17-x86_64-linux-musl) @@ -600,7 +600,7 @@ GEM jekyll-include-cache (~> 0) jekyll-relative-urls (~> 0.0) jekyll-seo-tag (~> 2.1) - sutty-liquid (0.7.3) + sutty-liquid (0.7.4) fast_blank (~> 1.0) jekyll (~> 4) sutty-minima (2.5.0) @@ -631,7 +631,7 @@ GEM activesupport (>= 3.0) warden (1.2.9) rack (>= 2.0.9) - web-console (4.1.0) + web-console (4.2.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) @@ -705,7 +705,7 @@ DEPENDENCIES minima mobility net-ssh - nokogiri (~> 1.11.0) + nokogiri pg pg_search prometheus_exporter From 1fa97854a6858cfe90491b3b69814a360a92b1ff Mon Sep 17 00:00:00 2001 From: f Date: Mon, 29 Nov 2021 11:30:55 -0300 Subject: [PATCH 097/146] actualizar mobility para recuperar performance --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9f0b56c5..8df2d77e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -374,7 +374,7 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.4) - mobility (1.2.3) + mobility (1.2.4) i18n (>= 0.6.10, < 2) request_store (~> 1.0) multi_xml (0.6.0) From f2a0654ebcb2fd63992a7c146d48b36f45d8a832 Mon Sep 17 00:00:00 2001 From: Nulo Date: Tue, 30 Nov 2021 16:45:19 +0000 Subject: [PATCH 098/146] =?UTF-8?q?Permitir=20clickear=20en=20el=20p=C3=A1?= =?UTF-8?q?rrafo=20de=20ejemplo=20para=20subir=20multimedia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/editor.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/editor.scss b/app/assets/stylesheets/editor.scss index e0886533..30fab60a 100644 --- a/app/assets/stylesheets/editor.scss +++ b/app/assets/stylesheets/editor.scss @@ -71,6 +71,10 @@ strong, em, del, u, sub, sup, small { background: #0002; } a { background: #13fefe50; } [data-editor-selected] { outline: #f206f9 solid thick; } + p[data-multimedia-inner] { + // Ignorar clicks en el párrafo placeholder + pointer-events: none; + } } *[data-editor-loading] { From 380d80ded4d3ffd4291d3d98d5f0d9ad0c6cef03 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 6 Dec 2021 14:55:46 -0300 Subject: [PATCH 099/146] =?UTF-8?q?solo=20instalar=20paquetes=20de=20produ?= =?UTF-8?q?cci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #3892 --- 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 c063b7bc..fb1142b2 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -82,7 +82,7 @@ class DeployLocal < Deploy def yarn return true unless yarn_lock? - run 'yarn' + run 'yarn install --production' end def bundle From 4e461e7af6f648fc4b5d91437160ec363e5cdc8b Mon Sep 17 00:00:00 2001 From: f Date: Thu, 9 Dec 2021 10:42:03 -0300 Subject: [PATCH 100/146] =?UTF-8?q?usar=20una=20cach=C3=A9=20com=C3=BAn=20?= =?UTF-8?q?para=20yarn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/deploy_local.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index fb1142b2..f9225f39 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -62,10 +62,15 @@ class DeployLocal < Deploy 'AIRBRAKE_PROJECT_ID' => site.id.to_s, 'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key, 'JEKYLL_ENV' => Rails.env, - 'LANG' => ENV['LANG'] + 'LANG' => ENV['LANG'], + 'YARN_CACHE_FOLDER' => yarn_cache_dir } end + def yarn_cache_dir + Rails.root.join('_yarn_cache') + end + def yarn_lock File.join(site.path, 'yarn.lock') end From 36cf199548805b498b810cb8789b84254c76443b Mon Sep 17 00:00:00 2001 From: f Date: Thu, 23 Dec 2021 22:47:15 -0300 Subject: [PATCH 101/146] devolver una string --- 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 f9225f39..4fa588f5 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -68,7 +68,7 @@ class DeployLocal < Deploy end def yarn_cache_dir - Rails.root.join('_yarn_cache') + Rails.root.join('_yarn_cache').to_s end def yarn_lock From 460635e940fca637bf41499cb8d4070beb9a3db7 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:03:02 -0300 Subject: [PATCH 102/146] ya no hace falta analizar archivos en primer plano --- config/initializers/analyze_job.rb | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 config/initializers/analyze_job.rb diff --git a/config/initializers/analyze_job.rb b/config/initializers/analyze_job.rb deleted file mode 100644 index f268e0dd..00000000 --- a/config/initializers/analyze_job.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -# TODO: Estamos procesando el análisis de los archivos en el momento -# porque queremos obtener la ruta del archivo en el momento y no -# después. Necesitaríamos poder generar el vínculo en el -# repositorio a destiempo, modificando el Job de ActiveStorage -ActiveStorage::AnalyzeJob.queue_adapter = :inline From 29950e4380b4c6d5122a0bfd3f8024178b44a40d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:05:11 -0300 Subject: [PATCH 103/146] cargar decorators --- config/application.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/application.rb b/config/application.rb index 7326ae0f..0e6e7f44 100644 --- a/config/application.rb +++ b/config/application.rb @@ -38,6 +38,12 @@ module Sutty config.active_storage.variant_processor = :vips + config.to_prepare do + Dir.glob(File.join(File.dirname(__FILE__), '..', 'app', '**', '*_decorator.rb')) do |c| + Rails.configuration.cache_classes ? require(c) : load(c) + end + end + config.after_initialize do ActiveStorage::DirectUploadsController.include ActiveStorage::AuthenticatedDirectUploadsController From 3de1228c26541185a62fa7a528dfc170308018bf Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:08:09 -0300 Subject: [PATCH 104/146] implementa un servicio de carga de archivos en jekyll --- .../active_storage/service/jekyll_service.rb | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 app/lib/active_storage/service/jekyll_service.rb diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb new file mode 100644 index 00000000..686c3979 --- /dev/null +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module ActiveStorage + module 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 + BLOB_NAME = 'blob' + + # Para poder guardar el archivo con el nombre original pero poder + # recuperarlo durante el download, luego de subirlo le cambiamos el + # nombre y creamos un link simbólico a un nombre conocido. + def upload(key, io, checksum: nil, **options) + super.tap do + path = path_for(key) + filename = options[:filename].to_s + + FileUtils.mv path, path.sub(/#{BLOB_NAME}\z/, filename) + FileUtils.ln_s filename, path + end + end + + # Mantener retrocompatibilidad con cómo gestionamos los archivos + # subidos hasta ahora. + # + # @param :key [String] + # @return [String] + def folder_for(key) + key + end + + # Crea una ruta para la llave con un nombre conocido. + def path_for(key) + File.join root, folder_for(key), BLOB_NAME + end + end + end +end From 873f2c7bcb8db83a1bdc46580158ff28ce3e67e9 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:09:06 -0300 Subject: [PATCH 105/146] informar cuando no se pudo cargar el archivo --- app/models/metadata_file.rb | 1 + config/locales/en.yml | 2 ++ config/locales/es.yml | 2 ++ 3 files changed, 5 insertions(+) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 80cefa27..b020d078 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -19,6 +19,7 @@ class MetadataFile < MetadataTemplate errors << I18n.t("metadata.#{type}.site_invalid") if site.invalid? errors << I18n.t("metadata.#{type}.path_required") if path_missing? errors << I18n.t("metadata.#{type}.no_file_for_description") if no_file_for_description? + errors << I18n.t("metadata.#{type}.attachment_missing") unless static_file errors.compact! errors.empty? diff --git a/config/locales/en.yml b/config/locales/en.yml index b814796d..8bbe3621 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -41,10 +41,12 @@ en: not_an_image: 'Not an image' path_required: 'Missing image for upload' no_file_for_description: "Description with no associated image" + attachment_missing: "I couldn't save the image :(" file: site_invalid: 'The file cannot be stored if the site configuration is not valid' path_required: "Missing file for upload" no_file_for_description: "Description with no associated file" + attachment_missing: "I couldn't save the file :(" event: zone_missing: 'Inexistent timezone' date_missing: 'Event date is required' diff --git a/config/locales/es.yml b/config/locales/es.yml index a6fbd407..93dd162e 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -41,10 +41,12 @@ es: not_an_image: 'No es una imagen' path_required: 'Se necesita una imagen' no_file_for_description: 'Se envió una descripción sin imagen asociada' + attachment_missing: 'no pude guardar el archivo :(' file: site_invalid: 'El archivo no se puede almacenar si la configuración del sitio no es válida' path_required: 'Se necesita un archivo' no_file_for_description: 'se envió una descripción sin archivo asociado' + attachment_missing: 'no pude guardar el archivo :(' event: zone_missing: 'El huso horario no es correcto' date_missing: 'La fecha es obligatoria' From c4139c4b92746c84cdbdaaffe1fea31a69afc9a8 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:12:06 -0300 Subject: [PATCH 106/146] =?UTF-8?q?eliminar=20c=C3=B3digo=20que=20no=20se?= =?UTF-8?q?=20usa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_file.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index b020d078..58adc857 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -35,12 +35,6 @@ class MetadataFile < MetadataTemplate value['path'].is_a?(String) end - # Determina si la ruta es opcional pero deja pasar si la ruta se - # especifica - def path_optional? - !required && !path? - end - # Asociar la imagen subida al sitio y obtener la ruta # # XXX: Si evitamos guardar cambios con changed? no tenemos forma de From 3d5267451eec0e879fad28ef4086cd240884d683 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:15:38 -0300 Subject: [PATCH 107/146] =?UTF-8?q?eliminar=20c=C3=B3digo=20que=20ya=20no?= =?UTF-8?q?=20se=20usa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_file.rb | 65 ------------------------------------- 1 file changed, 65 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 58adc857..86644fcc 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -93,71 +93,6 @@ class MetadataFile < MetadataTemplate private - def filemagic - @filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME) - end - - # @return [Pathname] - def path - @path ||= Pathname.new(File.join(site.path, value['path'])) - end - - def file - return unless path? - - @file ||= - case value['path'] - when ActionDispatch::Http::UploadedFile then value['path'].tempfile.path - when String then File.join(site.path, value['path']) - end - end - - # Hacemos un link duro para colocar el archivo dentro del repositorio - # y no duplicar el espacio que ocupan. Esto requiere que ambos - # directorios estén dentro del mismo punto de montaje. - # - # XXX: Asumimos que el archivo destino no existe porque siempre - # contiene una key única. - # - # @return [Boolean] - def hardlink - return if hardlink? - return if File.exist? destination_path - - FileUtils.mkdir_p(File.dirname(destination_path)) - FileUtils.ln(uploaded_path, destination_path).zero? - end - - def hardlink? - File.stat(uploaded_path).ino == File.stat(destination_path).ino - rescue Errno::ENOENT - false - end - - # Obtener la ruta al archivo - # https://stackoverflow.com/a/53908358 - def uploaded_relative_path - ActiveStorage::Blob.service.path_for(static_file.key) - end - - # @return [String] - def uploaded_path - Rails.root.join uploaded_relative_path - end - - # La ruta del archivo mantiene el nombre original pero contiene el - # nombre interno y único del archivo para poder relacionarlo con el - # archivo subido en Sutty. - # - # @return [String] - def relative_destination_path - @relative_destination_path ||= File.join('public', static_file.key, static_file.filename.to_s) - end - - # @return [String] - def destination_path - @destination_path ||= File.join(site.path, relative_destination_path) - end # No hay archivo pero se lo describió def no_file_for_description? From d8fd25a7cb32ab6cdec028f4d054cf398df4b97c Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:16:36 -0300 Subject: [PATCH 108/146] =?UTF-8?q?chequear=20la=20descripci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_file.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 86644fcc..20d093b2 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -91,11 +91,14 @@ class MetadataFile < MetadataTemplate value['path'].present? end - private + def description? + value['description'].present? + end + private # No hay archivo pero se lo describió def no_file_for_description? - value['description'].present? && value['path'].blank? + !path? && description? end end From 63f8b869eb185dd9c607ed4b684baf9ab478a08d Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:17:03 -0300 Subject: [PATCH 109/146] fixup! cargar decorators --- config/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/application.rb b/config/application.rb index 0e6e7f44..031c1909 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,7 +39,7 @@ module Sutty config.active_storage.variant_processor = :vips config.to_prepare do - Dir.glob(File.join(File.dirname(__FILE__), '..', 'app', '**', '*_decorator.rb')) do |c| + Dir.glob(File.join(File.dirname(__FILE__), '..', 'app', '**', '*_decorator.rb')).sort.each do |c| Rails.configuration.cache_classes ? require(c) : load(c) end end From 37deb361785d9f79c2d721898c3545a5c7323985 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:19:40 -0300 Subject: [PATCH 110/146] conseguir la ruta al archivo --- app/models/metadata_file.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 20d093b2..89e6d461 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -83,6 +83,15 @@ class MetadataFile < MetadataTemplate end end + # Obtiene la ruta absoluta al archivo + # + # @return [Pathname] + def pathname + raise NoMethodError unless uploaded? + + @pathname ||= Pathname.new(File.join(site.path, value['path'])) + end + def key_from_path path.dirname.basename.to_s end From 03d9913f58f4be0bd0e2c3417577bab6f8a67c4a Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:21:03 -0300 Subject: [PATCH 111/146] obtener el archivo subido --- app/models/metadata_file.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 89e6d461..e4c0d037 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -66,18 +66,19 @@ class MetadataFile < MetadataTemplate # XXX: La última opción provoca archivos duplicados, pero es lo mejor # que tenemos hasta que resolvamos https://0xacab.org/sutty/sutty/-/issues/213 # - # @return [ActiveStorage::Attachment] + # @todo encontrar una forma de obtener el attachment sin tener que + # recurrir al último subido. + # + # @return [ActiveStorage::Attachment,nil] def static_file - return unless path? - @static_file ||= case value['path'] when ActionDispatch::Http::UploadedFile site.static_files.last if site.static_files.attach(value['path']) when String - if (blob = ActiveStorage::Blob.where(key: key_from_path).pluck(:id).first) - site.static_files.find_by(blob_id: blob) - elsif site.static_files.attach(io: path.open, filename: path.basename) + if (blob_id = ActiveStorage::Blob.where(key: key_from_path).pluck(:id).first) + site.static_files.find_by(blob_id: blob_id) + elsif path? && pathname.exist? && site.static_files.attach(io: pathname.open, filename: pathname.basename) site.static_files.last end end @@ -92,8 +93,11 @@ class MetadataFile < MetadataTemplate @pathname ||= Pathname.new(File.join(site.path, value['path'])) end + # Obtiene la key del attachment a partir de la ruta + # + # @return [String] def key_from_path - path.dirname.basename.to_s + pathname.dirname.basename.to_s end def path? From fdbe724f7c92953e9ba2cfa74f8470a6fa617c2e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:21:26 -0300 Subject: [PATCH 112/146] asociar el archivo subido al post --- app/models/metadata_file.rb | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index e4c0d037..1c859481 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -43,13 +43,7 @@ class MetadataFile < MetadataTemplate # repetida. def save value['description'] = sanitize value['description'] - - if path? - hardlink - value['path'] = relative_destination_path - else - value['path'] = nil - end + value['path'] = static_file ? relative_destination_path_with_filename.to_s : nil true end @@ -110,6 +104,28 @@ class MetadataFile < MetadataTemplate private + # Obtener la ruta al archivo relativa al sitio + # + # @return [Pathname] + def destination_path + Pathname.new(static_file_path) + end + + # Agrega el nombre de archivo a la ruta para tener retrocompatibilidad + # + # @return [Pathname] + def destination_path_with_filename + destination_path.realpath + end + + def relative_destination_path_with_filename + destination_path_with_filename.relative_path_from(site.path) + end + + def static_file_path + static_file.blob.service.path_for(static_file.key) + end + # No hay archivo pero se lo describió def no_file_for_description? !path? && description? From f3df5504944cbdbf2f07aa0cd33f8fd8cd7f55a0 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:21:48 -0300 Subject: [PATCH 113/146] =?UTF-8?q?no=20permitir=20subir=20im=C3=A1genes?= =?UTF-8?q?=20que=20no=20son=20para=20web?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_image.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/metadata_image.rb b/app/models/metadata_image.rb index f91a6273..f86c5c26 100644 --- a/app/models/metadata_image.rb +++ b/app/models/metadata_image.rb @@ -13,8 +13,6 @@ class MetadataImage < MetadataFile # Determina si es una imagen def image? - return true unless file - - filemagic.file(file).starts_with? 'image/' + static_file&.blob&.send(:web_image?) end end From 02b52b23b91b0c88a9c48b01604eb9ee22692d9f Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:24:04 -0300 Subject: [PATCH 114/146] compartir el nombre de archivo con JekyllService --- app/models/active_storage/blob_decorator.rb | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 app/models/active_storage/blob_decorator.rb diff --git a/app/models/active_storage/blob_decorator.rb b/app/models/active_storage/blob_decorator.rb new file mode 100644 index 00000000..9c01251a --- /dev/null +++ b/app/models/active_storage/blob_decorator.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module ActiveStorage + # Modificaciones a ActiveStorage::Blob + module BlobDecorator + extend ActiveSupport::Concern + + included do + # Permitir que llegue el nombre de archivo al servicio de subida de + # archivos. + # + # @return [Hash] + def service_metadata + if forcibly_serve_as_binary? + { content_type: ActiveStorage.binary_content_type, disposition: :attachment, filename: filename } + elsif !allowed_inline? + { content_type: content_type, disposition: :attachment, filename: filename } + else + { content_type: content_type, filename: filename } + end + end + end + end +end + +ActiveStorage::Blob.include ActiveStorage::BlobDecorator From 69e7df4c31b8f3b72d9e2cde2b7430bb3cef4f66 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 4 Mar 2022 19:26:56 -0300 Subject: [PATCH 115/146] instanciar JekyllService para cada sitio --- .../service/registry_decorator.rb | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/lib/active_storage/service/registry_decorator.rb diff --git a/app/lib/active_storage/service/registry_decorator.rb b/app/lib/active_storage/service/registry_decorator.rb new file mode 100644 index 00000000..f7f20784 --- /dev/null +++ b/app/lib/active_storage/service/registry_decorator.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module ActiveStorage + module Service + # Modificaciones a ActiveStorage::Service::Registry + module RegistryDecorator + extend ActiveSupport::Concern + + included do + # El mismo comportamiento que #fetch con el agregado de generar + # un {JekyllService} para cada sitio. + def fetch(name) + services.fetch(name.to_sym) do |key| + if configurations.include?(key) + services[key] = configurator.build(key) + elsif (site = Site.find_by_name(key)) + root = File.join(site.path, 'public') + services[key] = ActiveStorage::Service::JekyllService.new(root: root, public: true).tap do |s| + s.name = key.to_sym + end + elsif block_given? + yield key + else + raise KeyError, "Missing configuration for the #{key} Active Storage service. " \ + "Configurations available for the #{configurations.keys.to_sentence} services." + end + end + end + end + end + end +end + +ActiveStorage::Service::Registry.include ActiveStorage::Service::RegistryDecorator From 15e978c877cacc8b5eb3a6c79c5e0e9cc3349eda Mon Sep 17 00:00:00 2001 From: f Date: Sat, 5 Mar 2022 20:08:55 -0300 Subject: [PATCH 116/146] eran clases --- app/lib/active_storage/service/jekyll_service.rb | 2 +- app/lib/active_storage/service/registry_decorator.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 686c3979..173f6898 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module ActiveStorage - module Service + class Service # Sube los archivos a cada repositorio y los agrega al LFS de su # repositorio git. # diff --git a/app/lib/active_storage/service/registry_decorator.rb b/app/lib/active_storage/service/registry_decorator.rb index f7f20784..f6794607 100644 --- a/app/lib/active_storage/service/registry_decorator.rb +++ b/app/lib/active_storage/service/registry_decorator.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module ActiveStorage - module Service + class Service # Modificaciones a ActiveStorage::Service::Registry module RegistryDecorator extend ActiveSupport::Concern From 7f6063475bb63eed2cab8523d5f15d1ef71b15ea Mon Sep 17 00:00:00 2001 From: f Date: Sat, 5 Mar 2022 20:09:09 -0300 Subject: [PATCH 117/146] =?UTF-8?q?m=C3=A9todo=20gen=C3=A9rico=20para=20in?= =?UTF-8?q?stanciar=20el=20servicio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/active_storage/service/jekyll_service.rb | 7 +++++++ app/lib/active_storage/service/registry_decorator.rb | 5 +---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 173f6898..20dda523 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -12,6 +12,13 @@ module ActiveStorage class JekyllService < Service::DiskService BLOB_NAME = 'blob' + # Genera un servicio para un sitio determinado + def self.build_for_site(site:) + new(root: File.join(site.path, 'public'), public: true).tap do |js| + js.name = site.name.to_sym + end + end + # Para poder guardar el archivo con el nombre original pero poder # recuperarlo durante el download, luego de subirlo le cambiamos el # nombre y creamos un link simbólico a un nombre conocido. diff --git a/app/lib/active_storage/service/registry_decorator.rb b/app/lib/active_storage/service/registry_decorator.rb index f6794607..c7096356 100644 --- a/app/lib/active_storage/service/registry_decorator.rb +++ b/app/lib/active_storage/service/registry_decorator.rb @@ -14,10 +14,7 @@ module ActiveStorage if configurations.include?(key) services[key] = configurator.build(key) elsif (site = Site.find_by_name(key)) - root = File.join(site.path, 'public') - services[key] = ActiveStorage::Service::JekyllService.new(root: root, public: true).tap do |s| - s.name = key.to_sym - end + services[key] = ActiveStorage::Service::JekyllService.build_for_site(site: site) elsif block_given? yield key else From 10eef47ce8bfb0f233083e070207f7d1c8bbf578 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 5 Mar 2022 20:09:37 -0300 Subject: [PATCH 118/146] todos los archivos subidos se asocian al sitio --- .../attached/changes/create_one_decorator.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 app/lib/active_storage/attached/changes/create_one_decorator.rb diff --git a/app/lib/active_storage/attached/changes/create_one_decorator.rb b/app/lib/active_storage/attached/changes/create_one_decorator.rb new file mode 100644 index 00000000..bfb92478 --- /dev/null +++ b/app/lib/active_storage/attached/changes/create_one_decorator.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module ActiveStorage + module Attached::Changes::CreateOneDecorator + extend ActiveSupport::Concern + + included do + private + + # A partir de ahora todos los archivos se suben al servicio de + # cada sitio. + def attachment_service_name + record.name.to_sym + end + end + end +end + +ActiveStorage::Attached::Changes::CreateOne.include ActiveStorage::Attached::Changes::CreateOneDecorator From bfb8e95599762f73cc5c8b093932d1750b55c5ea Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 12:51:06 -0300 Subject: [PATCH 119/146] obtener el nombre de archivo desde la key esto agrega una query pero permite no tener que agregar una ruta falsa --- .../active_storage/service/jekyll_service.rb | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 20dda523..02316e65 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -10,8 +10,6 @@ module ActiveStorage # implementemos IPFS) para poder transferir los archivos junto con el # sitio. class JekyllService < Service::DiskService - BLOB_NAME = 'blob' - # Genera un servicio para un sitio determinado def self.build_for_site(site:) new(root: File.join(site.path, 'public'), public: true).tap do |js| @@ -19,16 +17,7 @@ module ActiveStorage end end - # Para poder guardar el archivo con el nombre original pero poder - # recuperarlo durante el download, luego de subirlo le cambiamos el - # nombre y creamos un link simbólico a un nombre conocido. - def upload(key, io, checksum: nil, **options) - super.tap do - path = path_for(key) - filename = options[:filename].to_s - FileUtils.mv path, path.sub(/#{BLOB_NAME}\z/, filename) - FileUtils.ln_s filename, path end end @@ -41,9 +30,17 @@ module ActiveStorage key end + # Obtiene el nombre de archivo para esta key + # + # @param :key [String] + # @return [String] + def filename_for(key) + @filename_for ||= ActiveStorage::Blob.where(key: key).limit(1).pluck(:filename).first + end + # Crea una ruta para la llave con un nombre conocido. def path_for(key) - File.join root, folder_for(key), BLOB_NAME + File.join root, folder_for(key), filename_for(key) end end end From 85cab49208cbfae13b1876ab5a57495544b4220c Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 15:25:15 -0300 Subject: [PATCH 120/146] subir los archivos desde el editor al sitio --- .../direct_uploads_controller_decorator.rb | 18 ++++++++++++++++++ app/controllers/posts_controller.rb | 6 ++++++ .../active_storage/service/jekyll_service.rb | 4 ---- 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 app/controllers/active_storage/direct_uploads_controller_decorator.rb diff --git a/app/controllers/active_storage/direct_uploads_controller_decorator.rb b/app/controllers/active_storage/direct_uploads_controller_decorator.rb new file mode 100644 index 00000000..f27c4cfb --- /dev/null +++ b/app/controllers/active_storage/direct_uploads_controller_decorator.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module ActiveStorage + # Modifica la creación de un blob antes de subir el archivo para que + # incluya el JekyllService adecuado. + module DirectUploadsControllerDecorator + extend ActiveSupport::Concern + + included do + def create + blob = ActiveStorage::Blob.create_before_direct_upload!(service_name: session[:service_name], **blob_args) + render json: direct_upload_json(blob) + end + end + end +end + +ActiveStorage::DirectUploadsController.include ActiveStorage::DirectUploadsControllerDecorator diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index dbdd4d0a..2aff9ac9 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -6,6 +6,7 @@ class PostsController < ApplicationController rescue_from Pundit::NilPolicyError, with: :page_not_found before_action :authenticate_usuarie! + before_action :service_for_direct_upload, only: %i[new edit] # TODO: Traer los comunes desde ApplicationController breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path @@ -166,4 +167,9 @@ class PostsController < ApplicationController def post @post ||= site.posts(lang: locale).find(params[:post_id] || params[:id]) end + + # Recuerda el nombre del servicio de subida de archivos + def service_for_direct_upload + session[:service_name] = site.name.to_sym + end end diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 02316e65..601b6f2f 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -17,10 +17,6 @@ module ActiveStorage end end - - end - end - # Mantener retrocompatibilidad con cómo gestionamos los archivos # subidos hasta ahora. # From c13c021fe92d749cf4a98673bc3cc504c6e90d78 Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 15:28:25 -0300 Subject: [PATCH 121/146] asignar el nombre de archivo en la subida directa --- .../active_storage/service/jekyll_service.rb | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 601b6f2f..a2e04336 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -17,6 +17,32 @@ module ActiveStorage end end + # Lo mismo que en DiskService agregando el nombre de archivo en la + # firma. Esto permite que luego podamos guardar el archivo donde + # corresponde. + def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) + instrument :url, key: key do |payload| + verified_token_with_expiration = ActiveStorage.verifier.generate( + { + key: key, + content_type: content_type, + content_length: content_length, + checksum: checksum, + service_name: name, + filename: filename_for(key) + }, + expires_in: expires_in, + purpose: :blob_token + ) + + generated_url = url_helpers.update_rails_disk_service_url(verified_token_with_expiration, host: current_host) + + payload[:url] = generated_url + + generated_url + end + end + # Mantener retrocompatibilidad con cómo gestionamos los archivos # subidos hasta ahora. # From 211fb308e39ddd1a380b711e98d240c59e9576d6 Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 15:59:57 -0300 Subject: [PATCH 122/146] asignar archivos subidos desde el editor al sitio --- .../disk_controller_decorator.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 app/controllers/active_storage/disk_controller_decorator.rb diff --git a/app/controllers/active_storage/disk_controller_decorator.rb b/app/controllers/active_storage/disk_controller_decorator.rb new file mode 100644 index 00000000..14366a15 --- /dev/null +++ b/app/controllers/active_storage/disk_controller_decorator.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module ActiveStorage + # Modificar {DiskController} para poder asociar el blob a un sitio + module DiskControllerDecorator + extend ActiveSupport::Concern + + included do + # Asociar el archivo subido al sitio correspondiente. Cada sitio + # tiene su propio servicio de subida de archivos. + def update + if (token = decode_verified_token) + if acceptable_content?(token) + named_disk_service(token[:service_name]).upload token[:key], request.body, checksum: token[:checksum] + + blob = ActiveStorage::Blob.find_by_key token[:key] + site = Site.find_by_name token[:service_name] + + site.static_files.attach(blob) + else + head :unprocessable_entity + end + else + head :not_found + end + rescue ActiveStorage::IntegrityError + head :unprocessable_entity + end + end + end +end + +ActiveStorage::DiskController.include ActiveStorage::DiskControllerDecorator From 61622a4c416b73288cc897b89b8721fe3bb700c9 Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 16:00:21 -0300 Subject: [PATCH 123/146] =?UTF-8?q?documentaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/active_storage/service/jekyll_service.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index a2e04336..3b1db7ec 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -11,6 +11,9 @@ module ActiveStorage # sitio. class JekyllService < Service::DiskService # Genera un servicio para un sitio determinado + # + # @param :site [Site] + # @return [ActiveStorage::Service::JekyllService] def self.build_for_site(site:) new(root: File.join(site.path, 'public'), public: true).tap do |js| js.name = site.name.to_sym @@ -20,6 +23,13 @@ module ActiveStorage # Lo mismo que en DiskService agregando el nombre de archivo en la # firma. Esto permite que luego podamos guardar el archivo donde # corresponde. + # + # @param :key [String] + # @param :expires_in [Integer] + # @param :content_type [String] + # @param :content_length [Integer] + # @param :checksum [String] + # @return [String] def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) instrument :url, key: key do |payload| verified_token_with_expiration = ActiveStorage.verifier.generate( @@ -61,6 +71,9 @@ module ActiveStorage end # Crea una ruta para la llave con un nombre conocido. + # + # @param :key [String] + # @return [String] def path_for(key) File.join root, folder_for(key), filename_for(key) end From 6c9288b03bd64f907760d63a5c0ddd638b9ea74f Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 16:01:16 -0300 Subject: [PATCH 124/146] =?UTF-8?q?deprecar=20la=20migraci=C3=B3n=20de=20a?= =?UTF-8?q?rchivos=20est=C3=A1ticos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit siempre fue super lenta y falible --- app/models/site.rb | 7 +--- app/models/site/static_file_migration.rb | 52 ------------------------ 2 files changed, 1 insertion(+), 58 deletions(-) delete mode 100644 app/models/site/static_file_migration.rb diff --git a/app/models/site.rb b/app/models/site.rb index 5b78d625..7d4875e5 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -57,7 +57,7 @@ class Site < ApplicationRecord # Carga el sitio Jekyll una vez que se inicializa el modelo o después # de crearlo after_initialize :load_jekyll - after_create :load_jekyll, :static_file_migration! + after_create :load_jekyll # Cambiar el nombre del directorio before_update :update_name! before_save :add_private_key_if_missing! @@ -474,11 +474,6 @@ class Site < ApplicationRecord config.hostname = hostname end - # Migra los archivos a Sutty - def static_file_migration! - Site::StaticFileMigration.new(site: self).migrate! - end - # Valida si el sitio tiene al menos una forma de alojamiento asociada # y es la local # diff --git a/app/models/site/static_file_migration.rb b/app/models/site/static_file_migration.rb deleted file mode 100644 index 36a882bf..00000000 --- a/app/models/site/static_file_migration.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -class Site - # Obtiene todos los archivos relacionados en artículos del sitio y los - # sube a Sutty. - class StaticFileMigration - # Tipos de metadatos que contienen archivos - STATIC_TYPES = %i[file image].freeze - - attr_reader :site - - def initialize(site:) - @site = site - end - - def migrate! - modified = site.docs.map do |doc| - next unless STATIC_TYPES.map do |field| - next unless doc.attribute? field - next unless doc[field].path? - next unless doc[field].static_file - - true - end.any? - - log.write "#{doc.path.relative};no se pudo guardar\n" unless doc.save(validate: false) - - doc.path.absolute - end.compact - - log.close - - return if modified.empty? - - # TODO: Hacer la migración desde el servicio de creación de sitios? - site.repository.commit(file: modified, - message: I18n.t('sites.static_file_migration'), - usuarie: author) - end - - private - - def author - @author ||= GitAuthor.new email: "sutty@#{Site.domain}", - name: 'Sutty' - end - - def log - @log ||= File.open(File.join(site.path, 'migration.csv'), 'w') - end - end -end From f7d8a3ecf9e0142292ea819e7ab94c6b6b096a56 Mon Sep 17 00:00:00 2001 From: f Date: Sun, 6 Mar 2022 17:07:37 -0300 Subject: [PATCH 125/146] fixup! obtener el nombre de archivo desde la key --- app/lib/active_storage/service/jekyll_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 3b1db7ec..92b26e0e 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -67,7 +67,7 @@ module ActiveStorage # @param :key [String] # @return [String] def filename_for(key) - @filename_for ||= ActiveStorage::Blob.where(key: key).limit(1).pluck(:filename).first + ActiveStorage::Blob.where(key: key).limit(1).pluck(:filename).first end # Crea una ruta para la llave con un nombre conocido. From 87c94e95484e0765fbdb8a5094af47c0895d8eb2 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 7 Mar 2022 11:47:37 -0300 Subject: [PATCH 126/146] mostrar el html --- app/views/posts/show.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/posts/show.haml b/app/views/posts/show.haml index da6ac9db..e46114af 100644 --- a/app/views/posts/show.haml +++ b/app/views/posts/show.haml @@ -38,4 +38,4 @@ - cache [metadata, I18n.locale] do %section.editor{ id: attr, dir: dir } - = @post.public_send(attr).to_s.html_safe + = @post.public_send(attr).value.html_safe From c9edc86be34d8728d5a15f599553a90977893efc Mon Sep 17 00:00:00 2001 From: f Date: Mon, 7 Mar 2022 11:48:46 -0300 Subject: [PATCH 127/146] =?UTF-8?q?copiar=20una=20tabla=20desde=20producci?= =?UTF-8?q?=C3=B3n=20a=20desarrollo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1f0ca914..5a9ad7a8 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,15 @@ rake: ## Corre rake dentro del entorno de desarrollo (pasar argumentos con args= bundle: ## Corre bundle dentro del entorno de desarrollo (pasar argumentos con args=). $(hain) 'bundle $(args)' +psql := psql -h $(PG_HOST) -U $(PG_USER) -p $(PG_PORT) -d sutty +copy-table: + test -n "$(table)" + echo "truncate $(table) $(cascade);" | $(psql) + ssh $(delegate) docker exec postgresql pg_dump -U sutty -d sutty -t $(table) | $(psql) + +psql: + $(psql) + rubocop: ## Yutea el código que está por ser commiteado git status --porcelain \ | grep -E "^(A|M)" \ @@ -102,8 +111,7 @@ save: ## Subir la imagen Docker al nodo delegado @echo -e "\a" ota-js: assets ## Actualizar Javascript en el nodo delegado - sudo chgrp -R 82 public/ - rsync -avi --delete-after public/ root@$(delegate):/srv/sutty/srv/http/data/_$(public)/ + rsync -avi --delete-after --chown 1000:82 public/ root@$(delegate):/srv/sutty/srv/http/data/_$(public)/ ssh root@$(delegate) docker exec $(container) sh -c "cat /srv/http/tmp/puma.pid | xargs -r kill -USR2" ota: ## Actualizar Rails en el nodo delegado From 07546bafb24eff7e98c319252518e59d02b74cab Mon Sep 17 00:00:00 2001 From: f Date: Mon, 7 Mar 2022 12:49:49 -0300 Subject: [PATCH 128/146] reutilizar contenedores --- Dockerfile | 114 +++++++++++++------------------------------------- entrypoint.sh | 36 ++++++++++++++-- monit.conf | 22 ++++------ 3 files changed, 69 insertions(+), 103 deletions(-) diff --git a/Dockerfile b/Dockerfile index ee6ba871..24a6d09e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,125 +1,67 @@ -# Este Dockerfile está armado pensando en una compilación lanzada desde -# el mismo repositorio de trabajo. Cuando tengamos CI/CD algunas cosas -# como el tarball van a tener que cambiar porque ya vamos a haber hecho -# un clone/pull limpio. -FROM alpine:3.13.6 AS build +FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 AS build MAINTAINER "f " -ARG RAILS_MASTER_KEY ARG BRANCH - -# Un entorno base ENV BRANCH=$BRANCH -ENV SECRET_KEY_BASE solo_es_necesaria_para_correr_rake -ENV RAILS_ENV production -ENV RAILS_MASTER_KEY=$RAILS_MASTER_KEY -RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-json ruby-bigdecimal ruby-rake -RUN apk add --no-cache postgresql-libs git yarn brotli libssh2 python3 +RUN apk add --no-cache libxslt libxml2 tzdata postgresql-libs git yarn brotli libssh2 python3 findutils -RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` +USER rails +WORKDIR /srv/gems -# https://github.com/rubygems/rubygems/issues/2918 -# https://gitlab.alpinelinux.org/alpine/aports/issues/10808 -RUN apk add --no-cache patch -COPY ./rubygems-platform-musl.patch /tmp/ -RUN cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch +COPY --chown=rails:www-data ./Gemfile . +COPY --chown=rails:www-data ./Gemfile.lock . -# Agregar el usuario -RUN addgroup -g 82 -S www-data -RUN adduser -s /bin/sh -G www-data -h /home/app -D app -RUN install -dm750 -o app -g www-data /home/app/sutty -RUN gem install --no-document bundler:2.1.4 - -# Empezamos con la usuaria app -USER app -# Vamos a trabajar dentro de este directorio -WORKDIR /home/app/sutty - -# Copiamos solo el Gemfile para poder instalar las gemas necesarias -COPY --chown=app:www-data ./Gemfile . -COPY --chown=app:www-data ./Gemfile.lock . RUN bundle config set no-cache true RUN bundle config set specific_platform true RUN bundle install --path=./vendor --without='test development' -# Vaciar la caché -RUN rm vendor/ruby/2.7.0/cache/*.gem -# Copiar el repositorio git -COPY --chown=app:www-data ./.git/ ./.git/ -# Hacer un clon limpio del repositorio en lugar de copiar todos los -# archivos +COPY --chown=rails:www-data ./.git/ ./.git/ + RUN cd .. && git clone sutty checkout RUN cd ../checkout && git checkout $BRANCH -WORKDIR /home/app/checkout -# Traer las gemas: -RUN rm -rf ./vendor -RUN mv ../sutty/vendor ./vendor -RUN mv ../sutty/.bundle ./.bundle +WORKDIR /srv/checkout -# Instalar secretos -COPY --chown=app:root ./config/credentials.yml.enc ./config/ +RUN rm -rf ./vendor ./node_modules ./tmp/cache ./.git ./test ./doc +RUN mv ../gems/vendor ./vendor +RUN mv ../gems/.bundle ./.bundle +RUN find /srv/checkout/vendor/ruby/2.7.0 -maxdepth 3 -type d -name test -o -name spec -o -name rubocop | xargs -r rm -rf -RUN rm -rf ./node_modules ./tmp/cache ./.git ./test ./doc -# Eliminar archivos innecesarios -USER root -RUN apk add --no-cache findutils -RUN find /home/app/checkout/vendor/ruby/2.7.0 -maxdepth 3 -type d -name test -o -name spec -o -name rubocop | xargs -r rm -rf - -# Contenedor final -FROM registry.nulo.in/sutty/monit:3.13.6 +FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 ENV RAILS_ENV production # Pandoc -RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories +RUN echo 'https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories # Instalar las dependencias, separamos la librería de base de datos para # poder reutilizar este primer paso desde otros contenedores -RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-json ruby-bigdecimal ruby-rake ruby-irb ruby-io-console ruby-etc -RUN apk add --no-cache postgresql-libs libssh2 file rsync git jpegoptim vips -RUN apk add --no-cache ffmpeg imagemagick pandoc tectonic oxipng jemalloc -RUN apk add --no-cache git-lfs openssh-client patch - -# Chequear que la versión de ruby sea la correcta -RUN test "2.7.4" = `ruby -e 'puts RUBY_VERSION'` - -# https://github.com/rubygems/rubygems/issues/2918 -# https://gitlab.alpinelinux.org/alpine/aports/issues/10808 -COPY ./rubygems-platform-musl.patch /tmp/ -RUN apk add --no-cache patch && cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch && apk del patch - +# # Necesitamos yarn para que Jekyll pueda generar los sitios # XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso # principal -RUN apk add --no-cache yarn -# Instalar foreman para poder correr los servicios -RUN gem install --no-document --no-user-install bundler:2.1.4 foreman +RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 file \ + rsync git jpegoptim vips ffmpeg imagemagick pandoc tectonic \ + oxipng git-lfs openssh-client patch yarn daemonize ruby-webrick -# Agregar el grupo del servidor web y la usuaria -RUN addgroup -g 82 -S www-data -RUN adduser -s /bin/sh -G www-data -h /srv/http -D app +RUN gem install --no-document --no-user-install foreman + +USER rails + +RUN rm -rf /srv +COPY --from=build --chown=rails:www-data /srv/checkout /srv -# Convertirse en app para instalar -USER app -COPY --from=build --chown=app:www-data /home/app/checkout /srv/http -COPY --chown=app:www-data ./.git/ ./.git/ RUN rm -rf /srv/http/_sites /srv/http/_deploy RUN ln -s data/_storage /srv/http/_storage RUN ln -s data/_sites /srv/http/_sites RUN ln -s data/_deploy /srv/http/_deploy RUN ln -s data/_private /srv/http/_private -# Volver a root para cerrar la compilación USER root -# Instalar la configuración de monit -RUN install -m 640 -o root -g root /srv/http/monit.conf /etc/monit.d/sutty.conf -RUN apk add --no-cache daemonize ruby-webrick -RUN install -m 755 /srv/http/entrypoint.sh /usr/local/bin/sutty +RUN install -m 640 -o root -g root /srv/monit.conf /etc/monit.d/sutty.conf +RUN install -m 755 /srv/entrypoint.sh /usr/local/bin/sutty -# Mantener estos directorios! -VOLUME "/srv/http/data" +VOLUME "/srv/data" -# El puerto de puma EXPOSE 3000 EXPOSE 9394 diff --git a/entrypoint.sh b/entrypoint.sh index 3ae103bb..c6bfdb3b 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,10 +1,38 @@ #!/bin/sh set -e +s_pid=/srv/tmp/puma.pid +p_pid=/tmp/prometheus.pid + case $1 in - sutty) - su app -c "cd /srv/http && foreman start migrate" - daemonize -c /srv/http -u app /usr/bin/foreman start sutty + start) + su rails -c "cd /srv && foreman run migrate" + daemonize -c /srv -u rails /usr/bin/foreman start sutty + ;; + + stop) + cat $s_pid | xargs -r kill + ;; + + reload) + cat $s_pid | xargs -r kill -USR2 + ;; + + prometheus) + case $2 in + start) + rm -f $p_pid + daemonize -c /srv -p $p_pid -l $p_pid -u rails /usr/bin/foreman start prometheus + ;; + stop) + cat $p_pid | xargs -r kill + rm -f $p_pid + ;; + esac + ;; + + blazer) + test -z "$2" || b="_$2" + su rails -c "cd /srv && foreman run blazer$b" ;; - prometheus) daemonize -c /srv/http -p /tmp/prometheus.pid -l /tmp/prometheus.pid -u app /usr/bin/foreman start prometheus ;; esac diff --git a/monit.conf b/monit.conf index f574c56d..96c08d8a 100644 --- a/monit.conf +++ b/monit.conf @@ -1,31 +1,27 @@ -check process sutty with pidfile /srv/http/tmp/puma.pid - start program = "/usr/local/bin/sutty sutty" - stop program = "/bin/sh -c 'cat /srv/http/tmp/puma.pid | xargs kill'" +check process sutty with pidfile /srv/tmp/puma.pid + start program = "/usr/local/bin/sutty start" + stop program = "/usr/local/bin/sutty stop" check process prometheus with pidfile /tmp/prometheus.pid - start program = "/usr/local/bin/sutty prometheus" - stop program = "/bin/sh -c 'cat /tmp/prometheus.pid | xargs kill'" + start program = "/usr/local/bin/sutty prometheus start" + stop program = "/usr/local/bin/sutty prometheus start" check program blazer_5m - with path "/bin/sh -c 'cd /srv/http && foreman start blazer_5m'" - as uid "app" and gid "www-data" + with path "/usr/local/bin/sutty blazer 5m" every 5 cycles if status != 0 then alert check program blazer_1h - with path "/bin/sh -c 'cd /srv/http && foreman start blazer_1h'" - as uid "app" and gid "www-data" + with path "/usr/local/bin/sutty blazer 1h" every 60 cycles if status != 0 then alert check program blazer_1d - with path "/bin/sh -c 'cd /srv/http && foreman start blazer_1d'" - as uid "app" and gid "www-data" + with path "/usr/local/bin/sutty blazer 1d" every 1440 cycles if status != 0 then alert check program blazer - with path "/bin/sh -c 'cd /srv/http && foreman start blazer'" - as uid "app" and gid "www-data" + with path "/usr/local/bin/sutty blazer" every 61 cycles if status != 0 then alert From 9a68d80675fc943702c38eda5e3fd4af7d1f68bc Mon Sep 17 00:00:00 2001 From: f Date: Mon, 7 Mar 2022 19:37:05 -0300 Subject: [PATCH 129/146] simplificar el contenedor solo se encarga de las dependencias, el panel se deployea aparte. --- .dockerignore | 8 +------ Dockerfile | 58 ++++++--------------------------------------------- 2 files changed, 7 insertions(+), 59 deletions(-) diff --git a/.dockerignore b/.dockerignore index b9e4842e..afe4e8d7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,10 +1,4 @@ # Excluir todo * # Solo agregar lo que usamos en COPY -!./.git/ -!./rubygems-platform-musl.patch -!./Gemfile -!./Gemfile.lock -!./config/credentials.yml.enc -!./public/assets/ -!./public/packs/ +# !./archivo diff --git a/Dockerfile b/Dockerfile index 24a6d09e..ecf43cbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,67 +1,21 @@ -FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 AS build -MAINTAINER "f " - -ARG BRANCH -ENV BRANCH=$BRANCH - -RUN apk add --no-cache libxslt libxml2 tzdata postgresql-libs git yarn brotli libssh2 python3 findutils - -USER rails -WORKDIR /srv/gems - -COPY --chown=rails:www-data ./Gemfile . -COPY --chown=rails:www-data ./Gemfile.lock . - -RUN bundle config set no-cache true -RUN bundle config set specific_platform true -RUN bundle install --path=./vendor --without='test development' - -COPY --chown=rails:www-data ./.git/ ./.git/ - -RUN cd .. && git clone sutty checkout -RUN cd ../checkout && git checkout $BRANCH - -WORKDIR /srv/checkout - -RUN rm -rf ./vendor ./node_modules ./tmp/cache ./.git ./test ./doc -RUN mv ../gems/vendor ./vendor -RUN mv ../gems/.bundle ./.bundle -RUN find /srv/checkout/vendor/ruby/2.7.0 -maxdepth 3 -type d -name test -o -name spec -o -name rubocop | xargs -r rm -rf - FROM registry.nulo.in/sutty/rails:3.13.6-2.7.5 +ARG PANDOC_VERSION=2.17.1.1 ENV RAILS_ENV production -# Pandoc -RUN echo 'https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories - # Instalar las dependencias, separamos la librería de base de datos para # poder reutilizar este primer paso desde otros contenedores # # Necesitamos yarn para que Jekyll pueda generar los sitios # XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso # principal -RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 file \ - rsync git jpegoptim vips ffmpeg imagemagick pandoc tectonic \ - oxipng git-lfs openssh-client patch yarn daemonize ruby-webrick +RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 \ + rsync git jpegoptim vips tectonic oxipng git-lfs openssh-client \ + yarn daemonize ruby-webrick 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 -USER rails - -RUN rm -rf /srv -COPY --from=build --chown=rails:www-data /srv/checkout /srv - -RUN rm -rf /srv/http/_sites /srv/http/_deploy -RUN ln -s data/_storage /srv/http/_storage -RUN ln -s data/_sites /srv/http/_sites -RUN ln -s data/_deploy /srv/http/_deploy -RUN ln -s data/_private /srv/http/_private - -USER root -RUN install -m 640 -o root -g root /srv/monit.conf /etc/monit.d/sutty.conf -RUN install -m 755 /srv/entrypoint.sh /usr/local/bin/sutty - -VOLUME "/srv/data" +VOLUME "/srv" EXPOSE 3000 EXPOSE 9394 From 81cbafef66e31ba60ac6bf396adc88696d85f142 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 7 Mar 2022 20:52:33 -0300 Subject: [PATCH 130/146] validaciones --- app/models/metadata_file.rb | 2 +- app/models/metadata_image.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 1c859481..5be7f84c 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -19,7 +19,7 @@ class MetadataFile < MetadataTemplate errors << I18n.t("metadata.#{type}.site_invalid") if site.invalid? errors << I18n.t("metadata.#{type}.path_required") if path_missing? errors << I18n.t("metadata.#{type}.no_file_for_description") if no_file_for_description? - errors << I18n.t("metadata.#{type}.attachment_missing") unless static_file + errors << I18n.t("metadata.#{type}.attachment_missing") if path? && !static_file errors.compact! errors.empty? diff --git a/app/models/metadata_image.rb b/app/models/metadata_image.rb index f86c5c26..85ee062a 100644 --- a/app/models/metadata_image.rb +++ b/app/models/metadata_image.rb @@ -5,7 +5,7 @@ class MetadataImage < MetadataFile def validate super - errors << I18n.t('metadata.image.not_an_image') unless image? + errors << I18n.t('metadata.image.not_an_image') unless path? && image? errors.compact! errors.empty? From 7de96a4581a1d1483628c3da11f99e1a4e454ec0 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 8 Mar 2022 13:10:34 -0300 Subject: [PATCH 131/146] =?UTF-8?q?usar=20la=20ruta=20absoluta=20tambi?= =?UTF-8?q?=C3=A9n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit en producción usamos links simbólicos entre directorios y sin resolver la ubicación real de los sitios estábamos generando rutas erróneas. --- app/models/metadata_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 5be7f84c..31becc64 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -119,7 +119,7 @@ class MetadataFile < MetadataTemplate end def relative_destination_path_with_filename - destination_path_with_filename.relative_path_from(site.path) + destination_path_with_filename.relative_path_from(Pathname.new(site.path).realpath) end def static_file_path From 79974b710497c2db0498de7f9f4375f2802711c9 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 8 Mar 2022 13:21:13 -0300 Subject: [PATCH 132/146] =?UTF-8?q?validar=20im=C3=A1genes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_image.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_image.rb b/app/models/metadata_image.rb index 85ee062a..fc61a4d7 100644 --- a/app/models/metadata_image.rb +++ b/app/models/metadata_image.rb @@ -5,7 +5,7 @@ class MetadataImage < MetadataFile def validate super - errors << I18n.t('metadata.image.not_an_image') unless path? && image? + errors << I18n.t('metadata.image.not_an_image') if path? && !image? errors.compact! errors.empty? From c63ad496d8718e055edbac4898d836ff2b96305d Mon Sep 17 00:00:00 2001 From: f Date: Wed, 9 Mar 2022 14:19:50 -0300 Subject: [PATCH 133/146] ota con el nuevo container --- Makefile | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 5a9ad7a8..584d07d1 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ hain ?= ENV_FILE=.env $(HAINISH)## Ubicación de Hainish # # Production es el entorno de panel.sutty.nl ifeq ($(env),production) -container ?= sutty +container ?= panel ## TODO: Cambiar a otra cosa branch ?= rails public ?= public @@ -115,15 +115,9 @@ ota-js: assets ## Actualizar Javascript en el nodo delegado ssh root@$(delegate) docker exec $(container) sh -c "cat /srv/http/tmp/puma.pid | xargs -r kill -USR2" ota: ## Actualizar Rails en el nodo delegado - umask 022; git format-patch $(commit) - ssh $(delegate) mkdir -p /tmp/patches-$(commit)/ - scp ./0*.patch $(delegate):/tmp/patches-$(commit)/ - scp ./ota.sh $(delegate):/tmp/ - ssh $(delegate) docker cp /tmp/patches-$(shell echo $(commit) | cut -d / -f 1) $(container):/tmp/ - ssh $(delegate) docker cp /tmp/ota.sh $(container):/usr/local/bin/ota - ssh $(delegate) docker exec $(container) apk add --no-cache patch - ssh $(delegate) docker exec $(container) ota $(commit) - rm ./0*.patch + ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl pull ; true + ssh $(delegate) chown -R 1000:82 /srv/sutty/srv/http/panel.sutty.nl + ssh $(delegate) docker exec $(container) rails reload # Todos los archivos de assets. Si alguno cambia, se van a recompilar # los assets que luego se suben al nodo delegado. From d4d1acc8d91e5cf23db4fa056a5c0520d7179c43 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 9 Mar 2022 19:32:53 -0300 Subject: [PATCH 134/146] retrocompatibilidad los archivos subidos como archivos locales ya estaban copiados al sitio --- app/models/metadata_file.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 31becc64..0f50d643 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -123,7 +123,12 @@ class MetadataFile < MetadataTemplate end def static_file_path - static_file.blob.service.path_for(static_file.key) + case static_file.blob.service.name + when :local + File.join(site.path, 'public', static_file.key, static_file.filename.to_s) + else + static_file.blob.service.path_for(static_file.key) + end end # No hay archivo pero se lo describió From 263394baef931995b78e4a962a6bebfbc5f76b27 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 18 Mar 2022 15:42:39 -0300 Subject: [PATCH 135/146] no fallar al serializar Site#everything_of el problema era que los archivos subidos no se pueden marshalear y estamos usando MetadataTemplate#values para poder cachearlos. closes #1315 closes #1316 closes #1842 closes #2368 closes #2369 closes #2370 closes #2371 closes #2372 closes #2373 closes #2393 closes #2396 closes #2922 closes #3347 closes #3350 closes #3353 closes #3356 closes #3437 closes #3486 closes #3487 closes #3488 closes #3551 closes #3554 closes #4229 closes #4256 closes #4259 closes #4262 closes #4265 closes #4553 closes #4556 closes #4603 closes #4606 closes #4647 closes #4759 closes #4767 closes #4787 closes #4794 closes #4833 closes #4835 closes #4836 closes #4875 closes #4876 closes #4877 closes #4879 closes #4881 closes #4882 closes #4883 closes #4884 closes #4885 closes #4886 closes #4887 closes #4888 closes #4889 closes #4890 closes #4891 closes #4892 closes #4906 closes #4907 closes #4908 closes #4976 closes #4977 closes #4978 closes #4979 closes #4980 closes #4981 closes #4982 closes #4983 closes #4984 closes #4985 closes #4986 closes #4987 --- app/models/metadata_file.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 0f50d643..2c1a6d59 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -13,6 +13,11 @@ class MetadataFile < MetadataTemplate value == default_value end + # No hay valores sugeridos para archivos subidos. + # + # XXX: Esto ayuda a deserializar en {Site#everything_of} + def values; end + def validate super From c5896a63cfdd48128592087aac35aaf1a6523df1 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 22 Mar 2022 20:15:59 -0300 Subject: [PATCH 136/146] resiliencia closes #5061 closes #5060 closes #5058 closes #5057 closes #5056 closes #5054 closes #5053 closes #5051 closes #5050 closes #5048 closes #5047 closes #5045 closes #5042 closes #5040 closes #5038 closes #5036 closes #5034 closes #5033 closes #5032 closes #5030 closes #4946 closes #3856 closes #3562 closes #3558 closes #3557 closes #2707 closes #2706 closes #2705 closes #2703 closes #2702 closes #2297 closes #2296 closes #2295 closes #1970 closes #1969 closes #1768 --- app/models/metadata_file.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 2c1a6d59..eca87478 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -121,6 +121,13 @@ class MetadataFile < MetadataTemplate # @return [Pathname] def destination_path_with_filename destination_path.realpath + # Si el archivo no llegara a existir, en lugar de hacer fallar todo, + # devolvemos la ruta original, que puede ser el archivo que no existe + # o vacía si se está subiendo uno. + rescue Errno::ENOENT => e + ExceptionNotifier.notify_exception(e) + + value['path'] end def relative_destination_path_with_filename From ecb823f40746b4eae0d61cc3acca63ac620881f0 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 23 Mar 2022 11:37:00 -0300 Subject: [PATCH 137/146] al migrar un archivo reutilizar la key --- app/models/metadata_file.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index eca87478..71d3f049 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -78,7 +78,9 @@ class MetadataFile < MetadataTemplate if (blob_id = ActiveStorage::Blob.where(key: key_from_path).pluck(:id).first) site.static_files.find_by(blob_id: blob_id) elsif path? && pathname.exist? && site.static_files.attach(io: pathname.open, filename: pathname.basename) - site.static_files.last + site.static_files.last.tap do |s| + s.blob.update(key: key_from_path) + end end end end From b4532e94ca3ed5c33f50b236c31df8d38fdfb200 Mon Sep 17 00:00:00 2001 From: Nulo Date: Sat, 2 Apr 2022 14:34:12 +0000 Subject: [PATCH 138/146] Agregar citas al editor --- app/assets/stylesheets/editor.scss | 6 +++++- app/javascript/editor/types/blocks.ts | 8 +++++++- app/javascript/editor/utils.ts | 1 + app/models/metadata_template.rb | 2 +- app/views/posts/attributes/_content.haml | 3 +++ config/locales/en.yml | 1 + config/locales/es.yml | 1 + 7 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/editor.scss b/app/assets/stylesheets/editor.scss index 30fab60a..85bf4471 100644 --- a/app/assets/stylesheets/editor.scss +++ b/app/assets/stylesheets/editor.scss @@ -67,7 +67,11 @@ .editor-content { min-height: 480px; - p, h1, h2, h3, h4, h5, h6, ul, li, figcaption { outline: #ccc solid thin; } + p, h1, h2, h3, h4, h5, h6, ul, li, blockquote, figcaption { outline: #ccc solid thin; } + blockquote { + border-left: #555 solid .25em; + padding: .75em; + } strong, em, del, u, sub, sup, small { background: #0002; } a { background: #13fefe50; } [data-editor-selected] { outline: #f206f9 solid thick; } diff --git a/app/javascript/editor/types/blocks.ts b/app/javascript/editor/types/blocks.ts index 2e2dea7e..956b79d9 100644 --- a/app/javascript/editor/types/blocks.ts +++ b/app/javascript/editor/types/blocks.ts @@ -21,11 +21,12 @@ function makeBlock(tag: string): EditorBlock { } export const li: EditorBlock = makeBlock("li"); +const paragraph: EditorBlock = makeBlock("p"); // XXX: si agregás algo acá, agregalo a blockNames // (y probablemente le quieras hacer un botón en app/views/posts/attributes/_content.haml) export const blocks: { [propName: string]: EditorBlock } = { - paragraph: makeBlock("p"), + paragraph, h1: makeBlock("h1"), h2: makeBlock("h2"), h3: makeBlock("h3"), @@ -42,6 +43,11 @@ export const blocks: { [propName: string]: EditorBlock } = { allowedChildren: ["li"], handleEmpty: li, }, + blockquote: { + ...makeBlock("blockquote"), + allowedChildren: blockNames, + handleEmpty: paragraph, + }, }; export function setupButtons(editor: Editor): void { diff --git a/app/javascript/editor/utils.ts b/app/javascript/editor/utils.ts index 167c0a6d..b0bed66e 100644 --- a/app/javascript/editor/utils.ts +++ b/app/javascript/editor/utils.ts @@ -10,6 +10,7 @@ export const blockNames = [ "h6", "unordered_list", "ordered_list", + "blockquote", ]; export const markNames = [ "bold", diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index 5baa7a4a..26351249 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -199,7 +199,7 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, end def allowed_tags - @allowed_tags ||= %w[strong em del u mark p h1 h2 h3 h4 h5 h6 ul ol li img iframe audio video div figure + @allowed_tags ||= %w[strong em del u mark p h1 h2 h3 h4 h5 h6 ul ol li img iframe audio video div figure blockquote figcaption a sub sup small].freeze end diff --git a/app/views/posts/attributes/_content.haml b/app/views/posts/attributes/_content.haml index 4ae70ba0..36b88872 100644 --- a/app/views/posts/attributes/_content.haml +++ b/app/views/posts/attributes/_content.haml @@ -95,6 +95,9 @@ %button.btn{ type: 'button', title: t('editor.right'), data: { editor_button: 'parentBlock-right' } }> %i.fa.fa-fw.fa-align-right> %span.sr-only>= t('editor.right') + %button.btn{ type: 'button', title: t('editor.blockquote'), data: { editor_button: 'block-blockquote' } }> + %i.fa.fa-fw.fa-quote-left> + %span.sr-only>= t('editor.blockquote') -# HAML cringe .editor-auxiliary-toolbar.mt-1.scrollbar-black{ data: { editor_auxiliary_toolbar: '' } } diff --git a/config/locales/en.yml b/config/locales/en.yml index b814796d..99fbc8b1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -568,6 +568,7 @@ en: left: Left right: Right center: Center + blockquote: Quote color: Color text-color: Text color multimedia: Media diff --git a/config/locales/es.yml b/config/locales/es.yml index a6fbd407..3ed72d63 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -576,6 +576,7 @@ es: left: Izquierda right: Derecha center: Centro + blockquote: Cita color: Color text-color: Color del texto multimedia: Multimedia From 455070f2ea576775fe28f0bb2d01a6b62d2dc7d0 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 4 Apr 2022 13:56:40 -0300 Subject: [PATCH 139/146] normalizar todas las strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit convierte la codificación de windows/osx en unicode normalizado. --- app/models/metadata_markdown.rb | 2 +- app/models/metadata_markdown_content.rb | 2 +- app/models/metadata_permalink.rb | 2 +- app/models/metadata_string.rb | 2 +- app/models/metadata_template.rb | 9 ++++++--- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/models/metadata_markdown.rb b/app/models/metadata_markdown.rb index 1e8b4fc8..7816ec33 100644 --- a/app/models/metadata_markdown.rb +++ b/app/models/metadata_markdown.rb @@ -12,6 +12,6 @@ class MetadataMarkdown < MetadataText # markdown y se eliminan autolinks. Mejor es habilitar la generación # SAFE de CommonMark en la configuración del sitio. def sanitize(string) - string + string.unicode_normalize(:nfkc) end end diff --git a/app/models/metadata_markdown_content.rb b/app/models/metadata_markdown_content.rb index 92a1ab21..cb4124db 100644 --- a/app/models/metadata_markdown_content.rb +++ b/app/models/metadata_markdown_content.rb @@ -25,6 +25,6 @@ class MetadataMarkdownContent < MetadataText # markdown y se eliminan autolinks. Mejor es deshabilitar la # generación SAFE de CommonMark en la configuración del sitio. def sanitize(string) - string.tr("\r", '') + string.tr("\r", '').unicode_normalize(:nfkc) end end diff --git a/app/models/metadata_permalink.rb b/app/models/metadata_permalink.rb index 59b68461..9b0c063c 100644 --- a/app/models/metadata_permalink.rb +++ b/app/models/metadata_permalink.rb @@ -19,7 +19,7 @@ class MetadataPermalink < MetadataString # puntos suspensivos, la primera / para que siempre sea relativa y # agregamos una / al final si la ruta no tiene extensión. def sanitize(value) - value = value.strip.gsub('..', '/').gsub('./', '').squeeze('/') + value = value.strip.unicode_normalize(:nfkc).gsub('..', '/').gsub('./', '').squeeze('/') value = value[1..-1] if value.start_with? '/' value += '/' if File.extname(value).blank? diff --git a/app/models/metadata_string.rb b/app/models/metadata_string.rb index 95aac4d4..28bfe82a 100644 --- a/app/models/metadata_string.rb +++ b/app/models/metadata_string.rb @@ -17,7 +17,7 @@ class MetadataString < MetadataTemplate def sanitize(string) return '' if string.blank? - sanitizer.sanitize(string.strip, + sanitizer.sanitize(string.strip.unicode_normalize(:nfkc), tags: [], attributes: []).strip.html_safe end diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index 5baa7a4a..a72f8e83 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -184,9 +184,12 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, return if string.nil? return string unless string.is_a? String - sanitizer.sanitize(string.tr("\r", ''), - tags: allowed_tags, - attributes: allowed_attributes).strip.html_safe + sanitizer + .sanitize(string.tr("\r", '').unicode_normalize(:nfkc), + tags: allowed_tags, + attributes: allowed_attributes) + .strip + .html_safe end def sanitizer From 30bc14d83e790c6540a6fb19e8afa8184eef6c37 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 4 Apr 2022 14:27:00 -0300 Subject: [PATCH 140/146] normalizar los nombres de archivo enviados por subida directa --- .../direct_uploads_controller_decorator.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/controllers/active_storage/direct_uploads_controller_decorator.rb b/app/controllers/active_storage/direct_uploads_controller_decorator.rb index f27c4cfb..3052f974 100644 --- a/app/controllers/active_storage/direct_uploads_controller_decorator.rb +++ b/app/controllers/active_storage/direct_uploads_controller_decorator.rb @@ -11,6 +11,17 @@ module ActiveStorage blob = ActiveStorage::Blob.create_before_direct_upload!(service_name: session[:service_name], **blob_args) render json: direct_upload_json(blob) end + + private + + # Normalizar los caracteres unicode en los nombres de archivos + # para que puedan propagarse correctamente a través de todo el + # stack. + def blob_args + params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type, metadata: {}).to_h.symbolize_keys.tap do |ba| + ba[:filename] = ba[:filename].unicode_normalize(:nfkc) + end + end end end end From 4d6a26d67178ec90e4b8f580889cee528f74d195 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 4 Apr 2022 14:32:58 -0300 Subject: [PATCH 141/146] normalizar todos los nombres de archivos subidos --- .../http/uploaded_file_decorator.rb | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/lib/action_dispatch/http/uploaded_file_decorator.rb diff --git a/app/lib/action_dispatch/http/uploaded_file_decorator.rb b/app/lib/action_dispatch/http/uploaded_file_decorator.rb new file mode 100644 index 00000000..c171c81c --- /dev/null +++ b/app/lib/action_dispatch/http/uploaded_file_decorator.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module ActionDispatch + module Http + # Normaliza los nombres de archivo para que se propaguen + # correctamente a través de todo el stack. + module UploadedFileDecorator + extend ActiveSupport::Concern + + included do + # Devolver el nombre de archivo con caracteres unicode + # normalizados + def original_filename + @original_filename.unicode_normalize(:nfkc) + end + end + end + end +end + +ActionDispatch::Http::UploadedFile.include ActionDispatch::Http::UploadedFileDecorator From 13561a5f717af796371a244daf11b2e7d3d029d7 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 19 Apr 2022 10:07:10 -0300 Subject: [PATCH 142/146] =?UTF-8?q?no=20generar=20errores=20si=20se=20env?= =?UTF-8?q?=C3=ADa=20el=20reporte=20incompleto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #5136 --- app/controllers/api/v1/csp_reports_controller.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v1/csp_reports_controller.rb b/app/controllers/api/v1/csp_reports_controller.rb index bc6cfae0..f1d7a376 100644 --- a/app/controllers/api/v1/csp_reports_controller.rb +++ b/app/controllers/api/v1/csp_reports_controller.rb @@ -6,6 +6,9 @@ module Api class CspReportsController < BaseController skip_forgery_protection + # No queremos indicar que algo salió mal + rescue_from ActionController::ParameterMissing, with: :csp_report_created + # Crea un reporte de CSP intercambiando los guiones medios por # bajos # @@ -18,7 +21,7 @@ module Api csp.id = SecureRandom.uuid csp.save - render json: {}, status: :created + csp_report_created end private @@ -39,6 +42,10 @@ module Api :'column-number', :'source-file') end + + def csp_report_created + render json: {}, status: :created + end end end end From 52f446fcf1e8fc9c31a1ee9ef1028f320bb24304 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 19 Apr 2022 10:57:01 -0300 Subject: [PATCH 143/146] refactorizacion --- app/controllers/api/v1/csp_reports_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/v1/csp_reports_controller.rb b/app/controllers/api/v1/csp_reports_controller.rb index f1d7a376..ea186729 100644 --- a/app/controllers/api/v1/csp_reports_controller.rb +++ b/app/controllers/api/v1/csp_reports_controller.rb @@ -14,9 +14,9 @@ module Api # # TODO: Aplicar rate_limit def create - csp = CspReport.new(csp_report_params.to_h.map do |k, v| - [k.tr('-', '_'), v] - end.to_h) + csp = CspReport.new(csp_report_params.to_h.transform_keys do |k| + k.tr('-', '_') + end) csp.id = SecureRandom.uuid csp.save From eb7d0679bbc411d8f2afe831a23d958bc0e91abd Mon Sep 17 00:00:00 2001 From: f Date: Thu, 28 Apr 2022 10:34:57 -0300 Subject: [PATCH 144/146] normalizar strings sin romperlas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit en castellano no nos afectó pero en árabe rompe el significado --- .../active_storage/direct_uploads_controller_decorator.rb | 2 +- app/lib/action_dispatch/http/uploaded_file_decorator.rb | 2 +- app/models/metadata_markdown.rb | 2 +- app/models/metadata_markdown_content.rb | 2 +- app/models/metadata_permalink.rb | 2 +- app/models/metadata_string.rb | 2 +- app/models/metadata_template.rb | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/active_storage/direct_uploads_controller_decorator.rb b/app/controllers/active_storage/direct_uploads_controller_decorator.rb index 3052f974..c62dae2a 100644 --- a/app/controllers/active_storage/direct_uploads_controller_decorator.rb +++ b/app/controllers/active_storage/direct_uploads_controller_decorator.rb @@ -19,7 +19,7 @@ module ActiveStorage # stack. def blob_args params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type, metadata: {}).to_h.symbolize_keys.tap do |ba| - ba[:filename] = ba[:filename].unicode_normalize(:nfkc) + ba[:filename] = ba[:filename].unicode_normalize end end end diff --git a/app/lib/action_dispatch/http/uploaded_file_decorator.rb b/app/lib/action_dispatch/http/uploaded_file_decorator.rb index c171c81c..0bdebdc0 100644 --- a/app/lib/action_dispatch/http/uploaded_file_decorator.rb +++ b/app/lib/action_dispatch/http/uploaded_file_decorator.rb @@ -11,7 +11,7 @@ module ActionDispatch # Devolver el nombre de archivo con caracteres unicode # normalizados def original_filename - @original_filename.unicode_normalize(:nfkc) + @original_filename.unicode_normalize end end end diff --git a/app/models/metadata_markdown.rb b/app/models/metadata_markdown.rb index 7816ec33..a09e351c 100644 --- a/app/models/metadata_markdown.rb +++ b/app/models/metadata_markdown.rb @@ -12,6 +12,6 @@ class MetadataMarkdown < MetadataText # markdown y se eliminan autolinks. Mejor es habilitar la generación # SAFE de CommonMark en la configuración del sitio. def sanitize(string) - string.unicode_normalize(:nfkc) + string.unicode_normalize end end diff --git a/app/models/metadata_markdown_content.rb b/app/models/metadata_markdown_content.rb index cb4124db..75088e30 100644 --- a/app/models/metadata_markdown_content.rb +++ b/app/models/metadata_markdown_content.rb @@ -25,6 +25,6 @@ class MetadataMarkdownContent < MetadataText # markdown y se eliminan autolinks. Mejor es deshabilitar la # generación SAFE de CommonMark en la configuración del sitio. def sanitize(string) - string.tr("\r", '').unicode_normalize(:nfkc) + string.tr("\r", '').unicode_normalize end end diff --git a/app/models/metadata_permalink.rb b/app/models/metadata_permalink.rb index 9b0c063c..30ad32cc 100644 --- a/app/models/metadata_permalink.rb +++ b/app/models/metadata_permalink.rb @@ -19,7 +19,7 @@ class MetadataPermalink < MetadataString # puntos suspensivos, la primera / para que siempre sea relativa y # agregamos una / al final si la ruta no tiene extensión. def sanitize(value) - value = value.strip.unicode_normalize(:nfkc).gsub('..', '/').gsub('./', '').squeeze('/') + value = value.strip.unicode_normalize.gsub('..', '/').gsub('./', '').squeeze('/') value = value[1..-1] if value.start_with? '/' value += '/' if File.extname(value).blank? diff --git a/app/models/metadata_string.rb b/app/models/metadata_string.rb index 28bfe82a..c1d888b1 100644 --- a/app/models/metadata_string.rb +++ b/app/models/metadata_string.rb @@ -17,7 +17,7 @@ class MetadataString < MetadataTemplate def sanitize(string) return '' if string.blank? - sanitizer.sanitize(string.strip.unicode_normalize(:nfkc), + sanitizer.sanitize(string.strip.unicode_normalize, tags: [], attributes: []).strip.html_safe end diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index a72f8e83..ddcd100e 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -185,7 +185,7 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, return string unless string.is_a? String sanitizer - .sanitize(string.tr("\r", '').unicode_normalize(:nfkc), + .sanitize(string.tr("\r", '').unicode_normalize, tags: allowed_tags, attributes: allowed_attributes) .strip From 2a416b4e670fc8690538a2de70d501b72e0ee436 Mon Sep 17 00:00:00 2001 From: Nulo Date: Wed, 13 Jul 2022 21:43:44 +0000 Subject: [PATCH 145/146] editor: No reportar error cuando no se selecciona un archivo para subir --- app/javascript/editor/types/multimedia.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/javascript/editor/types/multimedia.ts b/app/javascript/editor/types/multimedia.ts index 2af9643a..29d2a0ab 100644 --- a/app/javascript/editor/types/multimedia.ts +++ b/app/javascript/editor/types/multimedia.ts @@ -137,8 +137,10 @@ export function setupAuxiliaryToolbar(editor: Editor): void { "click", (event) => { const files = editor.toolbar.auxiliary.multimedia.fileEl.files; - if (!files || !files.length) - throw new Error("no hay archivos para subir"); + if (!files || !files.length) { + console.info("no hay archivos para subir"); + return; + } const file = files[0]; const selectedEl = editor.contentEl.querySelector( From 64e93506b77de088f3696a1588e5dfad2873bed8 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 3 Aug 2022 12:53:50 -0300 Subject: [PATCH 146/146] =?UTF-8?q?eliminar=20c=C3=B3digo=20que=20no=20se?= =?UTF-8?q?=20usa=20m=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/post/template_field.rb | 360 ------------------------------ 1 file changed, 360 deletions(-) delete mode 100644 app/models/post/template_field.rb diff --git a/app/models/post/template_field.rb b/app/models/post/template_field.rb deleted file mode 100644 index 08da933b..00000000 --- a/app/models/post/template_field.rb +++ /dev/null @@ -1,360 +0,0 @@ -# frozen_string_literal: true - -# Representa los distintos tipos de campos que pueden venir de una -# plantilla compleja -class Post - class TemplateField - attr_reader :post, :contents, :key - - STRING_VALUES = %w[string text url number email password date year - image video audio document].freeze - - # Tipo de valores que son archivos - FILE_TYPES = %w[image video audio document].freeze - - def initialize(post, key, contents) - @post = post - @key = key - @contents = contents - end - - def title - contents.dig('title') if complex? - end - - def subtitle - contents.dig('subtitle') if complex? - end - - # Obtiene el valor - def value - complex? ? contents.dig('value') : contents - end - - def max - return 0 if simple? - - contents.fetch('max', 0) - end - - def min - return 0 if simple? - - contents.fetch('min', 0) - end - - # TODO: volver elegante! - def type - return @type if @type - - if image? - @type = 'image' - elsif email? - @type = 'email' - elsif url? - @type = 'url' - elsif number? - @type = 'number' - elsif password? - @type = 'password' - elsif date? - @type = 'date' - elsif year? - @type = 'year' - elsif text_area? - @type = 'text_area' - elsif check_box_group? - @type = 'check_box_group' - elsif radio_group? - @type = 'radio_group' - elsif string? - @type = 'text' - # TODO: volver a hacer funcionar esto y ahorranos los multiple: - # false - elsif string? && contents.split('/', 2).count == 2 - @type = 'select' - elsif nested? - @type = 'table' - elsif array? - @type = 'select' - elsif boolean? - @type = 'check_box' - end - - @type - end - - # Devuelve los valores vacíos según el tipo - def empty_value - if string? - '' - elsif nested? - # TODO: devolver las keys también - {} - elsif array? - [] - elsif boolean? - false - end - end - - def cols - complex? && contents.dig('cols') - end - - def align - complex? && contents.dig('align') - end - - # El campo es requerido si es complejo y se especifica que lo sea - def required? - complex? && contents.dig('required') - end - - def boolean? - value.is_a?(FalseClass) || value.is_a?(TrueClass) - end - - def string? - value.is_a? String - end - - def text_area? - value == 'text' - end - - def url? - value == 'url' - end - - def email? - value == 'email' || value == 'mail' - end - alias mail? email? - - def date? - value == 'date' - end - - def password? - value == 'password' - end - - def number? - value == 'number' - end - - def year? - value == 'year' - end - - def file? - string? && FILE_TYPES.include?(value) - end - - def image? - array? ? value.first == 'image' : value == 'image' - end - - # Si la plantilla es simple no está admitiendo Hashes como valores - def simple? - !complex? - end - - def complex? - contents.is_a? Hash - end - - # XXX Retrocompatibilidad - def to_s - key - end - - # Convierte el campo en un parámetro - def to_param - if nested? - { key.to_sym => {} } - elsif array? && multiple? - { key.to_sym => [] } - else - key.to_sym - end - end - - # Convierte la plantilla en el formato de front_matter - def to_front_matter - { key => empty_value } - end - - def check_box_group? - array? && (complex? && contents.fetch('checkbox', false)) - end - - def radio_group? - array? && (complex? && contents.fetch('radio', false)) - end - - def array? - value.is_a? Array - end - - # TODO: detectar cuando es complejo y tomar el valor de :multiple - def multiple? - # si la plantilla es simple, es multiple cuando tenemos un array - return array? if simple? - - array? && contents.fetch('multiple', true) - end - - # Detecta si el valor es una tabla de campos - def nested? - value.is_a?(Hash) || (array? && value.first.is_a?(Hash)) - end - - # Un campo acepta valores abiertos si no es un array con múltiples - # elementos - def open? - # Todos los valores simples son abiertos - return true unless complex? - return false unless array? - - # La cosa se complejiza cuando tenemos valores complejos - # - # Si tenemos una lista cerrada de valores, necesitamos saber si el - # campo es abierto o cerrado. Si la lista tiene varios elementos, - # es una lista cerrada, opcionalmente abierta. Si la lista tiene - # un elemento, quiere decir que estamos autocompletando desde otro - # lado. - contents.fetch('open', value.count < 2) - end - - def closed? - !open? - end - - # Determina si los valores del campo serán públicos después - # - # XXX Esto es solo una indicación, el theme Jekyll tiene que - # respetarlos por su lado luego - def public? - # Todos los campos son públicos a menos que se indique lo - # contrario - simple? || contents.fetch('public', true) - end - - def private? - !public? - end - - def human - h = key.humanize - - h - end - - def label - h = (complex? && contents.dig('label')) || human - h += ' *' if required? - - h - end - - def help - complex? && contents.dig('help') - end - - def nested_fields - return unless nested? - - v = value - v = value.first if array? - - @nested_fields ||= v.map do |k, sv| - Post::TemplateField.new post, k, sv - end - end - - # Obtiene los valores posibles para el campo de la plantilla - def values - return 'false' if value == false - return 'true' if value == true - # XXX por alguna razón `value` no refiere a value() :/ - return '' if STRING_VALUES.include? value - # Las listas cerradas no necesitan mayor procesamiento - return value if array? && closed? && value.count > 1 - # Y las vacías tampoco - return value if array? && value.empty? - # Ahorrarnos el trabajo - return @values if @values - - # Duplicar el valor para no tener efectos secundarios luego (?) - value = self.value.dup - - # Para obtener los valores posibles, hay que procesar la string y - # convertirla a parametros - - # Si es una array de un solo elemento, es un indicador de que - # tenemos que rellenarla con los valores que indica. - # - # El primer valor es el que trae la string de autocompletado - values = array? ? value.shift : value - - # Si el valor es un array con más de un elemento, queremos usar - # esas opciones. Pero si además es abierto, queremos traer los - # valores cargados anteriormente. - - # Procesamos el valor, buscando : como separador de campos que - # queremos encontrar y luego los unimos - _value = (values&.split(':', 2) || []).map do |v| - # Tenemos hasta tres niveles de búsqueda - collection, attr, subattr = v.split('/', 3) - - if collection == 'site' - # TODO: puede ser peligroso permitir acceder a cualquier - # atributo de site? No estamos trayendo nada fuera de - # lo normal - post.site.send(attr.to_sym) - # Si hay un subatributo, tenemos que averiguar todos los - # valores dentro de el - # TODO volver elegante! - # TODO volver recursivo! - elsif subattr - post.site.everything_of(attr, lang: collection) - .compact - .map { |sv| sv[subattr] } - .flatten - .compact - .uniq - else - post.site.everything_of(attr, lang: collection).compact - end - end - - # Si el valor es abierto, sumar los valores auto-completados a - # lo pre-cargados. - # - # En este punto _value es un array de 1 o 2 arrays, si es de uno, - # value tambien tiene que serlo. Si es de 2, hay que unir cada - # una - if open? - if _value.count == 1 - _value = [(_value.first + value).uniq] - elsif _value.count == 2 - _value = _value.each_with_index.map do |v, i| - v + value.fetch(i, []) - end - end - end - - # Crea un array de arrays, útil para los select - # [ [ 1, a ], [ 2, b ] ] - # aunque si no hay un : en el autocompletado, el array queda - # [ [ 1, 1 ], [ 2, 2 ] ] - values = _value.empty? ? [] : _value.last.zip(_value.first) - - # En última instancia, traer el valor por defecto y ahorrarnos - # volver a procesar - @values = values - end - end -end