diff --git a/Gemfile b/Gemfile index 6becfaf42..e3537bce2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source "https://rubygems.org" -gem "rails", "5.2.8.1" +gem "rails", "6.0.5.1" gem "acts-as-taggable-on", "~> 8.1.0" gem "acts_as_votable", "~> 0.13.1" @@ -28,6 +28,7 @@ gem "globalize-accessors", "~> 0.3.0" gem "graphiql-rails", "~> 1.7.0" gem "graphql", "~> 1.12.14" gem "groupdate", "~> 5.2.2" +gem "image_processing", "~> 1.12.2" gem "initialjs-rails", "~> 0.2.0.9" gem "invisible_captcha", "~> 2.0.0" gem "jquery-fileupload-rails" @@ -112,7 +113,7 @@ group :development do gem "rubocop-rspec", "~> 2.4.0", require: false gem "rvm1-capistrano3", "~> 1.4.0", require: false gem "scss_lint", "~> 0.59.0", require: false - gem "web-console", "~> 3.7.0" + gem "web-console", "~> 4.0.4" end eval_gemfile "./Gemfile_custom" diff --git a/Gemfile.lock b/Gemfile.lock index bfc8bd2ac..ee0c8f765 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,47 +2,61 @@ GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: - actioncable (5.2.8.1) - actionpack (= 5.2.8.1) + actioncable (6.0.5.1) + actionpack (= 6.0.5.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.8.1) - actionpack (= 5.2.8.1) - actionview (= 5.2.8.1) - activejob (= 5.2.8.1) + actionmailbox (6.0.5.1) + actionpack (= 6.0.5.1) + activejob (= 6.0.5.1) + activerecord (= 6.0.5.1) + activestorage (= 6.0.5.1) + activesupport (= 6.0.5.1) + mail (>= 2.7.1) + actionmailer (6.0.5.1) + actionpack (= 6.0.5.1) + actionview (= 6.0.5.1) + activejob (= 6.0.5.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.8.1) - actionview (= 5.2.8.1) - activesupport (= 5.2.8.1) + actionpack (6.0.5.1) + actionview (= 6.0.5.1) + activesupport (= 6.0.5.1) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.8.1) - activesupport (= 5.2.8.1) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.0.5.1) + actionpack (= 6.0.5.1) + activerecord (= 6.0.5.1) + activestorage (= 6.0.5.1) + activesupport (= 6.0.5.1) + nokogiri (>= 1.8.5) + actionview (6.0.5.1) + activesupport (= 6.0.5.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.8.1) - activesupport (= 5.2.8.1) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.0.5.1) + activesupport (= 6.0.5.1) globalid (>= 0.3.6) - activemodel (5.2.8.1) - activesupport (= 5.2.8.1) - activerecord (5.2.8.1) - activemodel (= 5.2.8.1) - activesupport (= 5.2.8.1) - arel (>= 9.0) - activestorage (5.2.8.1) - actionpack (= 5.2.8.1) - activerecord (= 5.2.8.1) - marcel (~> 1.0.0) - activesupport (5.2.8.1) + activemodel (6.0.5.1) + activesupport (= 6.0.5.1) + activerecord (6.0.5.1) + activemodel (= 6.0.5.1) + activesupport (= 6.0.5.1) + activestorage (6.0.5.1) + actionpack (= 6.0.5.1) + activejob (= 6.0.5.1) + activerecord (= 6.0.5.1) + marcel (~> 1.0) + activesupport (6.0.5.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) acts-as-taggable-on (8.1.0) activerecord (>= 5.0, < 6.2) acts_as_votable (0.13.1) @@ -64,7 +78,6 @@ GEM nokogiri ancestry (4.1.0) activerecord (>= 5.2.6) - arel (9.0.0) ast (2.4.2) audited (5.0.1) activerecord (>= 5.0, < 6.2) @@ -145,7 +158,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) coveralls (0.8.23) json (>= 1.8, < 3) simplecov (~> 0.16.1) @@ -276,7 +289,7 @@ GEM gitlab (4.17.0) httparty (~> 0.18) terminal-table (~> 1.5, >= 1.5.1) - globalid (0.5.2) + globalid (1.0.0) activesupport (>= 5.0) globalize (6.0.1) activemodel (>= 4.2, < 7.0) @@ -315,6 +328,9 @@ GEM rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) ice_nine (0.11.2) + image_processing (1.12.2) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.17, < 3) initialjs-rails (0.2.0.9) railties (>= 3.1, < 7.0) invisible_captcha (2.0.0) @@ -469,18 +485,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.8.1) - actioncable (= 5.2.8.1) - actionmailer (= 5.2.8.1) - actionpack (= 5.2.8.1) - actionview (= 5.2.8.1) - activejob (= 5.2.8.1) - activemodel (= 5.2.8.1) - activerecord (= 5.2.8.1) - activestorage (= 5.2.8.1) - activesupport (= 5.2.8.1) + rails (6.0.5.1) + actioncable (= 6.0.5.1) + actionmailbox (= 6.0.5.1) + actionmailer (= 6.0.5.1) + actionpack (= 6.0.5.1) + actiontext (= 6.0.5.1) + actionview (= 6.0.5.1) + activejob (= 6.0.5.1) + activemodel (= 6.0.5.1) + activerecord (= 6.0.5.1) + activestorage (= 6.0.5.1) + activesupport (= 6.0.5.1) bundler (>= 1.3.0) - railties (= 5.2.8.1) + railties (= 6.0.5.1) sprockets-rails (>= 2.0.0) rails-assets-leaflet (1.5.1) rails-assets-markdown-it (9.0.1) @@ -489,15 +507,15 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.4.3) loofah (~> 2.3) - rails-i18n (5.1.3) + rails-i18n (6.0.0) i18n (>= 0.7, < 2) - railties (>= 5.0, < 6) - railties (5.2.8.1) - actionpack (= 5.2.8.1) - activesupport (= 5.2.8.1) + railties (>= 6.0.0, < 7) + railties (6.0.5.1) + actionpack (= 6.0.5.1) + activesupport (= 6.0.5.1) method_source rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) + thor (>= 0.20.3, < 2.0) rainbow (3.0.0) rake (13.0.6) rb-fsevent (0.10.4) @@ -555,6 +573,8 @@ GEM rubocop (~> 1.0) rubocop-ast (>= 1.1.0) ruby-progressbar (1.11.0) + ruby-vips (2.1.4) + ffi (~> 1.12) ruby2_keywords (0.0.5) rubyzip (2.3.2) rugged (1.0.1) @@ -627,7 +647,7 @@ GEM unicode-display_width (~> 1.1, >= 1.1.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) - thor (1.1.0) + thor (1.2.1) thread_safe (0.3.6) tilt (2.0.10) tins (1.25.0) @@ -660,11 +680,11 @@ GEM addressable httpi (~> 2.0) nokogiri (>= 1.4.2) - web-console (3.7.0) - actionview (>= 5.0) - activemodel (>= 5.0) + web-console (4.0.4) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) bindex (>= 0.4.0) - railties (>= 5.0) + railties (>= 6.0.0) webdrivers (4.6.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) @@ -680,6 +700,7 @@ GEM wkhtmltopdf-binary (0.12.6.5) xpath (3.2.0) nokogiri (~> 1.8) + zeitwerk (2.6.0) PLATFORMS ruby @@ -728,6 +749,7 @@ DEPENDENCIES graphql (~> 1.12.14) groupdate (~> 5.2.2) i18n-tasks (~> 0.9.34) + image_processing (~> 1.12.2) initialjs-rails (~> 0.2.0.9) invisible_captcha (~> 2.0.0) jquery-fileupload-rails @@ -753,7 +775,7 @@ DEPENDENCIES pronto-rubocop (~> 0.11.1) pronto-scss (~> 0.11.0) puma (~> 4.3.12) - rails (= 5.2.8.1) + rails (= 6.0.5.1) rails-assets-leaflet! rails-assets-markdown-it (~> 9.0.1)! recipient_interceptor (~> 0.3.0) @@ -781,7 +803,7 @@ DEPENDENCIES uglifier (~> 4.2.0) uuidtools (~> 2.1.5) view_component (~> 2.49.1) - web-console (~> 3.7.0) + web-console (~> 4.0.4) webdrivers (~> 4.6.0) whenever (~> 1.0.0) wicked_pdf (~> 2.1.0) diff --git a/app/components/admin/menu_component.html.erb b/app/components/admin/menu_component.html.erb index 40e501dc5..750ee18ec 100644 --- a/app/components/admin/menu_component.html.erb +++ b/app/components/admin/menu_component.html.erb @@ -22,7 +22,7 @@ <% end %> <% if feature?(:legislation) %> -
  • "> +
  • "> <%= link_to t("admin.menu.legislation"), admin_legislation_processes_path, class: "legislation-link" %>
  • <% end %> @@ -69,7 +69,7 @@ banners_link, information_texts_link, documents_link, - class: ("is-active" if customization? && controller.class.parent != Admin::Poll::Questions::Answers) + class: ("is-active" if customization? && controller.class.module_parent != Admin::Poll::Questions::Answers) ) %> diff --git a/app/components/admin/menu_component.rb b/app/components/admin/menu_component.rb index 15e15f2b1..4ef5d262f 100644 --- a/app/components/admin/menu_component.rb +++ b/app/components/admin/menu_component.rb @@ -4,7 +4,7 @@ class Admin::MenuComponent < ApplicationComponent private def moderated_content? - moderated_sections.include?(controller_name) && controller.class.parent != Admin::Legislation + moderated_sections.include?(controller_name) && controller.class.module_parent != Admin::Legislation end def moderated_sections @@ -17,7 +17,7 @@ class Admin::MenuComponent < ApplicationComponent end def polls? - controller.class.parent == Admin::Poll::Questions::Answers || + controller.class.module_parent == Admin::Poll::Questions::Answers || %w[polls active_polls recounts results questions answers].include?(controller_name) && action_name != "booth_assignments" end @@ -35,7 +35,7 @@ class Admin::MenuComponent < ApplicationComponent controllers_names = ["settings", "tags", "geozones", "images", "content_blocks", "local_census_records", "imports"] controllers_names.include?(controller_name) && - controller.class.parent != Admin::Poll::Questions::Answers + controller.class.module_parent != Admin::Poll::Questions::Answers end def customization? @@ -57,7 +57,7 @@ class Admin::MenuComponent < ApplicationComponent def local_census_records? controller_name == "local_census_records" || - (controller_name == "imports" && controller.class.parent == Admin::LocalCensusRecords) + (controller_name == "imports" && controller.class.module_parent == Admin::LocalCensusRecords) end def messages_menu_active? @@ -69,11 +69,11 @@ class Admin::MenuComponent < ApplicationComponent end def sdg_managers? - controller_name == "managers" && controller.class.parent == Admin::SDG + controller_name == "managers" && controller.class.module_parent == Admin::SDG end def managers? - controller_name == "managers" && controller.class.parent == Admin + controller_name == "managers" && controller.class.module_parent == Admin end def officers_link @@ -320,7 +320,7 @@ class Admin::MenuComponent < ApplicationComponent [ t("admin.menu.site_customization.images"), admin_site_customization_images_path, - controller_name == "images" && controller.class.parent != Admin::Poll::Questions::Answers + controller_name == "images" && controller.class.module_parent != Admin::Poll::Questions::Answers ] end diff --git a/app/components/admin/poll/officers/officers_component.html.erb b/app/components/admin/poll/officers/officers_component.html.erb index f35ae2793..54784ebaf 100644 --- a/app/components/admin/poll/officers/officers_component.html.erb +++ b/app/components/admin/poll/officers/officers_component.html.erb @@ -1,4 +1,4 @@ -<%= tag.table options do %> +<%= tag.table(**options) do %> <%= t("admin.poll_officers.officer.name") %> diff --git a/app/components/admin/stats/stat_component.html.erb b/app/components/admin/stats/stat_component.html.erb index 684b016a3..fa5b95999 100644 --- a/app/components/admin/stats/stat_component.html.erb +++ b/app/components/admin/stats/stat_component.html.erb @@ -1,5 +1,5 @@
    - <%= tag.p(options) do %> + <%= tag.p(**options) do %> <%= text %>
    <%= amount %> <% end %>
    diff --git a/app/components/shared/link_list_component.html.erb b/app/components/shared/link_list_component.html.erb index 86239013b..dc001156e 100644 --- a/app/components/shared/link_list_component.html.erb +++ b/app/components/shared/link_list_component.html.erb @@ -1 +1 @@ -<%= tag.ul(options) { safe_join(list_items, "\n") } %> +<%= tag.ul(**options) { safe_join(list_items, "\n") } %> diff --git a/app/components/shared/link_list_component.rb b/app/components/shared/link_list_component.rb index 683bc80db..3a9a21b68 100644 --- a/app/components/shared/link_list_component.rb +++ b/app/components/shared/link_list_component.rb @@ -18,7 +18,7 @@ class Shared::LinkListComponent < ApplicationComponent def list_items present_links.map do |text, url, current = false, **link_options| - tag.li(({ "aria-current": true } if current)) do + tag.li("aria-current": (true if current)) do if url link_to text, url, link_options else diff --git a/app/helpers/stats_helper.rb b/app/helpers/stats_helper.rb index 867cab161..acc79319b 100644 --- a/app/helpers/stats_helper.rb +++ b/app/helpers/stats_helper.rb @@ -2,7 +2,7 @@ module StatsHelper def chart_tag(opt = {}) opt[:data] ||= {} opt[:data][:graph] = admin_api_stats_path(chart_data(opt)) - tag.div opt + tag.div(**opt) end def chart_data(opt = {}) @@ -26,7 +26,7 @@ module StatsHelper def budget_investments_chart_tag(opt = {}) opt[:data] ||= {} opt[:data][:graph] = admin_api_stats_path(budget_investments: true) - tag.div opt + tag.div(**opt) end def number_to_stats_percentage(number, options = {}) diff --git a/app/helpers/translatable_form_helper.rb b/app/helpers/translatable_form_helper.rb index fea9b04ef..6e73433c9 100644 --- a/app/helpers/translatable_form_helper.rb +++ b/app/helpers/translatable_form_helper.rb @@ -8,7 +8,7 @@ module TranslatableFormHelper end def backend_translations_enabled? - (controller.class.parents & [Admin, Management, Valuation, SDGManagement]).any? + (controller.class.module_parents & [Admin, Management, Valuation, SDGManagement]).any? end def highlight_translation_html_class @@ -32,7 +32,7 @@ module TranslatableFormHelper def fields_for_locale(locale) fields_for_translation(@translations[locale]) do |translations_form| - @template.tag.div translations_options(translations_form.object, locale) do + @template.tag.div **translations_options(translations_form.object, locale) do @template.concat translations_form.hidden_field( :_destroy, value: !@template.enabled_locale?(translations_form.object.globalized_model, locale), diff --git a/app/models/concerns/attachable.rb b/app/models/concerns/attachable.rb index ac6c1e33a..cc457f934 100644 --- a/app/models/concerns/attachable.rb +++ b/app/models/concerns/attachable.rb @@ -1,9 +1,8 @@ module Attachable - include HasAttachment extend ActiveSupport::Concern included do - has_attachment :attachment + has_one_attached :attachment attr_accessor :cached_attachment validate :attachment_presence diff --git a/app/models/concerns/has_attachment.rb b/app/models/concerns/has_attachment.rb deleted file mode 100644 index 2ffbd931b..000000000 --- a/app/models/concerns/has_attachment.rb +++ /dev/null @@ -1,17 +0,0 @@ -module HasAttachment - extend ActiveSupport::Concern - - class_methods do - def has_attachment(attribute) - has_one_attached attribute - - define_method :"#{attribute}=" do |file| - if file.nil? - send(attribute).detach - else - send(attribute).attach(file) - end - end - end - end -end diff --git a/app/models/direct_upload.rb b/app/models/direct_upload.rb index cd562ca07..6d6eb7470 100644 --- a/app/models/direct_upload.rb +++ b/app/models/direct_upload.rb @@ -35,6 +35,7 @@ class DirectUpload def save_attachment @relation.attachment.blob.save! + @relation.attachment_changes["attachment"].upload end def persisted? diff --git a/app/models/image.rb b/app/models/image.rb index eda89ecc8..4d479d282 100644 --- a/app/models/image.rb +++ b/app/models/image.rb @@ -4,8 +4,8 @@ class Image < ApplicationRecord def self.styles { large: { resize: "x#{Setting["uploads.images.min_height"]}" }, - medium: { combine_options: { gravity: "center", resize: "300x300^", crop: "300x300+0+0" }}, - thumb: { combine_options: { gravity: "center", resize: "140x245^", crop: "140x245+0+0" }} + medium: { gravity: "center", resize: "300x300^", crop: "300x300+0+0" }, + thumb: { gravity: "center", resize: "140x245^", crop: "140x245+0+0" } } end @@ -61,7 +61,10 @@ class Image < ApplicationRecord if accepted_content_types.include?(attachment_content_type) return true if imageable_class == Widget::Card - attachment.analyze unless attachment.analyzed? + unless attachment.analyzed? + attachment_changes["attachment"].upload + attachment.analyze + end width = attachment.metadata[:width] height = attachment.metadata[:height] diff --git a/app/models/site_customization/image.rb b/app/models/site_customization/image.rb index 7d69f74c1..ca68c0288 100644 --- a/app/models/site_customization/image.rb +++ b/app/models/site_customization/image.rb @@ -1,6 +1,4 @@ class SiteCustomization::Image < ApplicationRecord - include HasAttachment - VALID_IMAGES = { "logo_header" => [260, 80], "social_media_icon" => [470, 246], @@ -22,7 +20,7 @@ class SiteCustomization::Image < ApplicationRecord image/x-icon ].freeze - has_attachment :image + has_one_attached :image validates :name, presence: true, uniqueness: true, inclusion: { in: ->(*) { VALID_IMAGES.keys }} validates :image, file_content_type: { allow: ->(*) { VALID_MIME_TYPES }, if: -> { image.attached? }} @@ -61,7 +59,11 @@ class SiteCustomization::Image < ApplicationRecord def check_image return unless image.attached? - image.analyze unless image.analyzed? + unless image.analyzed? + attachment_changes["image"].upload + image.analyze + end + width = image.metadata[:width] height = image.metadata[:height] diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index 1a78ad60a..47cba9f90 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -27,7 +27,7 @@ "aria-hidden": true, class: "button hollow expanded" %> <%= render "layouts/flash" %> - <%= render "layouts/officing_booth" if controller.class.parent == Officing && session[:booth_id].present? %> + <%= render "layouts/officing_booth" if controller.class.module_parent == Officing && session[:booth_id].present? %> <%= yield %> diff --git a/app/views/shared/_subnavigation.html.erb b/app/views/shared/_subnavigation.html.erb index 1c81f389a..4df7ff1d8 100644 --- a/app/views/shared/_subnavigation.html.erb +++ b/app/views/shared/_subnavigation.html.erb @@ -22,7 +22,7 @@
  • <%= layout_menu_link_to t("layouts.header.poll_questions"), polls_path, - controller_name == "polls" || (controller_name == "questions" && controller.class.parent == Polls), + controller_name == "polls" || (controller_name == "questions" && controller.class.module_parent == Polls), accesskey: "3" %>
  • <% end %> @@ -30,7 +30,7 @@
  • <%= layout_menu_link_to t("layouts.header.collaborative_legislation"), legislation_processes_path, - controller.class.parent == Legislation, + controller.class.module_parent == Legislation, accesskey: "4" %>
  • <% end %> diff --git a/bin/setup b/bin/setup index aa921f10d..5635f8ec1 100755 --- a/bin/setup +++ b/bin/setup @@ -1,6 +1,5 @@ #!/usr/bin/env ruby require "fileutils" -include FileUtils # path to your application root. APP_ROOT = File.expand_path("..", __dir__) @@ -9,8 +8,9 @@ def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to setup or update your development environment automatically. + # This script is idempotent, so that you can run it at anytime and get an expectable outcome. # Add necessary setup steps to this file. puts "== Installing dependencies ==" @@ -19,11 +19,11 @@ chdir APP_ROOT do # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system! "bin/rails db:setup" + system! "bin/rails db:prepare" puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" diff --git a/config/application.rb b/config/application.rb index a0de876cb..d18d64a15 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,19 @@ require_relative "boot" -require "rails/all" +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +require "active_job/railtie" +require "active_record/railtie" +require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +require "action_cable/engine" +require "sprockets/railtie" +require "rails/test_unit/railtie" # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. @@ -8,7 +21,7 @@ Bundler.require(*Rails.groups) module Consul class Application < Rails::Application - config.load_defaults 5.2 + config.load_defaults 6.0 # Keep belongs_to fields optional by default, because that's the way # Rails 4 models worked @@ -21,13 +34,22 @@ module Consul # in any CONSUL installations config.active_support.use_authenticated_message_encryption = false + # Keep using the classic autoloader until we decide how custom classes + # should work with zeitwerk + config.autoloader = :classic + + # Use the default queue for ActiveStorage like we were doing with Rails 5.2 + # because it will also be the default in Rails 6.1. + config.active_storage.queues.analysis = nil + config.active_storage.queues.purge = nil + # Keep reading existing data in the legislation_annotations ranges column config.active_record.yaml_column_permitted_classes = [ActiveSupport::HashWithIndifferentAccess, Symbol] # Handle custom exceptions config.action_dispatch.rescue_responses["FeatureFlags::FeatureDisabled"] = :forbidden - # Store files locally. + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. @@ -75,7 +97,7 @@ module Consul "zh-CN", "zh-TW"] config.i18n.available_locales = available_locales - config.i18n.fallbacks = { + config.i18n.fallbacks = [I18n.default_locale, { "ca" => "es", "es-PE" => "es", "eu" => "es", @@ -85,7 +107,7 @@ module Consul "oc" => "fr", "pt-BR" => "es", "val" => "es" - } + }] config.i18n.load_path += Dir[Rails.root.join("config", "locales", "**[^custom]*", "*.{rb,yml}")] config.i18n.load_path += Dir[Rails.root.join("config", "locales", "custom", "**", "*.{rb,yml}")] diff --git a/config/environments/development.rb b/config/environments/development.rb index 3b37e1e85..72d7ec69b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -16,6 +16,7 @@ Rails.application.configure do # Run rails dev:cache to toggle caching. if Rails.root.join("tmp", "caching-dev.txt").exist? config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store config.public_file_server.headers = { @@ -50,14 +51,10 @@ Rails.application.configure do # number of complex assets. config.assets.debug = false - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true # Suppress logger output for asset requests. config.assets.quiet = true - # Raises error for missing translations + # Raises error for missing translations. # config.action_view.raise_on_missing_translations = true config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews" diff --git a/config/environments/production.rb b/config/environments/production.rb index cb680f167..9c8f2e683 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -19,6 +19,10 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? @@ -37,7 +41,7 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX - # Mount Action Cable outside main process or domain + # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil # config.action_cable.url = "wss://example.com/cable" # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] @@ -56,9 +60,10 @@ Rails.application.configure do # Use a different cache store in production. config.cache_store = :mem_cache_store - # Use a real queuing backend for Active Job (and separate queues per environment) + # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "consul_#{Rails.env}" + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -90,9 +95,30 @@ Rails.application.configure do if ENV["RAILS_LOG_TO_STDOUT"].present? logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) + config.logger = ActiveSupport::TaggedLogging.new(logger) end # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Inserts middleware to perform automatic connection switching. + # The `database_selector` hash is used to pass options to the DatabaseSelector + # middleware. The `delay` is used to determine how long to wait after a write + # to send a subsequent read to the primary. + # + # The `database_resolver` class is used by the middleware to determine which + # database is appropriate to use based on the time delay. + # + # The `database_resolver_context` class is used by the middleware to set + # timestamps for the last write to the primary. The resolver uses the context + # class timestamps to determine how long to wait before reading from the + # replica. + # + # By default Rails will store a last write timestamp in the session. The + # DatabaseSelector middleware is designed as such you can define your own + # strategy for connection switching and pass that into the middleware through + # these configuration options. + # config.active_record.database_selector = { delay: 2.seconds } + # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver + # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session end diff --git a/config/environments/staging.rb b/config/environments/staging.rb index d84df4300..f05d0a6ee 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -19,6 +19,10 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? @@ -37,7 +41,7 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX - # Mount Action Cable outside main process or domain + # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil # config.action_cable.url = "wss://example.com/cable" # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] @@ -56,7 +60,7 @@ Rails.application.configure do # Use a different cache store in production. config.cache_store = :mem_cache_store - # Use a real queuing backend for Active Job (and separate queues per environment) + # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "consul_#{Rails.env}" config.action_mailer.perform_caching = false @@ -90,9 +94,30 @@ Rails.application.configure do if ENV["RAILS_LOG_TO_STDOUT"].present? logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) + config.logger = ActiveSupport::TaggedLogging.new(logger) end # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Inserts middleware to perform automatic connection switching. + # The `database_selector` hash is used to pass options to the DatabaseSelector + # middleware. The `delay` is used to determine how long to wait after a write + # to send a subsequent read to the primary. + # + # The `database_resolver` class is used by the middleware to determine which + # database is appropriate to use based on the time delay. + # + # The `database_resolver_context` class is used by the middleware to set + # timestamps for the last write to the primary. The resolver uses the context + # class timestamps to determine how long to wait before reading from the + # replica. + # + # By default Rails will store a last write timestamp in the session. The + # DatabaseSelector middleware is designed as such you can define your own + # strategy for connection switching and pass that into the middleware through + # these configuration options. + # config.active_record.database_selector = { delay: 2.seconds } + # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver + # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session end diff --git a/config/environments/test.rb b/config/environments/test.rb index 23ac6efa3..463b25f08 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,8 @@ +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -6,10 +11,6 @@ Rails.application.configure do config.i18n.default_locale = :en config.i18n.available_locales = %w[de en es fr nl pt-BR zh-CN] - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application @@ -26,12 +27,17 @@ Rails.application.configure do # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory. + config.active_storage.service = :test + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -44,14 +50,9 @@ Rails.application.configure do # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raises error for missing translations + # Raises error for missing translations. # config.action_view.raise_on_missing_translations = true - # Store files in tmp folders. - config.active_storage.service = :test - - config.cache_store = :null_store - config.after_initialize do Bullet.enable = true Bullet.bullet_logger = true diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index d3bcaa5ec..41c43016f 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -19,6 +19,9 @@ # If you are using UJS then enable automatic nonce generation # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + # Report CSP violations to a specified URI # For further information see the following documentation: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only diff --git a/config/initializers/i18n_translation.rb b/config/initializers/i18n_translation.rb index ae43e5fc0..69c933f35 100644 --- a/config/initializers/i18n_translation.rb +++ b/config/initializers/i18n_translation.rb @@ -6,7 +6,7 @@ module ActionView module TranslationHelper include TagHelper - def t(key, options = {}) + def t(key, **options) current_locale = options[:locale].presence || I18n.locale @i18n_content_translations ||= {} @@ -17,7 +17,7 @@ module ActionView if translation.present? translation % options else - translate(key, options) + translate(key, **options) end end end diff --git a/db/migrate/20210924194527_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb b/db/migrate/20210924194527_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb new file mode 100644 index 000000000..ff5d72c7e --- /dev/null +++ b/db/migrate/20210924194527_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb @@ -0,0 +1,10 @@ +# This migration comes from active_storage (originally 20180723000244) +class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0] + def up + return if foreign_key_exists?(:active_storage_attachments, column: :blob_id) + + if table_exists?(:active_storage_blobs) + add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8d87806d6..b3cac4d02 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,11 +2,11 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. diff --git a/spec/lib/tasks/files_spec.rb b/spec/lib/tasks/files_spec.rb index 4d55334bb..5671aa208 100644 --- a/spec/lib/tasks/files_spec.rb +++ b/spec/lib/tasks/files_spec.rb @@ -12,7 +12,9 @@ describe "files tasks" do document = build(:document) image.attachment.blob.save! + image.attachment_changes["attachment"].upload document.attachment.blob.save! + document.attachment_changes["attachment"].upload travel_to(2.days.from_now) { run_rake_task } @@ -25,7 +27,9 @@ describe "files tasks" do document = build(:document) image.attachment.blob.save! + image.attachment_changes["attachment"].upload document.attachment.blob.save! + document.attachment_changes["attachment"].upload travel_to(2.minutes.from_now) { run_rake_task } diff --git a/spec/shared/system/relationable.rb b/spec/shared/system/relationable.rb index 5eb40de4f..50246fb29 100644 --- a/spec/shared/system/relationable.rb +++ b/spec/shared/system/relationable.rb @@ -3,7 +3,11 @@ shared_examples "relationable" do |relationable_model_name| let(:related1) { create([:proposal, :debate, :budget_investment].sample) } let(:related2) { create([:proposal, :debate, :budget_investment].sample) } let(:user) { create(:user) } - before { Setting["url"] = Capybara.app_host } + + before do + integration_session.host = Capybara.app_host # TODO: remove after upgrading to Rails 6.1 + Setting["url"] = Capybara.app_host + end scenario "related contents are listed" do create(:related_content, parent_relationable: relationable, child_relationable: related1, author: build(:user)) diff --git a/spec/system/admin/budget_investments_spec.rb b/spec/system/admin/budget_investments_spec.rb index 6430f62da..82af1feb0 100644 --- a/spec/system/admin/budget_investments_spec.rb +++ b/spec/system/admin/budget_investments_spec.rb @@ -1709,7 +1709,7 @@ describe "Admin budget investments", :admin do header = page.response_headers["Content-Disposition"] expect(header).to match(/^attachment/) - expect(header).to match(/filename="budget_investments.csv"$/) + expect(header).to match(/filename="budget_investments.csv"/) csv_contents = "ID,Title,Supports,Administrator,Valuator,Valuation Group,Scope of operation,"\ "Feasibility,Val. Fin.,Selected,Show to valuators,Author username\n"\ diff --git a/spec/system/admin/emails/emails_download_spec.rb b/spec/system/admin/emails/emails_download_spec.rb index 26facab75..cabfcf5c3 100644 --- a/spec/system/admin/emails/emails_download_spec.rb +++ b/spec/system/admin/emails/emails_download_spec.rb @@ -32,7 +32,7 @@ describe "Admin download user emails" do header = page.response_headers["Content-Disposition"] expect(header).to match(/^attachment/) - expect(header).to match(/filename="Administrators.csv"$/) + expect(header).to match(/filename="Administrators.csv"/) file_contents = page.body.split(",") expect(file_contents).to match_array ["admin_news1@consul.dev", "admin_news2@consul.dev"]