mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-16 19:46:22 +00:00
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13498
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
commit
341929a7bf
173 changed files with 1353 additions and 501 deletions
11
.editorconfig
Normal file
11
.editorconfig
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
public/assets/** filter=lfs diff=lfs merge=lfs -text
|
||||||
|
public/packs/** filter=lfs diff=lfs merge=lfs -text
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -34,12 +34,7 @@
|
||||||
/config/master.key
|
/config/master.key
|
||||||
/config/credentials.yml.enc
|
/config/credentials.yml.enc
|
||||||
|
|
||||||
/public/packs
|
|
||||||
/public/packs-test
|
/public/packs-test
|
||||||
/public/assets
|
|
||||||
/public/assets-production
|
|
||||||
/public/packs
|
|
||||||
/public/packs-production
|
|
||||||
/node_modules
|
/node_modules
|
||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
@ -49,8 +44,6 @@ yarn-debug.log*
|
||||||
*.key
|
*.key
|
||||||
*.crt
|
*.crt
|
||||||
|
|
||||||
/public/packs
|
|
||||||
/public/packs-test
|
|
||||||
/node_modules
|
/node_modules
|
||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
|
|
@ -20,6 +20,7 @@ pipeline:
|
||||||
branch:
|
branch:
|
||||||
- "rails"
|
- "rails"
|
||||||
- "panel.sutty.nl"
|
- "panel.sutty.nl"
|
||||||
|
- "17.3.alpine.panel.sutty.nl"
|
||||||
event: "push"
|
event: "push"
|
||||||
path:
|
path:
|
||||||
include:
|
include:
|
||||||
|
@ -27,7 +28,7 @@ pipeline:
|
||||||
- ".dockerignore"
|
- ".dockerignore"
|
||||||
- ".woodpecker.yml"
|
- ".woodpecker.yml"
|
||||||
assets:
|
assets:
|
||||||
image: "gitea.nulo.in/sutty/panel:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}"
|
image: "gitea.nulo.in/sutty/panel:3.14.10-2.7.8"
|
||||||
commands:
|
commands:
|
||||||
- "apk add python2 dotenv openssh-client brotli"
|
- "apk add python2 dotenv openssh-client brotli"
|
||||||
- "install -d -m 700 ~/.ssh/"
|
- "install -d -m 700 ~/.ssh/"
|
||||||
|
@ -51,6 +52,9 @@ pipeline:
|
||||||
- "git add public && git commit -m \"ci: assets [skip ci]\""
|
- "git add public && git commit -m \"ci: assets [skip ci]\""
|
||||||
- "git pull upstream ${CI_COMMIT_BRANCH}"
|
- "git pull upstream ${CI_COMMIT_BRANCH}"
|
||||||
- "git push upstream ${CI_COMMIT_BRANCH}"
|
- "git push upstream ${CI_COMMIT_BRANCH}"
|
||||||
|
environment:
|
||||||
|
- "RUBY_VERSION=${RUBY_VERSION}"
|
||||||
|
- "GEMS_SOURCE=https://14.3.alpine.gems.sutty.nl"
|
||||||
secrets:
|
secrets:
|
||||||
- "SSH_KEY"
|
- "SSH_KEY"
|
||||||
- "KNOWN_HOSTS"
|
- "KNOWN_HOSTS"
|
||||||
|
@ -65,8 +69,15 @@ pipeline:
|
||||||
- "app/javascript/**/*"
|
- "app/javascript/**/*"
|
||||||
- "package.json"
|
- "package.json"
|
||||||
- "yarn.lock"
|
- "yarn.lock"
|
||||||
|
matrix:
|
||||||
|
ALPINE_VERSION: "3.14.10"
|
||||||
|
RUBY_VERSION: "2.7"
|
||||||
|
RUBY_PATCH: "8"
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- ALPINE_VERSION: "3.17.3"
|
||||||
|
RUBY_VERSION: "3.1"
|
||||||
|
RUBY_PATCH: "4"
|
||||||
- ALPINE_VERSION: "3.14.10"
|
- ALPINE_VERSION: "3.14.10"
|
||||||
RUBY_VERSION: "2.7"
|
RUBY_VERSION: "2.7"
|
||||||
RUBY_PATCH: "8"
|
RUBY_PATCH: "8"
|
||||||
|
|
30
Gemfile
30
Gemfile
|
@ -1,14 +1,13 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
puts 'Usa haini.sh para generar un entorno de trabajo reproducible'
|
source ENV.fetch('GEMS_SOURCE', 'https://17.3.alpine.gems.sutty.nl')
|
||||||
source 'https://gems.sutty.nl'
|
|
||||||
|
|
||||||
ruby '~> 2.7'
|
ruby "~> #{ENV.fetch('RUBY_VERSION', '3.1')}"
|
||||||
|
|
||||||
gem 'dotenv-rails', require: 'dotenv/rails-now'
|
gem 'dotenv-rails', require: 'dotenv/rails-now'
|
||||||
|
|
||||||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||||
gem 'rails', '~> 6'
|
gem 'rails', '~> 6.1.0'
|
||||||
# Use Puma as the app server
|
# Use Puma as the app server
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
|
|
||||||
|
@ -33,13 +32,14 @@ gem 'turbolinks', '~> 5'
|
||||||
gem 'jbuilder', '~> 2.5'
|
gem 'jbuilder', '~> 2.5'
|
||||||
# Use ActiveModel has_secure_password
|
# Use ActiveModel has_secure_password
|
||||||
gem 'bcrypt', '~> 3.1.7'
|
gem 'bcrypt', '~> 3.1.7'
|
||||||
|
gem 'safely_block', '~> 0.3.0'
|
||||||
gem 'blazer'
|
gem 'blazer'
|
||||||
gem 'chartkick'
|
gem 'chartkick'
|
||||||
gem 'commonmarker'
|
gem 'commonmarker'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise-i18n'
|
gem 'devise-i18n'
|
||||||
gem 'devise_invitable'
|
gem 'devise_invitable'
|
||||||
gem 'distributed-press-api-client', '~> 0.2.3'
|
gem 'distributed-press-api-client', '~> 0.3.0rc0'
|
||||||
gem 'njalla-api-client', '~> 0.2.0'
|
gem 'njalla-api-client', '~> 0.2.0'
|
||||||
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
|
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
|
||||||
gem 'exception_notification'
|
gem 'exception_notification'
|
||||||
|
@ -51,10 +51,10 @@ gem 'image_processing'
|
||||||
gem 'icalendar'
|
gem 'icalendar'
|
||||||
gem 'inline_svg'
|
gem 'inline_svg'
|
||||||
gem 'httparty'
|
gem 'httparty'
|
||||||
gem 'safe_yaml'
|
gem 'safe_yaml', require: false
|
||||||
gem 'jekyll', '~> 4.2'
|
gem 'jekyll', '~> 4.2.0'
|
||||||
gem 'jekyll-data'
|
gem 'jekyll-data'
|
||||||
gem 'jekyll-commonmark'
|
gem 'jekyll-commonmark', '~> 1.4.0'
|
||||||
gem 'jekyll-images'
|
gem 'jekyll-images'
|
||||||
gem 'jekyll-include-cache'
|
gem 'jekyll-include-cache'
|
||||||
gem 'sutty-liquid', '>= 0.7.3'
|
gem 'sutty-liquid', '>= 0.7.3'
|
||||||
|
@ -65,11 +65,12 @@ gem 'mobility'
|
||||||
gem 'pundit'
|
gem 'pundit'
|
||||||
gem 'rails-i18n'
|
gem 'rails-i18n'
|
||||||
gem 'rails_warden'
|
gem 'rails_warden'
|
||||||
gem 'redis', require: %w[redis redis/connection/hiredis]
|
gem 'redis', '~> 4.0', require: %w[redis redis/connection/hiredis]
|
||||||
gem 'redis-rails'
|
gem 'redis-rails'
|
||||||
gem 'rollups', git: 'https://github.com/fauno/rollup.git', branch: 'update'
|
gem 'rollups', git: 'https://github.com/fauno/rollup.git', branch: 'update'
|
||||||
gem 'rubyzip'
|
gem 'rubyzip'
|
||||||
gem 'rugged'
|
gem 'rugged', '1.5.0.1'
|
||||||
|
gem 'git_clone_url'
|
||||||
gem 'concurrent-ruby-ext'
|
gem 'concurrent-ruby-ext'
|
||||||
gem 'que'
|
gem 'que'
|
||||||
gem 'symbol-fstring', require: 'fstring/all'
|
gem 'symbol-fstring', require: 'fstring/all'
|
||||||
|
@ -78,6 +79,7 @@ gem 'validates_hostname'
|
||||||
gem 'webpacker'
|
gem 'webpacker'
|
||||||
gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git'
|
gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git'
|
||||||
gem 'kaminari'
|
gem 'kaminari'
|
||||||
|
gem 'device_detector'
|
||||||
|
|
||||||
# database
|
# database
|
||||||
gem 'hairtrigger'
|
gem 'hairtrigger'
|
||||||
|
@ -111,7 +113,7 @@ group :development, :test do
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
# Adds support for Capybara system testing and selenium driver
|
# Adds support for Capybara system testing and selenium driver
|
||||||
gem 'capybara', '~> 2.13'
|
gem 'capybara', '~> 2.13'
|
||||||
gem 'selenium-webdriver'
|
gem 'selenium-webdriver', '~> 4.8.0'
|
||||||
gem 'sqlite3'
|
gem 'sqlite3'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -119,11 +121,11 @@ group :development do
|
||||||
gem 'brakeman'
|
gem 'brakeman'
|
||||||
gem 'haml-lint', require: false
|
gem 'haml-lint', require: false
|
||||||
gem 'letter_opener'
|
gem 'letter_opener'
|
||||||
gem 'listen', '>= 3.0.5', '< 3.2'
|
gem 'listen'
|
||||||
gem 'rubocop-rails'
|
gem 'rubocop-rails'
|
||||||
gem 'spring'
|
gem 'spring'
|
||||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
gem 'spring-watcher-listen'
|
||||||
gem 'web-console', '>= 3.3.0'
|
gem 'web-console'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|
559
Gemfile.lock
559
Gemfile.lock
|
@ -25,86 +25,86 @@ GIT
|
||||||
groupdate (>= 5.2)
|
groupdate (>= 5.2)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://gems.sutty.nl/
|
remote: https://17.3.alpine.gems.sutty.nl/
|
||||||
specs:
|
specs:
|
||||||
actioncable (6.1.4.1)
|
actioncable (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.1.4.1)
|
actionmailbox (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
activejob (= 6.1.4.1)
|
activejob (= 6.1.7.3)
|
||||||
activerecord (= 6.1.4.1)
|
activerecord (= 6.1.7.3)
|
||||||
activestorage (= 6.1.4.1)
|
activestorage (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.1.4.1)
|
actionmailer (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
actionview (= 6.1.4.1)
|
actionview (= 6.1.7.3)
|
||||||
activejob (= 6.1.4.1)
|
activejob (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.1.4.1)
|
actionpack (6.1.7.3)
|
||||||
actionview (= 6.1.4.1)
|
actionview (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
rack (~> 2.0, >= 2.0.9)
|
rack (~> 2.0, >= 2.0.9)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.1.4.1)
|
actiontext (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
activerecord (= 6.1.4.1)
|
activerecord (= 6.1.7.3)
|
||||||
activestorage (= 6.1.4.1)
|
activestorage (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.1.4.1)
|
actionview (6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
activejob (6.1.4.1)
|
activejob (6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.1.4.1)
|
activemodel (6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
activerecord (6.1.4.1)
|
activerecord (6.1.7.3)
|
||||||
activemodel (= 6.1.4.1)
|
activemodel (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
activestorage (6.1.4.1)
|
activestorage (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
activejob (= 6.1.4.1)
|
activejob (= 6.1.7.3)
|
||||||
activerecord (= 6.1.4.1)
|
activerecord (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
marcel (~> 1.0.0)
|
marcel (~> 1.0)
|
||||||
mini_mime (>= 1.1.0)
|
mini_mime (>= 1.1.0)
|
||||||
activesupport (6.1.4.1)
|
activesupport (6.1.7.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
zeitwerk (~> 2.3)
|
zeitwerk (~> 2.3)
|
||||||
addressable (2.8.0)
|
addressable (2.8.4)
|
||||||
public_suffix (>= 2.0.2, < 5.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
autoprefixer-rails (10.3.3.0)
|
autoprefixer-rails (10.4.13.0)
|
||||||
execjs (~> 2)
|
execjs (~> 2)
|
||||||
bcrypt (3.1.16-x86_64-linux-musl)
|
bcrypt (3.1.19-x86_64-linux-musl)
|
||||||
bcrypt_pbkdf (1.1.0-x86_64-linux-musl)
|
bcrypt_pbkdf (1.1.0-x86_64-linux-musl)
|
||||||
benchmark-ips (2.9.2)
|
benchmark-ips (2.12.0)
|
||||||
bindex (0.8.1-x86_64-linux-musl)
|
bindex (0.8.1-x86_64-linux-musl)
|
||||||
blazer (2.4.7)
|
blazer (2.6.5)
|
||||||
activerecord (>= 5)
|
activerecord (>= 5)
|
||||||
chartkick (>= 3.2)
|
chartkick (>= 3.2)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
safely_block (>= 0.1.1)
|
safely_block (>= 0.1.1)
|
||||||
bootstrap (4.6.0)
|
bootstrap (4.6.2)
|
||||||
autoprefixer-rails (>= 9.1.0)
|
autoprefixer-rails (>= 9.1.0)
|
||||||
popper_js (>= 1.14.3, < 2)
|
popper_js (>= 1.16.1, < 2)
|
||||||
sassc-rails (>= 2.0.0)
|
sassc-rails (>= 2.0.0)
|
||||||
brakeman (5.1.2)
|
brakeman (5.4.1)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
capybara (2.18.0)
|
capybara (2.18.0)
|
||||||
addressable
|
addressable
|
||||||
|
@ -113,22 +113,24 @@ GEM
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
xpath (>= 2.0, < 4.0)
|
xpath (>= 2.0, < 4.0)
|
||||||
chartkick (4.1.2)
|
chartkick (5.0.2)
|
||||||
childprocess (4.1.0)
|
|
||||||
climate_control (1.2.0)
|
climate_control (1.2.0)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
colorator (1.1.0)
|
colorator (1.1.0)
|
||||||
commonmarker (0.21.2-x86_64-linux-musl)
|
commonmarker (0.23.10-x86_64-linux-musl)
|
||||||
ruby-enum (~> 0.5)
|
concurrent-ruby (1.2.2)
|
||||||
|
concurrent-ruby-ext (1.2.2-x86_64-linux-musl)
|
||||||
|
concurrent-ruby (= 1.2.2)
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
database_cleaner (2.0.1)
|
database_cleaner (2.0.2)
|
||||||
database_cleaner-active_record (~> 2.0.0)
|
database_cleaner-active_record (>= 2, < 3)
|
||||||
database_cleaner-active_record (2.0.1)
|
database_cleaner-active_record (2.1.0)
|
||||||
activerecord (>= 5.a)
|
activerecord (>= 5.a)
|
||||||
database_cleaner-core (~> 2.0.0)
|
database_cleaner-core (~> 2.0.0)
|
||||||
database_cleaner-core (2.0.1)
|
database_cleaner-core (2.0.1)
|
||||||
dead_end (3.1.0)
|
date (3.3.3-x86_64-linux-musl)
|
||||||
derailed_benchmarks (2.1.1)
|
dead_end (4.0.0)
|
||||||
|
derailed_benchmarks (2.1.2)
|
||||||
benchmark-ips (~> 2)
|
benchmark-ips (~> 2)
|
||||||
dead_end
|
dead_end
|
||||||
get_process_mem (~> 0)
|
get_process_mem (~> 0)
|
||||||
|
@ -140,29 +142,30 @@ GEM
|
||||||
rake (> 10, < 14)
|
rake (> 10, < 14)
|
||||||
ruby-statistics (>= 2.1)
|
ruby-statistics (>= 2.1)
|
||||||
thor (>= 0.19, < 2)
|
thor (>= 0.19, < 2)
|
||||||
devise (4.8.0)
|
device_detector (1.1.1)
|
||||||
|
devise (4.9.2)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 4.1.0)
|
railties (>= 4.1.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-i18n (1.10.1)
|
devise-i18n (1.11.0)
|
||||||
devise (>= 4.8.0)
|
devise (>= 4.9.0)
|
||||||
devise_invitable (2.0.5)
|
devise_invitable (2.0.8)
|
||||||
actionmailer (>= 5.0)
|
actionmailer (>= 5.0)
|
||||||
devise (>= 4.6)
|
devise (>= 4.6)
|
||||||
distributed-press-api-client (0.2.2)
|
distributed-press-api-client (0.3.0rc0)
|
||||||
addressable (~> 2.3, >= 2.3.0)
|
addressable (~> 2.3, >= 2.3.0)
|
||||||
climate_control
|
climate_control
|
||||||
dry-schema
|
dry-schema
|
||||||
httparty (~> 0.18)
|
httparty (~> 0.18)
|
||||||
json (~> 2.1, >= 2.1.0)
|
json (~> 2.1, >= 2.1.0)
|
||||||
jwt (~> 2.6.0)
|
jwt (~> 2.6.0)
|
||||||
dotenv (2.7.6)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.7.6)
|
dotenv-rails (2.8.1)
|
||||||
dotenv (= 2.7.6)
|
dotenv (= 2.8.1)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
down (5.2.4)
|
down (5.4.1)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
dry-configurable (1.0.1)
|
dry-configurable (1.0.1)
|
||||||
dry-core (~> 1.0, < 2)
|
dry-core (~> 1.0, < 2)
|
||||||
|
@ -176,65 +179,68 @@ GEM
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
dry-core (~> 1.0, < 2)
|
dry-core (~> 1.0, < 2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
dry-schema (1.13.0)
|
dry-schema (1.13.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
dry-configurable (~> 1.0, >= 1.0.1)
|
dry-configurable (~> 1.0, >= 1.0.1)
|
||||||
dry-core (~> 1.0, < 2)
|
dry-core (~> 1.0, < 2)
|
||||||
dry-initializer (~> 3.0)
|
dry-initializer (~> 3.0)
|
||||||
dry-logic (>= 1.5, < 2)
|
dry-logic (>= 1.4, < 2)
|
||||||
dry-types (>= 1.7, < 2)
|
dry-types (>= 1.7, < 2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
dry-types (1.7.0)
|
dry-types (1.7.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
dry-core (~> 1.0, < 2)
|
dry-core (~> 1.0)
|
||||||
dry-inflector (~> 1.0, < 2)
|
dry-inflector (~> 1.0)
|
||||||
dry-logic (>= 1.4, < 2)
|
dry-logic (~> 1.4)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
ed25519 (1.2.4-x86_64-linux-musl)
|
ed25519 (1.3.0-x86_64-linux-musl)
|
||||||
em-websocket (0.5.3)
|
em-websocket (0.5.3)
|
||||||
eventmachine (>= 0.12.9)
|
eventmachine (>= 0.12.9)
|
||||||
http_parser.rb (~> 0)
|
http_parser.rb (~> 0)
|
||||||
errbase (0.2.1)
|
errbase (0.2.2)
|
||||||
erubi (1.10.0)
|
erubi (1.12.0)
|
||||||
eventmachine (1.2.7-x86_64-linux-musl)
|
eventmachine (1.2.7-x86_64-linux-musl)
|
||||||
exception_notification (4.4.3)
|
exception_notification (4.5.0)
|
||||||
actionmailer (>= 4.0, < 7)
|
actionmailer (>= 5.2, < 8)
|
||||||
activesupport (>= 4.0, < 7)
|
activesupport (>= 5.2, < 8)
|
||||||
execjs (2.8.1)
|
execjs (2.8.1)
|
||||||
factory_bot (6.2.0)
|
factory_bot (6.2.1)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
factory_bot_rails (6.2.0)
|
factory_bot_rails (6.2.0)
|
||||||
factory_bot (~> 6.2.0)
|
factory_bot (~> 6.2.0)
|
||||||
railties (>= 5.0.0)
|
railties (>= 5.0.0)
|
||||||
fast_blank (1.0.1-x86_64-linux-musl)
|
fast_blank (1.0.1-x86_64-linux-musl)
|
||||||
fast_jsonparser (0.5.0-x86_64-linux-musl)
|
fast_jsonparser (0.5.0-x86_64-linux-musl)
|
||||||
ffi (1.15.4-x86_64-linux-musl)
|
ffi (1.15.5-x86_64-linux-musl)
|
||||||
flamegraph (0.9.5)
|
flamegraph (0.9.5)
|
||||||
forwardable-extended (2.6.0)
|
forwardable-extended (2.6.0)
|
||||||
friendly_id (5.4.2)
|
friendly_id (5.5.0)
|
||||||
activerecord (>= 4.0.0)
|
activerecord (>= 4.0.0)
|
||||||
get_process_mem (0.2.7)
|
get_process_mem (0.2.7)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
globalid (0.6.0)
|
git_clone_url (2.0.0)
|
||||||
|
uri-ssh_git (>= 2.0)
|
||||||
|
globalid (1.1.0)
|
||||||
activesupport (>= 5.0)
|
activesupport (>= 5.0)
|
||||||
groupdate (6.1.0)
|
groupdate (6.2.1)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
hairtrigger (0.2.24)
|
hairtrigger (1.0.0)
|
||||||
activerecord (>= 5.0, < 7)
|
activerecord (>= 6.0, < 8)
|
||||||
ruby2ruby (~> 2.4)
|
ruby2ruby (~> 2.4)
|
||||||
ruby_parser (~> 3.10)
|
ruby_parser (~> 3.10)
|
||||||
haml (5.2.2)
|
haml (6.1.2-x86_64-linux-musl)
|
||||||
temple (>= 0.8.0)
|
temple (>= 0.8.2)
|
||||||
|
thor
|
||||||
tilt
|
tilt
|
||||||
haml-lint (0.999.999)
|
haml-lint (0.999.999)
|
||||||
haml_lint
|
haml_lint
|
||||||
haml_lint (0.37.1)
|
haml_lint (0.45.0)
|
||||||
haml (>= 4.0, < 5.3)
|
haml (>= 4.0, < 6.2)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
rainbow
|
rainbow
|
||||||
rubocop (>= 0.50.0)
|
rubocop (>= 0.50.0)
|
||||||
sysexits (~> 1.1)
|
sysexits (~> 1.1)
|
||||||
hamlit (2.15.1-x86_64-linux-musl)
|
hamlit (3.0.3-x86_64-linux-musl)
|
||||||
temple (>= 0.8.2)
|
temple (>= 0.8.2)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
|
@ -250,20 +256,21 @@ GEM
|
||||||
httparty (0.21.0)
|
httparty (0.21.0)
|
||||||
mini_mime (>= 1.0.0)
|
mini_mime (>= 1.0.0)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
i18n (1.8.11)
|
i18n (1.14.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
icalendar (2.7.1)
|
icalendar (2.8.0)
|
||||||
ice_cube (~> 0.16)
|
ice_cube (~> 0.16)
|
||||||
ice_cube (0.16.4)
|
ice_cube (0.16.4)
|
||||||
image_processing (1.12.1)
|
image_processing (1.12.2)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 5)
|
||||||
ruby-vips (>= 2.0.17, < 3)
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
inline_svg (1.7.2)
|
inline_svg (1.9.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
jbuilder (2.11.3)
|
jbuilder (2.11.5)
|
||||||
|
actionview (>= 5.0.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
jekyll (4.2.1)
|
jekyll (4.2.2)
|
||||||
addressable (~> 2.4)
|
addressable (~> 2.4)
|
||||||
colorator (~> 1.0)
|
colorator (~> 1.0)
|
||||||
em-websocket (~> 0.5)
|
em-websocket (~> 0.5)
|
||||||
|
@ -278,243 +285,219 @@ GEM
|
||||||
rouge (~> 3.0)
|
rouge (~> 3.0)
|
||||||
safe_yaml (~> 1.0)
|
safe_yaml (~> 1.0)
|
||||||
terminal-table (~> 2.0)
|
terminal-table (~> 2.0)
|
||||||
jekyll-commonmark (1.3.2)
|
jekyll-commonmark (1.4.0)
|
||||||
commonmarker (~> 0.14, < 0.22)
|
commonmarker (~> 0.22)
|
||||||
jekyll (>= 3.7, < 5.0)
|
|
||||||
jekyll-data (1.1.2)
|
jekyll-data (1.1.2)
|
||||||
jekyll (>= 3.3, < 5.0.0)
|
jekyll (>= 3.3, < 5.0.0)
|
||||||
jekyll-dotenv (0.2.0)
|
jekyll-images (0.4.1)
|
||||||
dotenv (~> 2.7)
|
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-feed (0.15.1)
|
|
||||||
jekyll (>= 3.7, < 5.0)
|
|
||||||
jekyll-hardlinks (0.1.2)
|
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-ignore-layouts (0.1.2)
|
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-images (0.3.2)
|
|
||||||
jekyll (~> 4)
|
jekyll (~> 4)
|
||||||
ruby-filemagic (~> 0.7)
|
ruby-filemagic (~> 0.7)
|
||||||
ruby-vips (~> 2)
|
ruby-vips (~> 2)
|
||||||
jekyll-include-cache (0.2.1)
|
jekyll-include-cache (0.2.1)
|
||||||
jekyll (>= 3.7, < 5.0)
|
jekyll (>= 3.7, < 5.0)
|
||||||
jekyll-linked-posts (0.4.2)
|
jekyll-sass-converter (2.2.0)
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-locales (0.1.13)
|
|
||||||
jekyll-lunr (0.3.0)
|
|
||||||
loofah (~> 2.4)
|
|
||||||
jekyll-order (0.1.4)
|
|
||||||
jekyll-relative-urls (0.0.6)
|
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-sass-converter (2.1.0)
|
|
||||||
sassc (> 2.0.1, < 3.0)
|
sassc (> 2.0.1, < 3.0)
|
||||||
jekyll-seo-tag (2.7.1)
|
|
||||||
jekyll (>= 3.8, < 5.0)
|
|
||||||
jekyll-spree-client (0.1.19)
|
|
||||||
fast_blank (~> 1)
|
|
||||||
spree-api-client (>= 0.2.4)
|
|
||||||
jekyll-turbolinks (0.0.5)
|
|
||||||
jekyll (~> 4)
|
|
||||||
turbolinks-source (~> 5)
|
|
||||||
jekyll-unique-urls (0.1.1)
|
|
||||||
jekyll (~> 4)
|
|
||||||
jekyll-watch (2.2.1)
|
jekyll-watch (2.2.1)
|
||||||
listen (~> 3.0)
|
listen (~> 3.0)
|
||||||
jekyll-write-and-commit-changes (0.2.1)
|
json (2.6.3-x86_64-linux-musl)
|
||||||
jekyll (~> 4)
|
|
||||||
rugged (~> 1)
|
|
||||||
jwt (2.6.0)
|
jwt (2.6.0)
|
||||||
kaminari (1.2.1)
|
kaminari (1.2.2)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
kaminari-actionview (= 1.2.1)
|
kaminari-actionview (= 1.2.2)
|
||||||
kaminari-activerecord (= 1.2.1)
|
kaminari-activerecord (= 1.2.2)
|
||||||
kaminari-core (= 1.2.1)
|
kaminari-core (= 1.2.2)
|
||||||
kaminari-actionview (1.2.1)
|
kaminari-actionview (1.2.2)
|
||||||
actionview
|
actionview
|
||||||
kaminari-core (= 1.2.1)
|
kaminari-core (= 1.2.2)
|
||||||
kaminari-activerecord (1.2.1)
|
kaminari-activerecord (1.2.2)
|
||||||
activerecord
|
activerecord
|
||||||
kaminari-core (= 1.2.1)
|
kaminari-core (= 1.2.2)
|
||||||
kaminari-core (1.2.1)
|
kaminari-core (1.2.2)
|
||||||
kramdown (2.3.1)
|
kramdown (2.4.0)
|
||||||
rexml
|
rexml
|
||||||
kramdown-parser-gfm (1.1.0)
|
kramdown-parser-gfm (1.1.0)
|
||||||
kramdown (~> 2.0)
|
kramdown (~> 2.0)
|
||||||
launchy (2.5.0)
|
launchy (2.5.2)
|
||||||
addressable (~> 2.7)
|
addressable (~> 2.8)
|
||||||
letter_opener (1.7.0)
|
letter_opener (1.8.1)
|
||||||
launchy (~> 2.2)
|
launchy (>= 2.2, < 3)
|
||||||
liquid (4.0.3)
|
liquid (4.0.4)
|
||||||
listen (3.1.5)
|
listen (3.8.0)
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
ruby_dep (~> 1.2)
|
|
||||||
loaf (0.10.0)
|
loaf (0.10.0)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
lockbox (0.6.6)
|
lockbox (1.2.0)
|
||||||
lograge (0.11.2)
|
lograge (0.12.0)
|
||||||
actionpack (>= 4)
|
actionpack (>= 4)
|
||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
railties (>= 4)
|
railties (>= 4)
|
||||||
request_store (~> 1.0)
|
request_store (~> 1.0)
|
||||||
loofah (2.12.0)
|
loofah (2.21.3)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.12.0)
|
||||||
mail (2.7.1)
|
mail (2.8.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
|
net-imap
|
||||||
|
net-pop
|
||||||
|
net-smtp
|
||||||
marcel (1.0.2)
|
marcel (1.0.2)
|
||||||
memory_profiler (1.0.0)
|
memory_profiler (1.0.1)
|
||||||
mercenary (0.4.0)
|
mercenary (0.4.0)
|
||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mime-types (3.4.1)
|
|
||||||
mime-types-data (~> 3.2015)
|
|
||||||
mime-types-data (3.2021.1115)
|
|
||||||
mini_histogram (0.3.1)
|
mini_histogram (0.3.1)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.12.0)
|
||||||
mini_mime (1.1.2)
|
mini_mime (1.1.2)
|
||||||
mini_portile2 (2.6.1)
|
mini_portile2 (2.8.2)
|
||||||
minitest (5.14.4)
|
minitest (5.18.0)
|
||||||
mobility (1.2.4)
|
mobility (1.2.9)
|
||||||
i18n (>= 0.6.10, < 2)
|
i18n (>= 0.6.10, < 2)
|
||||||
request_store (~> 1.0)
|
request_store (~> 1.0)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
net-ssh (6.1.0)
|
net-imap (0.3.4)
|
||||||
netaddr (2.0.5)
|
date
|
||||||
nio4r (2.5.8-x86_64-linux-musl)
|
net-protocol
|
||||||
nokogiri (1.12.5-x86_64-linux-musl)
|
net-pop (0.1.2)
|
||||||
mini_portile2 (~> 2.6.1)
|
net-protocol
|
||||||
racc (~> 1.4)
|
net-protocol (0.2.1)
|
||||||
|
timeout
|
||||||
|
net-smtp (0.3.3)
|
||||||
|
net-protocol
|
||||||
|
net-ssh (7.1.0)
|
||||||
|
netaddr (2.0.6)
|
||||||
|
nio4r (2.5.9-x86_64-linux-musl)
|
||||||
njalla-api-client (0.2.0)
|
njalla-api-client (0.2.0)
|
||||||
dry-schema
|
dry-schema
|
||||||
httparty (~> 0.18)
|
httparty (~> 0.18)
|
||||||
|
nokogiri (1.15.4-x86_64-linux-musl)
|
||||||
|
mini_portile2 (~> 2.8.2)
|
||||||
|
racc (~> 1.4)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
pairing_heap (3.0.0)
|
pairing_heap (3.0.1)
|
||||||
parallel (1.21.0)
|
parallel (1.23.0)
|
||||||
parser (3.0.2.0)
|
parser (3.2.2.1)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
pathutil (0.16.2)
|
pathutil (0.16.2)
|
||||||
forwardable-extended (~> 2.6)
|
forwardable-extended (~> 2.6)
|
||||||
pg (1.2.3-x86_64-linux-musl)
|
pg (1.5.3-x86_64-linux-musl)
|
||||||
pg_search (2.3.5)
|
pg_search (2.3.6)
|
||||||
activerecord (>= 5.2)
|
activerecord (>= 5.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
popper_js (1.16.0)
|
popper_js (1.16.1)
|
||||||
prometheus_exporter (1.0.0)
|
prometheus_exporter (2.0.8)
|
||||||
webrick
|
webrick
|
||||||
pry (0.14.1)
|
pry (0.14.2)
|
||||||
coderay (~> 1.1)
|
coderay (~> 1.1)
|
||||||
method_source (~> 1.0)
|
method_source (~> 1.0)
|
||||||
public_suffix (4.0.6)
|
public_suffix (5.0.3)
|
||||||
puma (5.5.2-x86_64-linux-musl)
|
puma (6.3.1-x86_64-linux-musl)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.1.1)
|
pundit (2.3.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
racc (1.6.0-x86_64-linux-musl)
|
que (2.2.1)
|
||||||
que (2.2.0)
|
racc (1.7.1-x86_64-linux-musl)
|
||||||
rack (2.2.3)
|
rack (2.2.7)
|
||||||
rack-cors (1.1.1)
|
rack-cors (2.0.1)
|
||||||
rack (>= 2.0.0)
|
rack (>= 2.0.0)
|
||||||
rack-mini-profiler (2.3.3)
|
rack-mini-profiler (3.1.0)
|
||||||
rack (>= 1.2.0)
|
rack (>= 1.2.0)
|
||||||
rack-proxy (0.7.0)
|
rack-proxy (0.7.6)
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.3)
|
||||||
rails (6.1.4.1)
|
rails (6.1.7.3)
|
||||||
actioncable (= 6.1.4.1)
|
actioncable (= 6.1.7.3)
|
||||||
actionmailbox (= 6.1.4.1)
|
actionmailbox (= 6.1.7.3)
|
||||||
actionmailer (= 6.1.4.1)
|
actionmailer (= 6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
actiontext (= 6.1.4.1)
|
actiontext (= 6.1.7.3)
|
||||||
actionview (= 6.1.4.1)
|
actionview (= 6.1.7.3)
|
||||||
activejob (= 6.1.4.1)
|
activejob (= 6.1.7.3)
|
||||||
activemodel (= 6.1.4.1)
|
activemodel (= 6.1.7.3)
|
||||||
activerecord (= 6.1.4.1)
|
activerecord (= 6.1.7.3)
|
||||||
activestorage (= 6.1.4.1)
|
activestorage (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 6.1.4.1)
|
railties (= 6.1.7.3)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.4.2)
|
rails-html-sanitizer (1.5.0)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.19, >= 2.19.1)
|
||||||
rails-i18n (6.0.0)
|
rails-i18n (7.0.7)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 6.0.0, < 7)
|
railties (>= 6.0.0, < 8)
|
||||||
rails_warden (0.6.0)
|
rails_warden (0.6.0)
|
||||||
warden (>= 1.2.0)
|
warden (>= 1.2.0)
|
||||||
railties (6.1.4.1)
|
railties (6.1.7.3)
|
||||||
actionpack (= 6.1.4.1)
|
actionpack (= 6.1.7.3)
|
||||||
activesupport (= 6.1.4.1)
|
activesupport (= 6.1.7.3)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.13)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0)
|
thor (~> 1.0)
|
||||||
rainbow (3.0.0)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
rb-fsevent (0.11.0)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
redis (4.5.1)
|
redis (4.8.1)
|
||||||
redis-actionpack (5.2.0)
|
redis-actionpack (5.3.0)
|
||||||
actionpack (>= 5, < 7)
|
actionpack (>= 5, < 8)
|
||||||
redis-rack (>= 2.1.0, < 3)
|
redis-rack (>= 2.1.0, < 3)
|
||||||
redis-store (>= 1.1.0, < 2)
|
redis-store (>= 1.1.0, < 2)
|
||||||
redis-activesupport (5.2.1)
|
redis-activesupport (5.3.0)
|
||||||
activesupport (>= 3, < 7)
|
activesupport (>= 3, < 8)
|
||||||
redis-store (>= 1.3, < 2)
|
redis-store (>= 1.3, < 2)
|
||||||
redis-rack (2.1.3)
|
redis-rack (2.1.4)
|
||||||
rack (>= 2.0.8, < 3)
|
rack (>= 2.0.8, < 3)
|
||||||
redis-store (>= 1.2, < 2)
|
redis-store (>= 1.2, < 2)
|
||||||
redis-rails (5.0.2)
|
redis-rails (5.0.2)
|
||||||
redis-actionpack (>= 5.0, < 6)
|
redis-actionpack (>= 5.0, < 6)
|
||||||
redis-activesupport (>= 5.0, < 6)
|
redis-activesupport (>= 5.0, < 6)
|
||||||
redis-store (>= 1.2, < 2)
|
redis-store (>= 1.2, < 2)
|
||||||
redis-store (1.9.0)
|
redis-store (1.9.2)
|
||||||
redis (>= 4, < 5)
|
redis (>= 4, < 6)
|
||||||
regexp_parser (2.1.1)
|
regexp_parser (2.8.0)
|
||||||
request_store (1.5.0)
|
request_store (1.5.1)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
responders (3.0.1)
|
responders (3.1.0)
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.2)
|
||||||
railties (>= 5.0)
|
railties (>= 5.2)
|
||||||
rexml (3.2.5)
|
rexml (3.2.5)
|
||||||
rgl (0.6.2)
|
rgl (0.6.3)
|
||||||
pairing_heap (>= 0.3.0)
|
pairing_heap (>= 0.3.0)
|
||||||
rexml (~> 3.2, >= 3.2.4)
|
rexml (~> 3.2, >= 3.2.4)
|
||||||
stream (~> 0.5.3)
|
stream (~> 0.5.3)
|
||||||
rouge (3.26.1)
|
rouge (3.30.0)
|
||||||
rubocop (1.23.0)
|
rubocop (1.42.0)
|
||||||
|
json (~> 2.3)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.0.0.0)
|
parser (>= 3.1.2.1)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml
|
rexml (>= 3.2.5, < 4.0)
|
||||||
rubocop-ast (>= 1.12.0, < 2.0)
|
rubocop-ast (>= 1.24.1, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 3.0)
|
unicode-display_width (>= 1.4.0, < 3.0)
|
||||||
rubocop-ast (1.13.0)
|
rubocop-ast (1.28.1)
|
||||||
parser (>= 3.0.1.1)
|
parser (>= 3.2.1.0)
|
||||||
rubocop-rails (2.12.4)
|
rubocop-rails (2.19.1)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.7.0, < 2.0)
|
rubocop (>= 1.33.0, < 2.0)
|
||||||
ruby-enum (0.9.0)
|
ruby-filemagic (0.7.3-x86_64-linux-musl)
|
||||||
i18n
|
ruby-progressbar (1.13.0)
|
||||||
ruby-filemagic (0.7.2-x86_64-linux-musl)
|
ruby-statistics (3.0.2)
|
||||||
ruby-progressbar (1.11.0)
|
|
||||||
ruby-statistics (3.0.0)
|
|
||||||
ruby-vips (2.1.4)
|
ruby-vips (2.1.4)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
ruby2ruby (2.4.4)
|
ruby2ruby (2.5.0)
|
||||||
ruby_parser (~> 3.1)
|
ruby_parser (~> 3.1)
|
||||||
sexp_processor (~> 4.6)
|
sexp_processor (~> 4.6)
|
||||||
ruby_dep (1.5.0)
|
ruby_parser (3.20.1)
|
||||||
ruby_parser (3.18.1)
|
|
||||||
sexp_processor (~> 4.16)
|
sexp_processor (~> 4.16)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
rugged (1.2.0-x86_64-linux-musl)
|
rugged (1.5.0.1-x86_64-linux-musl)
|
||||||
safe_yaml (1.0.6)
|
safe_yaml (1.0.6)
|
||||||
safely_block (0.3.0)
|
safely_block (0.3.0)
|
||||||
errbase (>= 0.1.1)
|
errbase (>= 0.1.1)
|
||||||
|
@ -526,56 +509,55 @@ GEM
|
||||||
sprockets (> 3.0)
|
sprockets (> 3.0)
|
||||||
sprockets-rails
|
sprockets-rails
|
||||||
tilt
|
tilt
|
||||||
selenium-webdriver (4.1.0)
|
selenium-webdriver (4.8.6)
|
||||||
childprocess (>= 0.5, < 5.0)
|
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (>= 1.2.2)
|
rubyzip (>= 1.2.2, < 3.0)
|
||||||
|
websocket (~> 1.0)
|
||||||
semantic_range (3.0.0)
|
semantic_range (3.0.0)
|
||||||
sexp_processor (4.16.0)
|
sexp_processor (4.17.0)
|
||||||
simpleidn (0.2.1)
|
simpleidn (0.2.1)
|
||||||
unf (~> 0.1.4)
|
unf (~> 0.1.4)
|
||||||
sourcemap (0.1.1)
|
sourcemap (0.1.1)
|
||||||
spree-api-client (0.2.4)
|
spring (4.1.1)
|
||||||
fast_blank (~> 1)
|
spring-watcher-listen (2.1.0)
|
||||||
httparty (~> 0.18.0)
|
|
||||||
spring (2.1.1)
|
|
||||||
spring-watcher-listen (2.0.1)
|
|
||||||
listen (>= 2.7, < 4.0)
|
listen (>= 2.7, < 4.0)
|
||||||
spring (>= 1.2, < 3.0)
|
spring (>= 4)
|
||||||
sprockets (4.0.2)
|
sprockets (4.2.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
rack (> 1, < 3)
|
rack (>= 2.2.4, < 4)
|
||||||
sprockets-rails (3.4.1)
|
sprockets-rails (3.4.2)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
sqlite3 (1.4.2-x86_64-linux-musl)
|
sqlite3 (1.6.3-x86_64-linux-musl)
|
||||||
stackprof (0.2.17-x86_64-linux-musl)
|
mini_portile2 (~> 2.8.0)
|
||||||
sutty-archives (2.5.4)
|
stackprof (0.2.25-x86_64-linux-musl)
|
||||||
jekyll (>= 3.6, < 5.0)
|
stream (0.5.5)
|
||||||
sutty-liquid (0.7.4)
|
sutty-liquid (0.11.11)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
jekyll (~> 4)
|
jekyll (~> 4)
|
||||||
symbol-fstring (1.0.2-x86_64-linux-musl)
|
symbol-fstring (1.0.2-x86_64-linux-musl)
|
||||||
sysexits (1.2.0)
|
sysexits (1.2.0)
|
||||||
temple (0.8.2)
|
temple (0.10.1)
|
||||||
terminal-table (2.0.0)
|
terminal-table (2.0.0)
|
||||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||||
thor (1.1.0)
|
thor (1.2.2)
|
||||||
tilt (2.0.10)
|
tilt (2.1.0)
|
||||||
timecop (0.9.4)
|
timecop (0.9.6)
|
||||||
|
timeout (0.3.2)
|
||||||
turbolinks (5.2.1)
|
turbolinks (5.2.1)
|
||||||
turbolinks-source (~> 5.2)
|
turbolinks-source (~> 5.2)
|
||||||
turbolinks-source (5.2.0)
|
turbolinks-source (5.2.0)
|
||||||
tzinfo (2.0.4)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
uglifier (4.2.0)
|
uglifier (4.2.0)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.8-x86_64-linux-musl)
|
unf_ext (0.0.8.2-x86_64-linux-musl)
|
||||||
unicode-display_width (1.8.0)
|
unicode-display_width (1.8.0)
|
||||||
validates_hostname (1.0.11)
|
uri-ssh_git (2.0.0)
|
||||||
|
validates_hostname (1.0.13)
|
||||||
activerecord (>= 3.0)
|
activerecord (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
warden (1.2.9)
|
warden (1.2.9)
|
||||||
|
@ -585,21 +567,21 @@ GEM
|
||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
webpacker (5.4.3)
|
webpacker (5.4.4)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
rack-proxy (>= 0.6.1)
|
rack-proxy (>= 0.6.1)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
semantic_range (>= 2.3.0)
|
semantic_range (>= 2.3.0)
|
||||||
webrick (1.7.0)
|
webrick (1.8.1)
|
||||||
websocket-driver (0.7.5-x86_64-linux-musl)
|
websocket (1.2.9)
|
||||||
|
websocket-driver (0.7.6-x86_64-linux-musl)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
zeitwerk (2.5.1)
|
zeitwerk (2.6.8)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
|
||||||
x86_64-linux-musl
|
x86_64-linux-musl
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
@ -614,10 +596,11 @@ DEPENDENCIES
|
||||||
concurrent-ruby-ext
|
concurrent-ruby-ext
|
||||||
database_cleaner
|
database_cleaner
|
||||||
derailed_benchmarks
|
derailed_benchmarks
|
||||||
|
device_detector
|
||||||
devise
|
devise
|
||||||
devise-i18n
|
devise-i18n
|
||||||
devise_invitable
|
devise_invitable
|
||||||
distributed-press-api-client (~> 0.2.3)
|
distributed-press-api-client (~> 0.3.0rc0)
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
down
|
down
|
||||||
ed25519
|
ed25519
|
||||||
|
@ -625,9 +608,10 @@ DEPENDENCIES
|
||||||
exception_notification
|
exception_notification
|
||||||
factory_bot_rails
|
factory_bot_rails
|
||||||
fast_blank
|
fast_blank
|
||||||
fast_jsonparser
|
fast_jsonparser (~> 0.5.0)
|
||||||
flamegraph
|
flamegraph
|
||||||
friendly_id
|
friendly_id
|
||||||
|
git_clone_url
|
||||||
hairtrigger
|
hairtrigger
|
||||||
haml-lint
|
haml-lint
|
||||||
hamlit-rails
|
hamlit-rails
|
||||||
|
@ -637,14 +621,14 @@ DEPENDENCIES
|
||||||
image_processing
|
image_processing
|
||||||
inline_svg
|
inline_svg
|
||||||
jbuilder (~> 2.5)
|
jbuilder (~> 2.5)
|
||||||
jekyll (~> 4.2)
|
jekyll (~> 4.2.0)
|
||||||
jekyll-commonmark
|
jekyll-commonmark (~> 1.4.0)
|
||||||
jekyll-data
|
jekyll-data
|
||||||
jekyll-images
|
jekyll-images
|
||||||
jekyll-include-cache
|
jekyll-include-cache
|
||||||
kaminari
|
kaminari
|
||||||
letter_opener
|
letter_opener
|
||||||
listen (>= 3.0.5, < 3.2)
|
listen
|
||||||
loaf
|
loaf
|
||||||
lockbox
|
lockbox
|
||||||
lograge
|
lograge
|
||||||
|
@ -652,7 +636,7 @@ DEPENDENCIES
|
||||||
mini_magick
|
mini_magick
|
||||||
mobility
|
mobility
|
||||||
net-ssh
|
net-ssh
|
||||||
njalla-api-client
|
njalla-api-client (~> 0.2.0)
|
||||||
nokogiri
|
nokogiri
|
||||||
pg
|
pg
|
||||||
pg_search
|
pg_search
|
||||||
|
@ -663,22 +647,23 @@ DEPENDENCIES
|
||||||
que
|
que
|
||||||
rack-cors
|
rack-cors
|
||||||
rack-mini-profiler
|
rack-mini-profiler
|
||||||
rails (~> 6)
|
rails (~> 6.1.0)
|
||||||
rails-i18n
|
rails-i18n
|
||||||
rails_warden
|
rails_warden
|
||||||
redis
|
redis (~> 4.0)
|
||||||
redis-rails
|
redis-rails
|
||||||
rgl
|
rgl
|
||||||
rollups!
|
rollups!
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
rubyzip
|
rubyzip
|
||||||
rugged
|
rugged (= 1.5.0.1)
|
||||||
safe_yaml
|
safe_yaml
|
||||||
|
safely_block (~> 0.3.0)
|
||||||
sassc-rails
|
sassc-rails
|
||||||
selenium-webdriver
|
selenium-webdriver (~> 4.8.0)
|
||||||
sourcemap
|
sourcemap
|
||||||
spring
|
spring
|
||||||
spring-watcher-listen (~> 2.0.0)
|
spring-watcher-listen
|
||||||
sqlite3
|
sqlite3
|
||||||
stackprof
|
stackprof
|
||||||
sutty-liquid (>= 0.7.3)
|
sutty-liquid (>= 0.7.3)
|
||||||
|
@ -688,12 +673,12 @@ DEPENDENCIES
|
||||||
turbolinks (~> 5)
|
turbolinks (~> 5)
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
validates_hostname
|
validates_hostname
|
||||||
web-console (>= 3.3.0)
|
web-console
|
||||||
webpacker
|
webpacker
|
||||||
yaml_db!
|
yaml_db!
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 2.7.1p83
|
ruby 3.1.4p223
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.2.2
|
2.4.17
|
||||||
|
|
16
Makefile
16
Makefile
|
@ -48,8 +48,6 @@ help: always ## Ayuda
|
||||||
@echo -e "\nArgumentos:\n"
|
@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/"
|
@grep -E "^[a-z\-]+ \?=.*##" Makefile | sed -re "s/(.*) \?=.*##(.*)/\1;\2/" | column -s ";" -t | sed -re "s/^([^ ]+) /\x1B[38;5;197m\1\x1B[0m/"
|
||||||
|
|
||||||
assets: public/packs/manifest.json.br ## Compilar los assets
|
|
||||||
|
|
||||||
test: always ## Ejecutar los tests
|
test: always ## Ejecutar los tests
|
||||||
$(MAKE) rake args="test RAILS_ENV=test $(args)"
|
$(MAKE) rake args="test RAILS_ENV=test $(args)"
|
||||||
|
|
||||||
|
@ -110,21 +108,13 @@ save: ## Subir la imagen Docker al nodo delegado
|
||||||
date +%F | xargs -I {} git tag -f $(container)-{}
|
date +%F | xargs -I {} git tag -f $(container)-{}
|
||||||
@echo -e "\a"
|
@echo -e "\a"
|
||||||
|
|
||||||
ota-js: assets ## Actualizar Javascript en el nodo delegado
|
|
||||||
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
|
ota: ## Actualizar Rails en el nodo delegado
|
||||||
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl pull ; true
|
git push
|
||||||
|
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl pull
|
||||||
|
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl lfs prune
|
||||||
ssh $(delegate) chown -R 1000:82 /srv/sutty/srv/http/panel.sutty.nl
|
ssh $(delegate) chown -R 1000:82 /srv/sutty/srv/http/panel.sutty.nl
|
||||||
ssh $(delegate) docker exec $(container) rails reload
|
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.
|
|
||||||
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
|
# Correr un test en particular por ejemplo
|
||||||
# `make test/models/usuarie_test.rb`
|
# `make test/models/usuarie_test.rb`
|
||||||
tests := $(shell find test/ -name "*_test.rb")
|
tests := $(shell find test/ -name "*_test.rb")
|
||||||
|
|
|
@ -10,7 +10,7 @@ module Api
|
||||||
# solo si la API key es verificable. Del otro lado siempre
|
# solo si la API key es verificable. Del otro lado siempre
|
||||||
# respondemos con lo mismo.
|
# respondemos con lo mismo.
|
||||||
def create
|
def create
|
||||||
if site&.airbrake_valid? airbrake_token
|
if (site&.airbrake_valid? airbrake_token) && !detected_device.bot?
|
||||||
BacktraceJob.perform_later site_id: params[:site_id],
|
BacktraceJob.perform_later site_id: params[:site_id],
|
||||||
params: airbrake_params.to_h
|
params: airbrake_params.to_h
|
||||||
end
|
end
|
||||||
|
@ -34,6 +34,11 @@ module Api
|
||||||
def airbrake_token
|
def airbrake_token
|
||||||
@airbrake_token ||= params[:key]
|
@airbrake_token ||= params[:key]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [DeviceDetector]
|
||||||
|
def detected_device
|
||||||
|
@detected_device ||= DeviceDetector.new(request.headers['User-Agent'], request.headers)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
77
app/controllers/api/v1/webhooks_controller.rb
Normal file
77
app/controllers/api/v1/webhooks_controller.rb
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
# Recibe webhooks y lanza un PullJob
|
||||||
|
class WebhooksController < BaseController
|
||||||
|
# responde con forbidden si falla la validación del token
|
||||||
|
rescue_from ActiveRecord::RecordNotFound, with: :platforms_answer
|
||||||
|
|
||||||
|
# Trae los cambios a partir de un post de Webhooks:
|
||||||
|
# (Gitlab, Github, Gitea, etc)
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def pull
|
||||||
|
message = I18n.with_locale(site.default_locale) do
|
||||||
|
I18n.t('webhooks.pull.message')
|
||||||
|
end
|
||||||
|
|
||||||
|
GitPullJob.perform_later(site, usuarie, message)
|
||||||
|
head :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# encuentra el sitio a partir de la url
|
||||||
|
def site
|
||||||
|
@site ||= Site.find_by_name!(params[:site_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# valida el token que envía la plataforma del webhook
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def token
|
||||||
|
@token ||=
|
||||||
|
begin
|
||||||
|
# Gitlab
|
||||||
|
if request.headers['X-Gitlab-Token'].present?
|
||||||
|
request.headers['X-Gitlab-Token']
|
||||||
|
# Github
|
||||||
|
elsif request.headers['X-Hub-Signature-256'].present?
|
||||||
|
token_from_signature(request.headers['X-Hub-Signature-256'], 'sha256=')
|
||||||
|
# Gitea
|
||||||
|
elsif request.headers['X-Gitea-Signature'].present?
|
||||||
|
token_from_signature(request.headers['X-Gitea-Signature'])
|
||||||
|
else
|
||||||
|
raise ActiveRecord::RecordNotFound, 'proveedor no soportado'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# valida token a partir de firma de webhook
|
||||||
|
#
|
||||||
|
# @return [String, Boolean]
|
||||||
|
def token_from_signature(signature, prepend = '')
|
||||||
|
payload = request.body.read
|
||||||
|
site.roles.where(temporal: false, rol: 'usuarie').pluck(:token).find do |token|
|
||||||
|
new_signature = prepend + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), token, payload)
|
||||||
|
ActiveSupport::SecurityUtils.secure_compare(new_signature, signature.to_s)
|
||||||
|
end.tap do |t|
|
||||||
|
raise ActiveRecord::RecordNotFound, 'token no encontrado' if t.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# encuentra le usuarie
|
||||||
|
def usuarie
|
||||||
|
@usuarie ||= site.roles.find_by!(temporal: false, rol: 'usuarie', token: token).usuarie
|
||||||
|
end
|
||||||
|
|
||||||
|
# respuesta de error a plataformas
|
||||||
|
def platforms_answer(exception)
|
||||||
|
ExceptionNotifier.notify_exception(exception, data: { headers: request.headers.to_h }
|
||||||
|
|
||||||
|
head :forbidden
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -59,7 +59,11 @@ class ApplicationController < ActionController::Base
|
||||||
#
|
#
|
||||||
# @return [String,Symbol]
|
# @return [String,Symbol]
|
||||||
def current_locale
|
def current_locale
|
||||||
session[:locale] = params[:change_locale_to] if params[:change_locale_to].present?
|
locale = params[:change_locale_to]
|
||||||
|
|
||||||
|
if locale.present? && I18n.locale_available?(locale)
|
||||||
|
session[:locale] = params[:change_locale_to]
|
||||||
|
end
|
||||||
|
|
||||||
session[:locale] || current_usuarie&.lang || I18n.locale
|
session[:locale] || current_usuarie&.lang || I18n.locale
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,12 @@ class BuildStatsController < ApplicationController
|
||||||
|
|
||||||
@table = site.deployment_list.map do |deploy|
|
@table = site.deployment_list.map do |deploy|
|
||||||
type = deploy.class.name.underscore
|
type = deploy.class.name.underscore
|
||||||
urls = deploy.respond_to?(:urls) ? deploy.urls : [deploy.url].compact
|
urls = deploy.urls.map do |url|
|
||||||
|
URI.parse(url)
|
||||||
|
rescue URI::Error
|
||||||
|
nil
|
||||||
|
end.compact
|
||||||
|
|
||||||
urls = [nil] if urls.empty?
|
urls = [nil] if urls.empty?
|
||||||
build_stat = deploy.build_stats.where(status: true).last
|
build_stat = deploy.build_stats.where(status: true).last
|
||||||
seconds = build_stat&.seconds || 0
|
seconds = build_stat&.seconds || 0
|
||||||
|
|
|
@ -5,6 +5,7 @@ class EnvController < ActionController::Base
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@site = Site.find_by_name('panel')
|
@site = Site.find_by_name('panel')
|
||||||
stale? @site
|
|
||||||
|
stale? @site if @site
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,7 @@ class PostsController < ApplicationController
|
||||||
|
|
||||||
# Todos los artículos de este sitio para el idioma actual
|
# 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)
|
||||||
|
@posts = @posts.page(filter_params.delete(:page)) if site.pagination
|
||||||
# De este tipo
|
# De este tipo
|
||||||
@posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout]
|
@posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout]
|
||||||
# Que estén dentro de la categoría
|
# Que estén dentro de la categoría
|
||||||
|
@ -154,7 +155,7 @@ class PostsController < ApplicationController
|
||||||
#
|
#
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def filter_params
|
def filter_params
|
||||||
@filter_params ||= params.permit(:q, :category, :layout).to_hash.select do |_, v|
|
@filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select do |_, v|
|
||||||
v.present?
|
v.present?
|
||||||
end.transform_keys(&:to_sym)
|
end.transform_keys(&:to_sym)
|
||||||
end
|
end
|
||||||
|
|
|
@ -57,6 +57,7 @@ class SitesController < ApplicationController
|
||||||
usuarie: current_usuarie)
|
usuarie: current_usuarie)
|
||||||
|
|
||||||
if service.update.valid?
|
if service.update.valid?
|
||||||
|
flash[:notice] = I18n.t('sites.update.post')
|
||||||
redirect_to site_posts_path(site, locale: site.default_locale)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
else
|
else
|
||||||
render 'edit'
|
render 'edit'
|
||||||
|
|
|
@ -2,11 +2,21 @@
|
||||||
|
|
||||||
import { Notifier } from '@airbrake/browser'
|
import { Notifier } from '@airbrake/browser'
|
||||||
|
|
||||||
window.airbrake = new Notifier({
|
try {
|
||||||
projectId: window.env.AIRBRAKE_SITE_ID,
|
window.airbrake = new Notifier({
|
||||||
projectKey: window.env.AIRBRAKE_API_KEY,
|
projectId: window.env.AIRBRAKE_PROJECT_ID,
|
||||||
|
projectKey: window.env.AIRBRAKE_PROJECT_KEY,
|
||||||
host: window.env.PANEL_URL
|
host: window.env.PANEL_URL
|
||||||
})
|
});
|
||||||
|
|
||||||
|
console.originalError = console.error;
|
||||||
|
console.error = (...e) => {
|
||||||
|
window.airbrake.notify(e.join(" "));
|
||||||
|
return console.originalError(...e);
|
||||||
|
};
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
import 'core-js/stable'
|
import 'core-js/stable'
|
||||||
import 'regenerator-runtime/runtime'
|
import 'regenerator-runtime/runtime'
|
||||||
|
|
|
@ -51,7 +51,11 @@ class DeployJob < ApplicationJob
|
||||||
status = d.deploy(output: @output)
|
status = d.deploy(output: @output)
|
||||||
seconds = d.build_stats.last.try(:seconds) || 0
|
seconds = d.build_stats.last.try(:seconds) || 0
|
||||||
size = d.size
|
size = d.size
|
||||||
urls = d.respond_to?(:urls) ? d.urls : [d.url].compact
|
urls = d.urls.map do |url|
|
||||||
|
URI.parse url
|
||||||
|
rescue URI::Error
|
||||||
|
nil
|
||||||
|
end.compact
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
status = false
|
status = false
|
||||||
seconds ||= 0
|
seconds ||= 0
|
||||||
|
|
13
app/jobs/git_pull_job.rb
Normal file
13
app/jobs/git_pull_job.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Permite traer los cambios desde webhooks
|
||||||
|
|
||||||
|
class GitPullJob < ApplicationJob
|
||||||
|
# @param :site [Site]
|
||||||
|
# @param :usuarie [Usuarie]
|
||||||
|
# @param :message [String]
|
||||||
|
# @return [nil]
|
||||||
|
def perform(site, usuarie, message)
|
||||||
|
site.repository.merge(usuarie, message) if site.repository.fetch&.positive?
|
||||||
|
end
|
||||||
|
end
|
11
app/jobs/git_push_job.rb
Normal file
11
app/jobs/git_push_job.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Permite pushear los cambios cada vez que se
|
||||||
|
# hacen commits en un sitio
|
||||||
|
class GitPushJob < ApplicationJob
|
||||||
|
# @param :site [Site]
|
||||||
|
# @return [nil]
|
||||||
|
def perform(site)
|
||||||
|
site.repository.push if site.repository.origin
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,9 +8,9 @@ module ExceptionNotifier
|
||||||
# Recibe la excepción y empieza la tarea de notificación en segundo
|
# Recibe la excepción y empieza la tarea de notificación en segundo
|
||||||
# plano.
|
# plano.
|
||||||
#
|
#
|
||||||
# @param [Exception]
|
# @param :exception [Exception]
|
||||||
# @param [Hash]
|
# @param :options [Hash]
|
||||||
def call(exception, **options)
|
def call(exception, options, &block)
|
||||||
case exception
|
case exception
|
||||||
when BacktraceJob::BacktraceException
|
when BacktraceJob::BacktraceException
|
||||||
GitlabNotifierJob.perform_later(exception, **options)
|
GitlabNotifierJob.perform_later(exception, **options)
|
||||||
|
|
|
@ -52,7 +52,7 @@ class DeployMailer < ApplicationMailer
|
||||||
t << (row.map do |k, v|
|
t << (row.map do |k, v|
|
||||||
case k
|
case k
|
||||||
when :seconds then v[:human]
|
when :seconds then v[:human]
|
||||||
when :urls then url
|
when :urls then url.to_s
|
||||||
else v
|
else v
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -23,6 +23,11 @@ class Deploy < ApplicationRecord
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [Array]
|
||||||
|
def urls
|
||||||
|
[url].compact
|
||||||
|
end
|
||||||
|
|
||||||
def limit
|
def limit
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
@ -55,6 +60,22 @@ class Deploy < ApplicationRecord
|
||||||
@gems_dir ||= Rails.root.join('_storage', 'gems', site.name)
|
@gems_dir ||= Rails.root.join('_storage', 'gems', site.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Un entorno que solo tiene lo que necesitamos
|
||||||
|
#
|
||||||
|
# @return [Hash]
|
||||||
|
def env
|
||||||
|
# XXX: This doesn't support Windows paths :B
|
||||||
|
paths = [File.dirname(`which bundle`), '/usr/local/bin', '/usr/bin', '/bin']
|
||||||
|
|
||||||
|
# Las variables de entorno extra no pueden superponerse al local.
|
||||||
|
extra_env.merge({
|
||||||
|
'HOME' => home_dir,
|
||||||
|
'PATH' => paths.join(':'),
|
||||||
|
'JEKYLL_ENV' => Rails.env,
|
||||||
|
'LANG' => ENV['LANG'],
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
# Corre un comando, lo registra en la base de datos y devuelve el
|
# Corre un comando, lo registra en la base de datos y devuelve el
|
||||||
# estado.
|
# estado.
|
||||||
#
|
#
|
||||||
|
@ -65,8 +86,7 @@ class Deploy < ApplicationRecord
|
||||||
lines = []
|
lines = []
|
||||||
|
|
||||||
time_start
|
time_start
|
||||||
Dir.chdir(site.path) do
|
Open3.popen2e(env, cmd, unsetenv_others: true, chdir: site.path) do |_, o, t|
|
||||||
Open3.popen2e(env, cmd, unsetenv_others: true) do |_, o, t|
|
|
||||||
# TODO: Enviar a un websocket para ver el proceso en vivo?
|
# TODO: Enviar a un websocket para ver el proceso en vivo?
|
||||||
Thread.new do
|
Thread.new do
|
||||||
o.each do |line|
|
o.each do |line|
|
||||||
|
@ -81,7 +101,6 @@ class Deploy < ApplicationRecord
|
||||||
|
|
||||||
r = t.value
|
r = t.value
|
||||||
end
|
end
|
||||||
end
|
|
||||||
time_stop
|
time_stop
|
||||||
|
|
||||||
build_stats.create action: readable_cmd(cmd),
|
build_stats.create action: readable_cmd(cmd),
|
||||||
|
@ -100,6 +119,11 @@ class Deploy < ApplicationRecord
|
||||||
@local_env ||= {}
|
@local_env ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Devuelve opciones para jekyll build
|
||||||
|
#
|
||||||
|
# @return [String,nil]
|
||||||
|
def flags_for_build(**args); end
|
||||||
|
|
||||||
# Trae todas las dependencias
|
# Trae todas las dependencias
|
||||||
#
|
#
|
||||||
# @return [Array]
|
# @return [Array]
|
||||||
|
@ -109,6 +133,21 @@ class Deploy < ApplicationRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Escribe el contenido en un archivo temporal y ejecuta el bloque
|
||||||
|
# provisto con el archivo como parámetro
|
||||||
|
#
|
||||||
|
# @param :content [String]
|
||||||
|
def with_tempfile(content, &block)
|
||||||
|
Tempfile.create(SecureRandom.hex) do |file|
|
||||||
|
file.write content.to_s
|
||||||
|
file.rewind
|
||||||
|
file.close
|
||||||
|
|
||||||
|
# @yieldparam :file [File]
|
||||||
|
yield file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# @param [String]
|
# @param [String]
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def readable_cmd(cmd)
|
def readable_cmd(cmd)
|
||||||
|
@ -119,7 +158,14 @@ class Deploy < ApplicationRecord
|
||||||
@deploy_local ||= site.deploys.find_by(type: 'DeployLocal')
|
@deploy_local ||= site.deploys.find_by(type: 'DeployLocal')
|
||||||
end
|
end
|
||||||
|
|
||||||
def non_local_deploys
|
# Consigue todas las variables de entorno configuradas por otros
|
||||||
@non_local_deploys ||= site.deploys.where.not(type: 'DeployLocal')
|
# deploys.
|
||||||
|
#
|
||||||
|
# @return [Hash]
|
||||||
|
def extra_env
|
||||||
|
@extra_env ||=
|
||||||
|
site.deployment_list.reduce({}) do |extra, deploy|
|
||||||
|
extra.merge deploy.local_env
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,7 +52,12 @@ class DeployDistributedPress < Deploy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
status = c.publish(publishing_site, deploy_local.destination)
|
status = c.publish(publishing_site, deploy_local.destination)
|
||||||
|
rescue DistributedPress::V1::Error => e
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name })
|
||||||
|
status = false
|
||||||
|
end
|
||||||
|
|
||||||
if status
|
if status
|
||||||
self.remote_info[:distributed_press] = c.show(publishing_site).to_h
|
self.remote_info[:distributed_press] = c.show(publishing_site).to_h
|
||||||
|
|
|
@ -62,32 +62,24 @@ class DeployLocal < Deploy
|
||||||
FileUtils.rm_rf(File.join(site.path, '.jekyll-cache'))
|
FileUtils.rm_rf(File.join(site.path, '.jekyll-cache'))
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
# Opciones necesarias para la compilación del sitio
|
||||||
|
|
||||||
def mkdir
|
|
||||||
FileUtils.mkdir_p destination
|
|
||||||
end
|
|
||||||
|
|
||||||
# Un entorno que solo tiene lo que necesitamos
|
|
||||||
#
|
#
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def env
|
def local_env
|
||||||
# XXX: This doesn't support Windows paths :B
|
@local_env ||= {
|
||||||
paths = [File.dirname(`which bundle`), '/usr/local/bin', '/usr/bin', '/bin']
|
|
||||||
|
|
||||||
# Las variables de entorno extra no pueden superponerse al local.
|
|
||||||
extra_env.merge({
|
|
||||||
'HOME' => home_dir,
|
|
||||||
'PATH' => paths.join(':'),
|
|
||||||
'SPREE_API_KEY' => site.tienda_api_key,
|
'SPREE_API_KEY' => site.tienda_api_key,
|
||||||
'SPREE_URL' => site.tienda_url,
|
'SPREE_URL' => site.tienda_url,
|
||||||
'AIRBRAKE_PROJECT_ID' => site.id.to_s,
|
'AIRBRAKE_PROJECT_ID' => site.id.to_s,
|
||||||
'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key,
|
'AIRBRAKE_PROJECT_KEY' => site.airbrake_api_key,
|
||||||
'JEKYLL_ENV' => Rails.env,
|
|
||||||
'LANG' => ENV['LANG'],
|
|
||||||
'YARN_CACHE_FOLDER' => yarn_cache_dir,
|
'YARN_CACHE_FOLDER' => yarn_cache_dir,
|
||||||
'GEMS_SOURCE' => ENV['GEMS_SOURCE']
|
'GEMS_SOURCE' => ENV['GEMS_SOURCE']
|
||||||
})
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def mkdir
|
||||||
|
FileUtils.mkdir_p destination
|
||||||
end
|
end
|
||||||
|
|
||||||
def yarn_cache_dir
|
def yarn_cache_dir
|
||||||
|
@ -138,11 +130,20 @@ class DeployLocal < Deploy
|
||||||
end
|
end
|
||||||
|
|
||||||
def bundle(output: false)
|
def bundle(output: false)
|
||||||
run %(bundle install --deployment --no-cache --path="#{gems_dir}" --clean --without test development), output: output
|
run %(bundle config set --local clean 'true'), output: output
|
||||||
|
run %(bundle config set --local deployment 'true'), output: output
|
||||||
|
run %(bundle config set --local path '#{gems_dir}'), output: output
|
||||||
|
run %(bundle config set --local without 'test development'), output: output
|
||||||
|
run %(bundle config set --local cache_all 'false'), output: output
|
||||||
|
run %(bundle install), output: output
|
||||||
end
|
end
|
||||||
|
|
||||||
def jekyll_build(output: false)
|
def jekyll_build(output: false)
|
||||||
run %(bundle exec jekyll build --trace --profile --destination "#{escaped_destination}"), output: output
|
with_tempfile(site.private_key_pem) do |file|
|
||||||
|
flags = extra_flags(private_key: file)
|
||||||
|
|
||||||
|
run %(bundle exec jekyll build --trace --profile #{flags} --destination "#{escaped_destination}"), output: output
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# no debería haber espacios ni caracteres especiales, pero por si
|
# no debería haber espacios ni caracteres especiales, pero por si
|
||||||
|
@ -156,17 +157,13 @@ class DeployLocal < Deploy
|
||||||
FileUtils.rm_rf destination
|
FileUtils.rm_rf destination
|
||||||
end
|
end
|
||||||
|
|
||||||
# Consigue todas las variables de entorno configuradas por otros
|
# Genera opciones extra desde los otros deploys
|
||||||
# deploys.
|
|
||||||
#
|
#
|
||||||
# @deprecated Solo tenía sentido para Distributed Press v0
|
# @param :args [Hash]
|
||||||
# @return [Hash]
|
# @return [String]
|
||||||
def extra_env
|
def extra_flags(**args)
|
||||||
@extra_env ||=
|
site.deployment_list.map do |deploy|
|
||||||
non_local_deploys.reduce({}) do |extra_env, deploy|
|
deploy.flags_for_build(**args)
|
||||||
extra_env.tap do |e|
|
end.compact.join(' ')
|
||||||
e.merge! deploy.local_env
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
55
app/models/deploy_social_distributed_press.rb
Normal file
55
app/models/deploy_social_distributed_press.rb
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'distributed_press/v1/social/client'
|
||||||
|
|
||||||
|
# Publicar novedades al Fediverso
|
||||||
|
class DeploySocialDistributedPress < Deploy
|
||||||
|
# Solo luego de publicar remotamente
|
||||||
|
DEPENDENCIES = %i[deploy_distributed_press deploy_rsync deploy_full_rsync]
|
||||||
|
|
||||||
|
# Envía las notificaciones
|
||||||
|
def deploy(output: false)
|
||||||
|
with_tempfile(site.private_key_pem) do |file|
|
||||||
|
key = Shellwords.escape file.path
|
||||||
|
dest = Shellwords.escape destination
|
||||||
|
|
||||||
|
run %(bundle exec jekyll notify --trace --key #{key} --destination "#{dest}"), output: output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Igual que DeployLocal
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def destination
|
||||||
|
File.join(Rails.root, '_deploy', site.hostname)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Solo uno
|
||||||
|
#
|
||||||
|
# @return [Integer]
|
||||||
|
def limit
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Espacio ocupado, pero no podemos calcularlo
|
||||||
|
#
|
||||||
|
# @return [Integer]
|
||||||
|
def size
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
# El perfil de actor
|
||||||
|
#
|
||||||
|
# @return [String,nil]
|
||||||
|
def url
|
||||||
|
site.data.dig('activity_pub', 'actor')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Genera la opción de llave privada para jekyll build
|
||||||
|
#
|
||||||
|
# @params :args [Hash]
|
||||||
|
# @return [String]
|
||||||
|
def flags_for_build(**args)
|
||||||
|
"--key #{Shellwords.escape args[:private_key].path}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,8 +4,12 @@
|
||||||
#
|
#
|
||||||
# Esto es increíblemente difícil de lograr que salga bien!
|
# Esto es increíblemente difícil de lograr que salga bien!
|
||||||
class MetadataBoolean < MetadataTemplate
|
class MetadataBoolean < MetadataTemplate
|
||||||
|
# El valor por defecto es una versión booleana de lo que diga (o no
|
||||||
|
# diga) el esquema
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def default_value
|
def default_value
|
||||||
false
|
!!super
|
||||||
end
|
end
|
||||||
|
|
||||||
# Los checkboxes son especiales porque la especificación de HTML
|
# Los checkboxes son especiales porque la especificación de HTML
|
||||||
|
|
19
app/models/metadata_created_at.rb
Normal file
19
app/models/metadata_created_at.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Fecha y hora de creación
|
||||||
|
class MetadataCreatedAt < MetadataTemplate
|
||||||
|
# Por defecto la hora actual, pero por retrocompatibilidad, queremos
|
||||||
|
# la fecha de publicación
|
||||||
|
def default_value
|
||||||
|
if post.date.value.to_date < Time.now.to_date
|
||||||
|
post.date.value
|
||||||
|
else
|
||||||
|
Time.now
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Nunca cambia
|
||||||
|
def value=(new_value)
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
|
@ -34,7 +34,7 @@ class MetadataRelatedPosts < MetadataArray
|
||||||
end
|
end
|
||||||
|
|
||||||
def title(post)
|
def title(post)
|
||||||
"#{post&.title&.value || post&.slug&.value} (#{post.layout.humanized_name})"
|
"#{post&.title&.value || post&.slug&.value} #{post&.date&.value.strftime('%F')} (#{post.layout.humanized_name})"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Encuentra el filtro
|
# Encuentra el filtro
|
||||||
|
|
|
@ -202,7 +202,7 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
|
|
||||||
def allowed_attributes
|
def allowed_attributes
|
||||||
@allowed_attributes ||= %w[style href src alt controls data-align data-multimedia data-multimedia-inner id
|
@allowed_attributes ||= %w[style href src alt controls data-align data-multimedia data-multimedia-inner id
|
||||||
name].freeze
|
name start].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_tags
|
def allowed_tags
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Post
|
||||||
DEFAULT_ATTRIBUTES = %i[site document layout].freeze
|
DEFAULT_ATTRIBUTES = %i[site document layout].freeze
|
||||||
# Otros atributos que no vienen en los metadatos
|
# Otros atributos que no vienen en los metadatos
|
||||||
PRIVATE_ATTRIBUTES = %i[path slug attributes errors].freeze
|
PRIVATE_ATTRIBUTES = %i[path slug attributes errors].freeze
|
||||||
PUBLIC_ATTRIBUTES = %i[lang date uuid].freeze
|
PUBLIC_ATTRIBUTES = %i[lang date uuid created_at].freeze
|
||||||
ATTR_SUFFIXES = %w[? =].freeze
|
ATTR_SUFFIXES = %w[? =].freeze
|
||||||
|
|
||||||
attr_reader :attributes, :errors, :layout, :site, :document
|
attr_reader :attributes, :errors, :layout, :site, :document
|
||||||
|
@ -217,6 +217,11 @@ class Post
|
||||||
post: self, required: true)
|
post: self, required: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# La fecha de creación inmodificable del post
|
||||||
|
def created_at
|
||||||
|
@metadata[:created_at] ||= MetadataCreatedAt.new(document: document, site: site, layout: layout, name: :created_at, type: :created_at, post: self, required: true)
|
||||||
|
end
|
||||||
|
|
||||||
# Detecta si es un atributo válido o no, a partir de la tabla de la
|
# Detecta si es un atributo válido o no, a partir de la tabla de la
|
||||||
# plantilla
|
# plantilla
|
||||||
def attribute?(mid)
|
def attribute?(mid)
|
||||||
|
@ -267,6 +272,7 @@ class Post
|
||||||
# Y que no se procese liquid
|
# Y que no se procese liquid
|
||||||
yaml['liquid'] = false
|
yaml['liquid'] = false
|
||||||
yaml['usuaries'] = usuaries.map(&:id).uniq
|
yaml['usuaries'] = usuaries.map(&:id).uniq
|
||||||
|
yaml['created_at'] = created_at.value
|
||||||
yaml['last_modified_at'] = modified_at
|
yaml['last_modified_at'] = modified_at
|
||||||
|
|
||||||
"#{yaml.to_yaml}---\n\n#{body}"
|
"#{yaml.to_yaml}---\n\n#{body}"
|
||||||
|
|
|
@ -14,6 +14,8 @@ class Rol < ApplicationRecord
|
||||||
|
|
||||||
validates_inclusion_of :rol, in: ROLES
|
validates_inclusion_of :rol, in: ROLES
|
||||||
|
|
||||||
|
before_save :add_token_if_missing!
|
||||||
|
|
||||||
def invitade?
|
def invitade?
|
||||||
rol == INVITADE
|
rol == INVITADE
|
||||||
end
|
end
|
||||||
|
@ -25,4 +27,11 @@ class Rol < ApplicationRecord
|
||||||
def self.role?(rol)
|
def self.role?(rol)
|
||||||
ROLES.include? rol
|
ROLES.include? rol
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Asegurarse que tenga un token
|
||||||
|
def add_token_if_missing!
|
||||||
|
self.token ||= SecureRandom.hex(64)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ class Site < ApplicationRecord
|
||||||
include Site::DeployDependencies
|
include Site::DeployDependencies
|
||||||
include Site::BuildStats
|
include Site::BuildStats
|
||||||
include Site::LayoutOrdering
|
include Site::LayoutOrdering
|
||||||
|
include Site::SocialDistributedPress
|
||||||
include Tienda
|
include Tienda
|
||||||
|
|
||||||
# Cifrar la llave privada que cifra y decifra campos ocultos. Sutty
|
# Cifrar la llave privada que cifra y decifra campos ocultos. Sutty
|
||||||
|
@ -18,10 +19,6 @@ class Site < ApplicationRecord
|
||||||
# protege de acceso al panel de Sutty!
|
# protege de acceso al panel de Sutty!
|
||||||
encrypts :private_key
|
encrypts :private_key
|
||||||
|
|
||||||
# TODO: Hacer que los diferentes tipos de deploy se auto registren
|
|
||||||
# @see app/services/site_service.rb
|
|
||||||
DEPLOYS = %i[local private www zip hidden_service distributed_press].freeze
|
|
||||||
|
|
||||||
validates :name, uniqueness: true, hostname: {
|
validates :name, uniqueness: true, hostname: {
|
||||||
allow_root_label: true
|
allow_root_label: true
|
||||||
}
|
}
|
||||||
|
@ -447,6 +444,10 @@ class Site < ApplicationRecord
|
||||||
find_by(name: "#{Site.domain}.")
|
find_by(name: "#{Site.domain}.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.one_at_a_time
|
||||||
|
@@one_at_a_time ||= Thread::Mutex.new
|
||||||
|
end
|
||||||
|
|
||||||
def reset
|
def reset
|
||||||
@read = false
|
@read = false
|
||||||
@layouts = nil
|
@layouts = nil
|
||||||
|
@ -474,6 +475,9 @@ class Site < ApplicationRecord
|
||||||
return if jekyll?
|
return if jekyll?
|
||||||
|
|
||||||
Rugged::Repository.clone_at ENV['SKEL_SUTTY'], path
|
Rugged::Repository.clone_at ENV['SKEL_SUTTY'], path
|
||||||
|
|
||||||
|
# Necesita un bloque
|
||||||
|
repository.rugged.remotes.rename('origin', 'upstream') {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Elimina el directorio del sitio
|
# Elimina el directorio del sitio
|
||||||
|
@ -553,8 +557,10 @@ class Site < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_in_path(&block)
|
def run_in_path(&block)
|
||||||
|
Site.one_at_a_time.synchronize do
|
||||||
Dir.chdir path, &block
|
Dir.chdir path, &block
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Instala las gemas cuando es necesario:
|
# Instala las gemas cuando es necesario:
|
||||||
#
|
#
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Site
|
||||||
|
|
||||||
author = GitAuthor.new email: "sutty@#{Site.domain}", name: 'Sutty'
|
author = GitAuthor.new email: "sutty@#{Site.domain}", name: 'Sutty'
|
||||||
|
|
||||||
repository.commit(file: modified,
|
repository.commit(add: modified,
|
||||||
message: I18n.t('sites.find_and_replace'),
|
message: I18n.t('sites.find_and_replace'),
|
||||||
usuarie: author)
|
usuarie: author)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,6 @@ class Site
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
# TODO: Debería ser un Job?
|
|
||||||
after_create :index_posts!
|
|
||||||
has_many :indexed_posts, dependent: :destroy
|
has_many :indexed_posts, dependent: :destroy
|
||||||
|
|
||||||
def index_posts!
|
def index_posts!
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Site
|
||||||
|
|
||||||
# Obtiene el origin
|
# Obtiene el origin
|
||||||
#
|
#
|
||||||
# @return [Rugged::Remote]
|
# @return [Rugged::Remote, nil]
|
||||||
def origin
|
def origin
|
||||||
@origin ||= rugged.remotes.find do |remote|
|
@origin ||= rugged.remotes.find do |remote|
|
||||||
remote.name == 'origin'
|
remote.name == 'origin'
|
||||||
|
@ -54,7 +54,7 @@ class Site
|
||||||
# Incorpora los cambios en el repositorio actual
|
# Incorpora los cambios en el repositorio actual
|
||||||
#
|
#
|
||||||
# @return [Rugged::Commit]
|
# @return [Rugged::Commit]
|
||||||
def merge(usuarie)
|
def merge(usuarie, message = I18n.t('sites.fetch.merge.message'))
|
||||||
merge = rugged.merge_commits(head_commit, remote_head_commit)
|
merge = rugged.merge_commits(head_commit, remote_head_commit)
|
||||||
|
|
||||||
# No hacemos nada si hay conflictos, pero notificarnos
|
# No hacemos nada si hay conflictos, pero notificarnos
|
||||||
|
@ -69,12 +69,16 @@ class Site
|
||||||
.create(rugged, update_ref: 'HEAD',
|
.create(rugged, update_ref: 'HEAD',
|
||||||
parents: [head_commit, remote_head_commit],
|
parents: [head_commit, remote_head_commit],
|
||||||
tree: merge.write_tree(rugged),
|
tree: merge.write_tree(rugged),
|
||||||
message: I18n.t('sites.fetch.merge.message'),
|
message: message,
|
||||||
author: author(usuarie), committer: committer)
|
author: author(usuarie), committer: committer)
|
||||||
|
|
||||||
# Forzamos el checkout para mover el HEAD al último commit y
|
# Forzamos el checkout para mover el HEAD al último commit y
|
||||||
# escribir los cambios
|
# escribir los cambios
|
||||||
rugged.checkout 'HEAD', strategy: :force
|
rugged.checkout 'HEAD', strategy: :force
|
||||||
|
|
||||||
|
git_sh("git", "lfs", "fetch", "origin", default_branch)
|
||||||
|
# reemplaza los pointers por los archivos correspondientes
|
||||||
|
git_sh("git", "lfs", "checkout")
|
||||||
commit
|
commit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -114,14 +118,21 @@ class Site
|
||||||
end
|
end
|
||||||
|
|
||||||
# Guarda los cambios en git
|
# Guarda los cambios en git
|
||||||
def commit(file:, usuarie:, message:, remove: false)
|
#
|
||||||
file = [file] unless file.respond_to? :each
|
# @param :add [Array] Archivos a agregar
|
||||||
|
# @param :rm [Array] Archivos a eliminar
|
||||||
|
# @param :usuarie [Usuarie] Quién hace el commit
|
||||||
|
# @param :message [String] Mensaje
|
||||||
|
def commit(add: [], rm: [], usuarie:, message:)
|
||||||
# Cargar el árbol actual
|
# Cargar el árbol actual
|
||||||
rugged.index.read_tree rugged.head.target.tree
|
rugged.index.read_tree rugged.head.target.tree
|
||||||
|
|
||||||
file.each do |f|
|
add.each do |file|
|
||||||
remove ? rm(f) : add(f)
|
rugged.index.add(relativize(file))
|
||||||
|
end
|
||||||
|
|
||||||
|
rm.each do |file|
|
||||||
|
rugged.index.remove(relativize(file))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Escribir los cambios para que el repositorio se vea tal cual
|
# Escribir los cambios para que el repositorio se vea tal cual
|
||||||
|
@ -142,41 +153,58 @@ class Site
|
||||||
{ name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now }
|
{ name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now }
|
||||||
end
|
end
|
||||||
|
|
||||||
def add(file)
|
|
||||||
rugged.index.add(relativize(file))
|
|
||||||
end
|
|
||||||
|
|
||||||
def rm(file)
|
|
||||||
rugged.index.remove(relativize(file))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Garbage collection
|
# Garbage collection
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def gc
|
def gc
|
||||||
env = { 'PATH' => '/usr/bin', 'LANG' => ENV['LANG'], 'HOME' => path }
|
git_sh("git", "gc")
|
||||||
cmd = 'git gc'
|
|
||||||
|
|
||||||
r = nil
|
|
||||||
Dir.chdir(path) do
|
|
||||||
Open3.popen2e(env, cmd, unsetenv_others: true) do |_, _, t|
|
|
||||||
r = t.value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
r&.success?
|
# Pushea cambios al repositorio remoto
|
||||||
|
#
|
||||||
|
# @param :remote [Rugged::Remote]
|
||||||
|
# @return [Boolean, nil]
|
||||||
|
def push(remote = origin)
|
||||||
|
remote.push(rugged.head.canonical_name, credentials: credentials_for(remote))
|
||||||
|
git_sh('git', 'lfs', 'push', remote.name, default_branch)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# @deprecated
|
||||||
|
def credentials
|
||||||
|
@credentials ||= credentials_for(origin)
|
||||||
|
end
|
||||||
|
|
||||||
# Si Sutty tiene una llave privada de tipo ED25519, devuelve las
|
# Si Sutty tiene una llave privada de tipo ED25519, devuelve las
|
||||||
# credenciales necesarias para trabajar con repositorios remotos.
|
# credenciales necesarias para trabajar con repositorios remotos.
|
||||||
#
|
#
|
||||||
|
# @param :remote [Rugged::Remote]
|
||||||
# @return [Nil, Rugged::Credentials::SshKey]
|
# @return [Nil, Rugged::Credentials::SshKey]
|
||||||
def credentials
|
def credentials_for(remote)
|
||||||
return unless File.exist? private_key
|
return unless File.exist? private_key
|
||||||
|
|
||||||
@credentials ||= Rugged::Credentials::SshKey.new username: 'git', publickey: public_key, privatekey: private_key
|
Rugged::Credentials::SshKey.new username: username_for(remote), publickey: public_key, privatekey: private_key
|
||||||
|
end
|
||||||
|
|
||||||
|
# Obtiene el nombre de usuario para el repositorio remoto, por
|
||||||
|
# defecto git
|
||||||
|
#
|
||||||
|
# @param :remote [Rugged::Remote]
|
||||||
|
# @return [String]
|
||||||
|
def username_for(remote)
|
||||||
|
username = parse_url(remote.url)&.user if remote.respond_to? :url
|
||||||
|
|
||||||
|
username || 'git'
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param :url [String]
|
||||||
|
# @return [URI, nil]
|
||||||
|
def parse_url(url)
|
||||||
|
GitCloneUrl.parse(url)
|
||||||
|
rescue URI::Error => e
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { path: path, url: url })
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
@ -192,5 +220,20 @@ class Site
|
||||||
def relativize(file)
|
def relativize(file)
|
||||||
Pathname.new(file).relative_path_from(Pathname.new(path)).to_s
|
Pathname.new(file).relative_path_from(Pathname.new(path)).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Ejecuta un comando de git
|
||||||
|
#
|
||||||
|
# @param :args [Array]
|
||||||
|
# @return [Boolean]
|
||||||
|
def git_sh(*args)
|
||||||
|
env = { 'PATH' => '/usr/bin', 'LANG' => ENV['LANG'], 'HOME' => path }
|
||||||
|
|
||||||
|
r = nil
|
||||||
|
Open3.popen2e(env, *args, unsetenv_others: true, chdir: path) do |_, _, t|
|
||||||
|
r = t.value
|
||||||
|
end
|
||||||
|
|
||||||
|
r&.success?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
23
app/models/site/social_distributed_press.rb
Normal file
23
app/models/site/social_distributed_press.rb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Site
|
||||||
|
# Agrega soporte para Social Distributed Press en los sitios
|
||||||
|
module SocialDistributedPress
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
encrypts :private_key_pem
|
||||||
|
|
||||||
|
before_save :generate_private_key_pem!, unless: :private_key_pem?
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Genera la llave privada y la almacena
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def generate_private_key_pem!
|
||||||
|
self.private_key_pem ||= DistributedPress::V1::Social::Client.new(public_key_url: nil, key_size: 2048).private_key.export
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,6 +10,7 @@ class Usuarie < ApplicationRecord
|
||||||
|
|
||||||
validates_uniqueness_of :email
|
validates_uniqueness_of :email
|
||||||
validates_with EmailAddress::ActiveRecordValidator, field: :email
|
validates_with EmailAddress::ActiveRecordValidator, field: :email
|
||||||
|
validate :locale_available!
|
||||||
|
|
||||||
before_create :lang_from_locale!
|
before_create :lang_from_locale!
|
||||||
before_update :remove_confirmation_invitation_inconsistencies!
|
before_update :remove_confirmation_invitation_inconsistencies!
|
||||||
|
@ -78,4 +79,15 @@ class Usuarie < ApplicationRecord
|
||||||
self.invitation_accepted_at ||= Time.now.utc
|
self.invitation_accepted_at ||= Time.now.utc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Muestra un error si el idioma no está disponible al cambiar el
|
||||||
|
# idioma de la cuenta.
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def locale_available!
|
||||||
|
return if I18n.locale_available? self.lang
|
||||||
|
|
||||||
|
errors.add(:lang, I18n.t('activerecord.errors.models.usuarie.attributes.lang.not_available'))
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,7 @@ class LfsObjectService
|
||||||
Site::Writer.new(site: site, file: path, content: pointer).save
|
Site::Writer.new(site: site, file: path, content: pointer).save
|
||||||
|
|
||||||
# Commitear el pointer
|
# Commitear el pointer
|
||||||
site.repository.commit(file: path, usuarie: author, message: File.basename(path))
|
site.repository.commit(add: [path], usuarie: author, message: File.basename(path))
|
||||||
|
|
||||||
# Eliminar el pointer
|
# Eliminar el pointer
|
||||||
FileUtils.rm(path)
|
FileUtils.rm(path)
|
||||||
|
|
|
@ -16,7 +16,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
post.slug.value = p[:slug] if p[:slug].present?
|
post.slug.value = p[:slug] if p[:slug].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
commit(action: :created, file: update_related_posts) if post.update(post_params)
|
commit(action: :created, add: update_related_posts) if post.update(post_params)
|
||||||
|
|
||||||
update_site_license!
|
update_site_license!
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
# Los artículos anónimos siempre son borradores
|
# Los artículos anónimos siempre son borradores
|
||||||
params[:draft] = true
|
params[:draft] = true
|
||||||
|
|
||||||
commit(action: :created) if post.update(anon_post_params)
|
commit(action: :created, add: [post.path.absolute]) if post.update(anon_post_params)
|
||||||
post
|
post
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -42,11 +42,17 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
post.usuaries << usuarie
|
post.usuaries << usuarie
|
||||||
params[:post][:draft] = true if site.invitade? usuarie
|
params[:post][:draft] = true if site.invitade? usuarie
|
||||||
|
|
||||||
|
# Eliminar ("mover") el archivo si cambió de ubicación.
|
||||||
|
if post.update(post_params)
|
||||||
|
rm = []
|
||||||
|
rm << post.path.value_was if post.path.changed?
|
||||||
|
|
||||||
# Es importante que el artículo se guarde primero y luego los
|
# Es importante que el artículo se guarde primero y luego los
|
||||||
# relacionados.
|
# relacionados.
|
||||||
commit(action: :updated, file: update_related_posts) if post.update(post_params)
|
commit(action: :updated, add: update_related_posts, rm: rm)
|
||||||
|
|
||||||
update_site_license!
|
update_site_license!
|
||||||
|
end
|
||||||
|
|
||||||
# Devolver el post aunque no se haya salvado para poder rescatar los
|
# Devolver el post aunque no se haya salvado para poder rescatar los
|
||||||
# errores
|
# errores
|
||||||
|
@ -56,7 +62,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
def destroy
|
def destroy
|
||||||
post.destroy!
|
post.destroy!
|
||||||
|
|
||||||
commit(action: :destroyed) if post.destroyed?
|
commit(action: :destroyed, rm: [post.path.absolute]) if post.destroyed?
|
||||||
|
|
||||||
post
|
post
|
||||||
end
|
end
|
||||||
|
@ -85,17 +91,19 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
|
|
||||||
# TODO: Implementar transacciones!
|
# TODO: Implementar transacciones!
|
||||||
posts.save_all(validate: false) &&
|
posts.save_all(validate: false) &&
|
||||||
commit(action: :reorder, file: files)
|
commit(action: :reorder, add: files)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def commit(action:, file: nil)
|
def commit(action:, add: [], rm: [])
|
||||||
site.repository.commit(file: file || post.path.absolute,
|
site.repository.commit(add: add,
|
||||||
|
rm: rm,
|
||||||
usuarie: usuarie,
|
usuarie: usuarie,
|
||||||
remove: action == :destroyed,
|
|
||||||
message: I18n.t("post_service.#{action}",
|
message: I18n.t("post_service.#{action}",
|
||||||
title: post&.title&.value))
|
title: post&.title&.value))
|
||||||
|
|
||||||
|
GitPushJob.perform_later(site)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Solo permitir cambiar estos atributos de cada articulo
|
# Solo permitir cambiar estos atributos de cada articulo
|
||||||
|
|
|
@ -33,6 +33,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
add_licencias &&
|
add_licencias &&
|
||||||
add_code_of_conduct &&
|
add_code_of_conduct &&
|
||||||
add_privacy_policy &&
|
add_privacy_policy &&
|
||||||
|
site.index_posts! &&
|
||||||
deploy
|
deploy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -54,9 +55,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
|
|
||||||
# Genera los Deploy necesarios para el sitio a menos que ya los tenga.
|
# Genera los Deploy necesarios para el sitio a menos que ya los tenga.
|
||||||
def build_deploys
|
def build_deploys
|
||||||
Site::DEPLOYS.map { |deploy| "Deploy#{deploy.to_s.camelcase}" }
|
Deploy.subclasses.each do |deploy|
|
||||||
.each do |deploy|
|
next if site.deploys.find_by type: deploy.name
|
||||||
next if site.deploys.find_by type: deploy
|
|
||||||
|
|
||||||
site.deploys.build type: deploy
|
site.deploys.build type: deploy
|
||||||
end
|
end
|
||||||
|
@ -94,9 +94,11 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
def commit_config(action:)
|
def commit_config(action:)
|
||||||
site.repository
|
site.repository
|
||||||
.commit(usuarie: usuarie,
|
.commit(usuarie: usuarie,
|
||||||
file: site.config.path,
|
add: [site.config.path],
|
||||||
message: I18n.t("site_service.#{action}",
|
message: I18n.t("site_service.#{action}",
|
||||||
name: site.name))
|
name: site.name))
|
||||||
|
|
||||||
|
GitPushJob.perform_later(site)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_role(temporal: true, rol: 'invitade')
|
def add_role(temporal: true, rol: 'invitade')
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
- row[:urls].each do |url|
|
- row[:urls].each do |url|
|
||||||
%tr
|
%tr
|
||||||
%th{ scope: 'row' }= row[:title]
|
%th{ scope: 'row' }= row[:title]
|
||||||
%td= link_to_if url.present?, url, url, class: 'word-break-all'
|
%td= link_to_if (url.present? && url.scheme.present?), url.to_s, url.to_s, class: 'word-break-all'
|
||||||
%td
|
%td
|
||||||
%time{ datetime: row[:seconds][:machine] }= row[:seconds][:human]
|
%time{ datetime: row[:seconds][:machine] }= row[:seconds][:human]
|
||||||
%td= row[:size]
|
%td= row[:size]
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
%tr
|
%tr
|
||||||
%td= row[:title]
|
%td= row[:title]
|
||||||
%td= row[:status]
|
%td= row[:status]
|
||||||
%td= link_to_if url.present?, url, url
|
%td= link_to_if (url.present? && url.scheme.present?), url.to_s, url.to_s
|
||||||
%td
|
%td
|
||||||
%time{ datetime: row[:seconds][:machine] }= row[:seconds][:human]
|
%time{ datetime: row[:seconds][:machine] }= row[:seconds][:human]
|
||||||
%td= row[:size]
|
%td= row[:size]
|
||||||
|
|
21
app/views/deploys/_deploy_social_distributed_press.haml
Normal file
21
app/views/deploys/_deploy_social_distributed_press.haml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
-# Publicar a la web distribuida
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col
|
||||||
|
= deploy.hidden_field :id
|
||||||
|
= deploy.hidden_field :type
|
||||||
|
.custom-control.custom-switch
|
||||||
|
-#
|
||||||
|
El checkbox invierte la lógica de destrucción porque queremos
|
||||||
|
crear el deploy si está activado y destruirlo si está
|
||||||
|
desactivado.
|
||||||
|
= deploy.check_box :_destroy,
|
||||||
|
{ checked: deploy.object.persisted?, class: 'custom-control-input' },
|
||||||
|
'0', '1'
|
||||||
|
= deploy.label :_destroy, class: 'custom-control-label' do
|
||||||
|
%h3= t('.title')
|
||||||
|
= sanitize_markdown t('.help'),
|
||||||
|
tags: %w[p strong em a]
|
||||||
|
|
||||||
|
|
||||||
|
%hr/
|
3
app/views/env/index.js.haml
vendored
3
app/views/env/index.js.haml
vendored
|
@ -1,4 +1,5 @@
|
||||||
= cache @site do
|
- if @site
|
||||||
|
= cache @site do
|
||||||
:plain
|
:plain
|
||||||
window.env = {
|
window.env = {
|
||||||
AIRBRAKE_SITE_ID: #{@site.id},
|
AIRBRAKE_SITE_ID: #{@site.id},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- flash.each do |type, message|
|
- flash.each do |type, message|
|
||||||
- unless type == 'js'
|
- unless type == 'js'
|
||||||
= render 'bootstrap/alert' do
|
= render 'bootstrap/alert' do
|
||||||
= message
|
= sanitize_markdown message, tags: %w[a strong em]
|
||||||
|
|
4
app/views/posts/attribute_ro/_created_at.haml
Normal file
4
app/views/posts/attribute_ro/_created_at.haml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
%tr{ id: attribute }
|
||||||
|
%th= post_label_t(attribute, post: post)
|
||||||
|
%td{ dir: dir, lang: locale }
|
||||||
|
%time{ datetime: metadata.value.xmlschema }= l metadata.value
|
1
app/views/posts/attributes/_created_at.haml
Normal file
1
app/views/posts/attributes/_created_at.haml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
-# nada
|
|
@ -84,7 +84,10 @@
|
||||||
%button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top')
|
%button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top')
|
||||||
%button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom')
|
%button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom')
|
||||||
|
|
||||||
|
- if @site.pagination
|
||||||
%div
|
%div
|
||||||
|
= link_to_prev_page @posts, t('posts.prev'), class: 'btn'
|
||||||
|
= link_to_next_page @posts, t('posts.next'), class: 'btn'
|
||||||
%tbody
|
%tbody
|
||||||
- dir = @site.data.dig(params[:locale], 'dir')
|
- dir = @site.data.dig(params[:locale], 'dir')
|
||||||
- size = @posts.size
|
- size = @posts.size
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
.invalid-feedback= site.errors.messages[:description].join(', ')
|
.invalid-feedback= site.errors.messages[:description].join(', ')
|
||||||
%hr/
|
%hr/
|
||||||
|
|
||||||
|
- unless site.persisted?
|
||||||
.form-group#design_id
|
.form-group#design_id
|
||||||
%h2= t('.design.title')
|
%h2= t('.design.title')
|
||||||
%p.lead= t('.help.design')
|
%p.lead= t('.help.design')
|
||||||
|
|
|
@ -142,7 +142,7 @@ Rails.application.configure do
|
||||||
}
|
}
|
||||||
config.action_mailer.default_options = { from: ENV.fetch('DEFAULT_FROM', "noreply@sutty.nl") }
|
config.action_mailer.default_options = { from: ENV.fetch('DEFAULT_FROM', "noreply@sutty.nl") }
|
||||||
|
|
||||||
config.middleware.use ExceptionNotification::Rack, gitlab: {}, ignore_exceptions: (['DeployJob::DeployAlreadyRunningException'] + ExceptionNotifier.ignored_exceptions)
|
config.middleware.use ExceptionNotification::Rack, gitlab: {}, ignore_exceptions: ['DeployJob::DeployAlreadyRunningException']
|
||||||
|
|
||||||
Rails.application.routes.default_url_options[:host] = "panel.#{ENV.fetch('SUTTY', 'sutty.nl')}"
|
Rails.application.routes.default_url_options[:host] = "panel.#{ENV.fetch('SUTTY', 'sutty.nl')}"
|
||||||
Rails.application.routes.default_url_options[:protocol] = 'https'
|
Rails.application.routes.default_url_options[:protocol] = 'https'
|
||||||
|
|
|
@ -91,6 +91,15 @@ module Jekyll
|
||||||
spec.name == name
|
spec.name == name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless spec
|
||||||
|
I18n.with_locale(locale) do
|
||||||
|
raise Jekyll::Errors::InvalidThemeName, I18n.t('activerecord.errors.models.site.attributes.design_id.missing_gem', theme: name)
|
||||||
|
rescue Jekyll::Errors::InvalidThemeName => e
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { theme: name, site: File.basename(site.source) })
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
ruby_version = Gem::Version.new(RUBY_VERSION)
|
ruby_version = Gem::Version.new(RUBY_VERSION)
|
||||||
ruby_version.canonical_segments[2] = 0
|
ruby_version.canonical_segments[2] = 0
|
||||||
base_path = Rails.root.join('_storage', 'gems', File.basename(site.source), 'ruby',
|
base_path = Rails.root.join('_storage', 'gems', File.basename(site.source), 'ruby',
|
||||||
|
@ -114,6 +123,11 @@ module Jekyll
|
||||||
private
|
private
|
||||||
|
|
||||||
def gemspec; end
|
def gemspec; end
|
||||||
|
|
||||||
|
# @return [Symbol]
|
||||||
|
def locale
|
||||||
|
@locale ||= (site.config['locale'] || site.config['lang'] || I18n.locale).to_sym
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# No necesitamos los archivos de la plantilla
|
# No necesitamos los archivos de la plantilla
|
||||||
|
|
3
config/initializers/device_detector.rb
Normal file
3
config/initializers/device_detector.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
DeviceDetector.configure do |config|
|
||||||
|
config.max_cache_keys = 5_000 # to check if not too much
|
||||||
|
end
|
|
@ -4,5 +4,5 @@ ActiveJob::Serializers.add_serializers ActiveJob::Serializers::ExceptionSerializ
|
||||||
|
|
||||||
# Notificar los errores
|
# Notificar los errores
|
||||||
Que.error_notifier = proc do |error, job|
|
Que.error_notifier = proc do |error, job|
|
||||||
ExceptionNotifier.notify_exception(error, data: (job || {}))
|
ExceptionNotifier.notify_exception(error, data: (job.dup || {}))
|
||||||
end
|
end
|
||||||
|
|
|
@ -123,6 +123,10 @@ en:
|
||||||
title: Distributed Web
|
title: Distributed Web
|
||||||
success: Success!
|
success: Success!
|
||||||
error: Error
|
error: Error
|
||||||
|
deploy_social_distributed_press:
|
||||||
|
title: Fediverse
|
||||||
|
success: Success!
|
||||||
|
error: Error
|
||||||
deploy_reindex:
|
deploy_reindex:
|
||||||
title: Reindex
|
title: Reindex
|
||||||
success: Success!
|
success: Success!
|
||||||
|
@ -191,9 +195,14 @@ en:
|
||||||
deploys:
|
deploys:
|
||||||
deploy_local_presence: 'We need to be build the site!'
|
deploy_local_presence: 'We need to be build the site!'
|
||||||
design_id:
|
design_id:
|
||||||
|
missing_gem: "Site is configured to use %{theme} theme, but the corresponding gem is missing from Gemfile"
|
||||||
layout_incompatible:
|
layout_incompatible:
|
||||||
error: "Design can't be changed because there are posts with incompatible layouts"
|
error: "Design can't be changed because there are posts with incompatible layouts"
|
||||||
help: "Your site has posts with layouts only compatible with the current design. If you change it, the site won't work as you expect. If you're trying out designs, you can delete posts in the following incompatible layouts:: %{layouts}."
|
help: "Your site has posts with layouts only compatible with the current design. If you change it, the site won't work as you expect. If you're trying out designs, you can delete posts in the following incompatible layouts:: %{layouts}."
|
||||||
|
usuarie:
|
||||||
|
attributes:
|
||||||
|
lang:
|
||||||
|
not_available: "This language is not yet available, would you help us by translating Sutty into it?"
|
||||||
errors:
|
errors:
|
||||||
argument_error: 'Argument `%{argument}` must be an instance of %{class}'
|
argument_error: 'Argument `%{argument}` must be an instance of %{class}'
|
||||||
unknown_locale: 'Unknown %{locale} locale'
|
unknown_locale: 'Unknown %{locale} locale'
|
||||||
|
@ -307,6 +316,14 @@ en:
|
||||||
indefinitely.
|
indefinitely.
|
||||||
|
|
||||||
[Learn more](https://sutty.nl/learn-more-about-publish-to-dweb-functionality/)
|
[Learn more](https://sutty.nl/learn-more-about-publish-to-dweb-functionality/)
|
||||||
|
deploy_social_distributed_press:
|
||||||
|
title: 'Publish on the Fediverse'
|
||||||
|
help: |
|
||||||
|
By using the ActivityPub protocol, people on the Fediverse
|
||||||
|
([Mastodon](https://joinmastodon.org/servers),
|
||||||
|
[Pixelfed](https://pixelfed.social/site/about), and
|
||||||
|
[others](https://fediverse.party/)) can follow your site,
|
||||||
|
receive news and interact with them.
|
||||||
stats:
|
stats:
|
||||||
index:
|
index:
|
||||||
title: Statistics
|
title: Statistics
|
||||||
|
@ -407,6 +424,8 @@ en:
|
||||||
title: 'Edit %{site}'
|
title: 'Edit %{site}'
|
||||||
submit: 'Save changes'
|
submit: 'Save changes'
|
||||||
btn: 'Configuration'
|
btn: 'Configuration'
|
||||||
|
update:
|
||||||
|
post: "Your changes have been saved. **If you enabled a publication method, don't forget to publish changes.**"
|
||||||
form:
|
form:
|
||||||
errors:
|
errors:
|
||||||
title: There were errors and we couldn't save your changes :(
|
title: There were errors and we couldn't save your changes :(
|
||||||
|
@ -415,7 +434,7 @@ en:
|
||||||
name: "This will be the host name for your site, ie. **example**.sutty.nl. Choose an expression up to 63 characters. It can contain only lowercase letters, numbers and dashes, **and no spaces**. It can't start or end with a dash, or be entirely composed of numbers."
|
name: "This will be the host name for your site, ie. **example**.sutty.nl. Choose an expression up to 63 characters. It can contain only lowercase letters, numbers and dashes, **and no spaces**. It can't start or end with a dash, or be entirely composed of numbers."
|
||||||
title: 'The title can be anything you want'
|
title: 'The title can be anything you want'
|
||||||
description: 'You site description that appears in search engines. Between 50 and 160 characters.'
|
description: 'You site description that appears in search engines. Between 50 and 160 characters.'
|
||||||
design: 'Select the design for your site. You can change it later. We add more designs from time to time!'
|
design: 'Select the design for your site. We add more designs from time to time!'
|
||||||
licencia: 'Everything we publish has automatic copyright. This
|
licencia: 'Everything we publish has automatic copyright. This
|
||||||
means nobody can use our works without explicit permission. By
|
means nobody can use our works without explicit permission. By
|
||||||
using licenses, we stablish conditions by which we want to share
|
using licenses, we stablish conditions by which we want to share
|
||||||
|
@ -466,6 +485,9 @@ en:
|
||||||
success: 'Site upgrade has been completed. Your next build will run this upgrade :)'
|
success: 'Site upgrade has been completed. Your next build will run this upgrade :)'
|
||||||
error: "There was an error when trying to upgrade your site. This could be due to conflicts that couldn't be solved automatically. A report of the issue has already been sent to our admins. Sorry for the inconvenience! :("
|
error: "There was an error when trying to upgrade your site. This could be due to conflicts that couldn't be solved automatically. A report of the issue has already been sent to our admins. Sorry for the inconvenience! :("
|
||||||
message: 'Skeleton upgrade'
|
message: 'Skeleton upgrade'
|
||||||
|
webhooks:
|
||||||
|
pull:
|
||||||
|
message: 'Webhooks pull'
|
||||||
footer:
|
footer:
|
||||||
powered_by: 'is developed by'
|
powered_by: 'is developed by'
|
||||||
i18n:
|
i18n:
|
||||||
|
@ -512,6 +534,8 @@ en:
|
||||||
feedback: 'This field cannot be empty!'
|
feedback: 'This field cannot be empty!'
|
||||||
uuid:
|
uuid:
|
||||||
label: 'Unique identifier'
|
label: 'Unique identifier'
|
||||||
|
created_at:
|
||||||
|
label: 'Created at'
|
||||||
geo:
|
geo:
|
||||||
uri: 'Open in app'
|
uri: 'Open in app'
|
||||||
osm: 'Open in web map'
|
osm: 'Open in web map'
|
||||||
|
@ -685,7 +709,7 @@ en:
|
||||||
new: 'Create'
|
new: 'Create'
|
||||||
edit: 'Configure'
|
edit: 'Configure'
|
||||||
posts:
|
posts:
|
||||||
new: 'New %{layout}'
|
new: 'Add %{layout}'
|
||||||
edit: 'Editing'
|
edit: 'Editing'
|
||||||
usuaries:
|
usuaries:
|
||||||
index: 'Users'
|
index: 'Users'
|
||||||
|
|
|
@ -123,6 +123,10 @@ es:
|
||||||
title: Web distribuida
|
title: Web distribuida
|
||||||
success: ¡Éxito!
|
success: ¡Éxito!
|
||||||
error: Hubo un error
|
error: Hubo un error
|
||||||
|
deploy_social_distributed_press:
|
||||||
|
title: Fediverso
|
||||||
|
success: ¡Éxito!
|
||||||
|
error: Hubo un error
|
||||||
deploy_reindex:
|
deploy_reindex:
|
||||||
title: Reindexación
|
title: Reindexación
|
||||||
success: ¡Éxito!
|
success: ¡Éxito!
|
||||||
|
@ -191,9 +195,14 @@ es:
|
||||||
deploys:
|
deploys:
|
||||||
deploy_local_presence: '¡Necesitamos poder generar el sitio!'
|
deploy_local_presence: '¡Necesitamos poder generar el sitio!'
|
||||||
design_id:
|
design_id:
|
||||||
|
missing_gem: "El sitio usa la plantilla %{theme} pero la gema correspondiente no se encuentra en el Gemfile"
|
||||||
layout_incompatible:
|
layout_incompatible:
|
||||||
error: 'No se puede cambiar la plantilla porque hay artículos con formatos incompatibles'
|
error: 'No se puede cambiar la plantilla porque hay artículos con formatos incompatibles'
|
||||||
help: 'En tu sitio hay artículos que solo son compatibles con el diseño actual, si cambias la plantilla el sitio no funcionará como esperas. Si estás probando plantillas, puedes eliminar los artículos en los formatos incompatibles: %{layouts}.'
|
help: 'En tu sitio hay artículos que solo son compatibles con el diseño actual, si cambias la plantilla el sitio no funcionará como esperas. Si estás probando plantillas, puedes eliminar los artículos en los formatos incompatibles: %{layouts}.'
|
||||||
|
usuarie:
|
||||||
|
attributes:
|
||||||
|
lang:
|
||||||
|
not_available: "Este idioma todavía no está disponible, ¿nos ayudas a agregarlo y mantenerlo?"
|
||||||
errors:
|
errors:
|
||||||
argument_error: 'El argumento `%{argument}` debe ser una instancia de %{class}'
|
argument_error: 'El argumento `%{argument}` debe ser una instancia de %{class}'
|
||||||
unknown_locale: 'El idioma %{locale} es desconocido'
|
unknown_locale: 'El idioma %{locale} es desconocido'
|
||||||
|
@ -312,6 +321,14 @@ es:
|
||||||
copias de tu contenido indefinidamente.
|
copias de tu contenido indefinidamente.
|
||||||
|
|
||||||
[Saber más](https://sutty.nl/saber-mas-sobre-publicar-a-la-web-distribuida/)
|
[Saber más](https://sutty.nl/saber-mas-sobre-publicar-a-la-web-distribuida/)
|
||||||
|
deploy_social_distributed_press:
|
||||||
|
title: 'Publicar al Fediverso'
|
||||||
|
help: |
|
||||||
|
Utilizando el protocolo ActivityPub, otras personas en el
|
||||||
|
Fediverso ([Mastodon](https://joinmastodon.org/servers),
|
||||||
|
[Pixelfed](https://pixelfed.social/site/about) y
|
||||||
|
[otros](https://fediverse.party/)) pueden seguir a tu sitio,
|
||||||
|
recibir novedades e interactuar con ellas.
|
||||||
stats:
|
stats:
|
||||||
index:
|
index:
|
||||||
title: Estadísticas
|
title: Estadísticas
|
||||||
|
@ -413,6 +430,8 @@ es:
|
||||||
title: 'Editar %{site}'
|
title: 'Editar %{site}'
|
||||||
submit: 'Guardar cambios'
|
submit: 'Guardar cambios'
|
||||||
btn: 'Configuración'
|
btn: 'Configuración'
|
||||||
|
update:
|
||||||
|
post: "Tus cambios han sido guardados. **Si agregaste un método de publicación, no te olvides de publicar cambios.**"
|
||||||
form:
|
form:
|
||||||
errors:
|
errors:
|
||||||
title: Hubo errores y no pudimos guardar tus cambios :(
|
title: Hubo errores y no pudimos guardar tus cambios :(
|
||||||
|
@ -421,7 +440,7 @@ es:
|
||||||
name: 'El nombre de tu sitio que formará parte de la dirección (**ejemplo**.sutty.nl). Solo puede contener hasta 63 letras minúsculas, números y guiones, pero **sin espacios**. No puede empezar ni terminar con guión, ni estar compuesto enteramente por números.'
|
name: 'El nombre de tu sitio que formará parte de la dirección (**ejemplo**.sutty.nl). Solo puede contener hasta 63 letras minúsculas, números y guiones, pero **sin espacios**. No puede empezar ni terminar con guión, ni estar compuesto enteramente por números.'
|
||||||
title: 'El título de tu sitio puede ser lo que quieras.'
|
title: 'El título de tu sitio puede ser lo que quieras.'
|
||||||
description: 'La descripción del sitio, que saldrá en buscadores. Entre 50 y 160 caracteres.'
|
description: 'La descripción del sitio, que saldrá en buscadores. Entre 50 y 160 caracteres.'
|
||||||
design: 'Elegí el diseño que va a tener tu sitio aquí. Podés cambiarlo luego. De tanto en tanto vamos sumando diseños nuevos.'
|
design: 'Elegí el diseño que va a tener tu sitio aquí. De tanto en tanto vamos sumando diseños nuevos.'
|
||||||
licencia: 'Todo lo que publicamos posee automáticamente derechos
|
licencia: 'Todo lo que publicamos posee automáticamente derechos
|
||||||
de autore. Esto significa que nadie puede hacer uso de nuestras
|
de autore. Esto significa que nadie puede hacer uso de nuestras
|
||||||
obras sin permiso explícito. Con las licencias establecemos
|
obras sin permiso explícito. Con las licencias establecemos
|
||||||
|
@ -474,6 +493,9 @@ es:
|
||||||
success: 'Ya se incorporaron los cambios en el sitio, se aplicarán en la próxima compilación que hagas :)'
|
success: 'Ya se incorporaron los cambios en el sitio, se aplicarán en la próxima compilación que hagas :)'
|
||||||
error: 'Hubo un error al incorporar los cambios en el sitio. Esto puede deberse a conflictos entre cambios que no se pueden resolver automáticamente. Hemos enviado un reporte del problema a les administradores de Sutty para que estén al tanto de la situación. ¡Lo sentimos! :('
|
error: 'Hubo un error al incorporar los cambios en el sitio. Esto puede deberse a conflictos entre cambios que no se pueden resolver automáticamente. Hemos enviado un reporte del problema a les administradores de Sutty para que estén al tanto de la situación. ¡Lo sentimos! :('
|
||||||
message: 'Actualización del esqueleto'
|
message: 'Actualización del esqueleto'
|
||||||
|
webhooks:
|
||||||
|
pull:
|
||||||
|
message: 'Traer los cambios a partir de un evento remoto'
|
||||||
footer:
|
footer:
|
||||||
powered_by: 'es desarrollada por'
|
powered_by: 'es desarrollada por'
|
||||||
i18n:
|
i18n:
|
||||||
|
@ -520,6 +542,8 @@ es:
|
||||||
feedback: '¡Este campo no puede estar vacío!'
|
feedback: '¡Este campo no puede estar vacío!'
|
||||||
uuid:
|
uuid:
|
||||||
label: 'Identificador único'
|
label: 'Identificador único'
|
||||||
|
created_at:
|
||||||
|
label: 'Fecha de creación'
|
||||||
geo:
|
geo:
|
||||||
uri: 'Abrir en aplicación'
|
uri: 'Abrir en aplicación'
|
||||||
osm: 'Abrir en mapa web'
|
osm: 'Abrir en mapa web'
|
||||||
|
@ -693,7 +717,7 @@ es:
|
||||||
new: 'Crear'
|
new: 'Crear'
|
||||||
edit: 'Configurar'
|
edit: 'Configurar'
|
||||||
posts:
|
posts:
|
||||||
new: 'Nuevo %{layout}'
|
new: 'Agregar %{layout}'
|
||||||
edit: 'Editando'
|
edit: 'Editando'
|
||||||
usuaries:
|
usuaries:
|
||||||
index: 'Usuaries'
|
index: 'Usuaries'
|
||||||
|
|
|
@ -17,6 +17,8 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
get :'contact/cookie', to: 'invitades#contact_cookie'
|
get :'contact/cookie', to: 'invitades#contact_cookie'
|
||||||
post :'contact/:form', to: 'contact#receive', as: :contact
|
post :'contact/:form', to: 'contact#receive', as: :contact
|
||||||
|
|
||||||
|
post :'webhooks/pull', to: 'webhooks#pull'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
8
db/migrate/20230519143500_add_pagination_to_site.rb
Normal file
8
db/migrate/20230519143500_add_pagination_to_site.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Agrega la opción de paginación a los sitios
|
||||||
|
class AddPaginationToSite < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :sites, :pagination, :boolean, default: false
|
||||||
|
end
|
||||||
|
end
|
12
db/migrate/20230731195050_add_token_to_roles.rb
Normal file
12
db/migrate/20230731195050_add_token_to_roles.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class AddTokenToRoles < ActiveRecord::Migration[6.1]
|
||||||
|
def up
|
||||||
|
add_column :roles, :token, :string
|
||||||
|
Rol.find_each do |m|
|
||||||
|
m.update_column( :token, SecureRandom.hex(64) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :roles, :token
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Almacena las llaves privadas de cada sitio
|
||||||
|
class AddPrivateKeyPemCiphertextToSites < ActiveRecord::Migration[6.1]
|
||||||
|
# Agrega la columna cifrada
|
||||||
|
def change
|
||||||
|
add_column :sites, :private_key_pem_ciphertext, :text
|
||||||
|
end
|
||||||
|
end
|
20
db/migrate/20230921155401_site_rename_origin_to_upstream.rb
Normal file
20
db/migrate/20230921155401_site_rename_origin_to_upstream.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Renombrar todos los repositorios que apunten a skel como su origin
|
||||||
|
class SiteRenameOriginToUpstream < ActiveRecord::Migration[6.1]
|
||||||
|
# Renombrar
|
||||||
|
def up
|
||||||
|
Site.find_each do |site|
|
||||||
|
next unless site.repository.origin&.url == ENV['SKEL_SUTTY']
|
||||||
|
|
||||||
|
site.repository.rugged.remotes.rename('origin', 'upstream') do |_|
|
||||||
|
Rails.logger.info "#{site.name}: renamed origin to upstream"
|
||||||
|
end
|
||||||
|
rescue Rugged::Error, Rugged::OSError => e
|
||||||
|
Rails.logger.warn "#{site.name}: #{e.message}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# No se puede deshacer
|
||||||
|
def down; end
|
||||||
|
end
|
16
db/seeds.rb
16
db/seeds.rb
|
@ -16,12 +16,14 @@ licencias.each do |l|
|
||||||
licencia.update l
|
licencia.update l
|
||||||
end
|
end
|
||||||
|
|
||||||
unless Rails.env.test?
|
if CodeOfConduct.count.zero?
|
||||||
YAML.safe_load(File.read('db/seeds/sites.yml')).each do |site|
|
YAML.safe_load(File.read('db/seeds/codes_of_conduct.yml')).each do |coc|
|
||||||
site = Site.find_or_create_by name: site['name']
|
CodeOfConduct.new(**coc).save!
|
||||||
|
end
|
||||||
site.update licencia: Licencia.first, design: Design.first,
|
end
|
||||||
title: site.name, description: 'x' * 50,
|
|
||||||
deploys: site.deploys.empty? ? [DeployLocal.new] : site.deploys
|
if PrivacyPolicy.count.zero?
|
||||||
|
YAML.safe_load(File.read('db/seeds/privacy_policies.yml')).each do |pp|
|
||||||
|
PrivacyPolicy.new(**pp).save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
- name_en: 'Minima'
|
- name_en: 'Minima'
|
||||||
name_es: 'Mínima'
|
name_es: 'Mínima'
|
||||||
gem: 'sutty-minima'
|
gem: 'sutty-minima'
|
||||||
url: 'https://0xacab.org/sutty/jekyll/minima'
|
url: 'https://minima.sutty.nl/'
|
||||||
description_en: "Sutty Minima is based on [Minima](https://jekyll.github.io/minima/), a blog-focused theme for Jekyll."
|
description_en: "Sutty Minima is based on [Minima](https://jekyll.github.io/minima/), a blog-focused theme for Jekyll."
|
||||||
description_es: 'Sutty Mínima es una plantilla para blogs basada en [Mínima](https://jekyll.github.io/minima/).'
|
description_es: 'Sutty Mínima es una plantilla para blogs basada en [Mínima](https://jekyll.github.io/minima/).'
|
||||||
license: 'https://0xacab.org/sutty/jekyll/minima/-/blob/master/LICENSE.txt'
|
license: 'https://0xacab.org/sutty/jekyll/minima/-/blob/master/LICENSE.txt'
|
||||||
|
@ -75,6 +75,14 @@
|
||||||
credits_en: 'This template was made in collaboration with Librenauta in 15 hours!'
|
credits_en: 'This template was made in collaboration with Librenauta in 15 hours!'
|
||||||
designer_url: 'https://copiona.com/donaunbit/'
|
designer_url: 'https://copiona.com/donaunbit/'
|
||||||
priority: '70'
|
priority: '70'
|
||||||
|
- name_en: 'Magazine'
|
||||||
|
name_es: 'Revista'
|
||||||
|
gem: 'compost-jekyll-theme'
|
||||||
|
url: 'https://two.compost.digital/'
|
||||||
|
description_en: 'A theme to create multimedia publications, based in COMPOST magazine'
|
||||||
|
description_es: 'Plantilla para crear publicaciones multimedia, basada en COMPOST magazine'
|
||||||
|
license: 'https://0xacab.org/sutty/jekyll/compost-jekyll-theme/-/blob/no-masters/LICENSE.txt'
|
||||||
|
priority: '40'
|
||||||
- name_en: 'Resource toolkit'
|
- name_en: 'Resource toolkit'
|
||||||
name_es: 'Recursero'
|
name_es: 'Recursero'
|
||||||
gem: 'recursero-jekyll-theme'
|
gem: 'recursero-jekyll-theme'
|
||||||
|
|
BIN
public/assets/.sprockets-manifest-c6294bb290dcb7473076f4de99ce9c00.json
(Stored with Git LFS)
Normal file
BIN
public/assets/.sprockets-manifest-c6294bb290dcb7473076f4de99ce9c00.json
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/.sprockets-manifest-c6294bb290dcb7473076f4de99ce9c00.json.br
(Stored with Git LFS)
Normal file
BIN
public/assets/.sprockets-manifest-c6294bb290dcb7473076f4de99ce9c00.json.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js
(Stored with Git LFS)
Normal file
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js.br
(Stored with Git LFS)
Normal file
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/activestorage-9f749d32771691cb3104d21c1c9926e52c04c48d8730498df4aaa39b0adfb7ba.js.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css
(Stored with Git LFS)
Normal file
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css.br
(Stored with Git LFS)
Normal file
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/application-dc5234b33b6c06db79ab79114f5b85952f35482ce5b97061ce9402b2a8a4cd19.css.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg
(Stored with Git LFS)
Normal file
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg.br
(Stored with Git LFS)
Normal file
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/arrows-alt-v-89a34626be855d3b1c3199cd75f62cf6327678eed1e126f74b7cbc6de3502606.svg.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-59c73da0ca1f2fd8dd42765f0a172ae513546920ad9fa0718c15d9b10a4f18dd.css.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/application-f14294068656a14630709493ca1bdd375b16209db5d3307d61c4927dd3eff3c5.js.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/favicon-ccead91b8853543a3542af03c7dde9963359b1c0b9b725220a7f193e1324ecd8.png
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/favicon-ccead91b8853543a3542af03c7dde9963359b1c0b9b725220a7f193e1324ecd8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/favicon-ccead91b8853543a3542af03c7dde9963359b1c0b9b725220a7f193e1324ecd8.png.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/favicon-ccead91b8853543a3542af03c7dde9963359b1c0b9b725220a7f193e1324ecd8.png.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-0703369a358a012c0011843ae337a8a20270c336948a8668df5cb89a8827299b.woff
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-0703369a358a012c0011843ae337a8a20270c336948a8668df5cb89a8827299b.woff
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-0703369a358a012c0011843ae337a8a20270c336948a8668df5cb89a8827299b.woff.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-0703369a358a012c0011843ae337a8a20270c336948a8668df5cb89a8827299b.woff.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-0805fb1fe24235f70a639f67514990e4bfb6d2cfb00ca563ad4b553c240ddc33.eot.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-22d0c88a49d7d0ebe45627143a601061a32a46a9b9afd2dc7f457436f5f15f6e.svg.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-403acfcf0cbaebd1c28b404eec442cea53642644b3a73f91c5a4ab46859af772.woff2
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-403acfcf0cbaebd1c28b404eec442cea53642644b3a73f91c5a4ab46859af772.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-403acfcf0cbaebd1c28b404eec442cea53642644b3a73f91c5a4ab46859af772.woff2.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-403acfcf0cbaebd1c28b404eec442cea53642644b3a73f91c5a4ab46859af772.woff2.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf.br
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/blazer/glyphicons-halflings-regular-7c9caa5f4e16169b0129fdf93c84e85ad14d6c107eb1b0ad60b542daf01ee1f0.ttf.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css
(Stored with Git LFS)
Normal file
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css.br
(Stored with Git LFS)
Normal file
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/editor-6ceecb9d2dc47b39b99575e60bc2c9eec573a495812d521ec5b82dedd4f55807.css.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css
(Stored with Git LFS)
Normal file
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css.br
(Stored with Git LFS)
Normal file
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css.br
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css.gz
(Stored with Git LFS)
Normal file
BIN
public/assets/fonts-86ce817a6287b9ff301be232f102b66152dd83f264e13a531098d8dc8b1398da.css.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
public/assets/icon_external_link-1af8262ac9c00df26e81bc5a33bcf64350729f954b85f82d5e759fffec4e183a.png
(Stored with Git LFS)
Normal file
BIN
public/assets/icon_external_link-1af8262ac9c00df26e81bc5a33bcf64350729f954b85f82d5e759fffec4e183a.png
(Stored with Git LFS)
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue