Merge pull request #5496 from consuldemocracy/rails7.1

Upgrade to Rails 7.1
This commit is contained in:
Javi Martín
2025-05-20 15:54:44 +02:00
committed by GitHub
28 changed files with 249 additions and 173 deletions

View File

@@ -12,6 +12,7 @@ AllCops:
Exclude: Exclude:
- "db/schema.rb" - "db/schema.rb"
- "app/lib/ckeditor/backend/active_storage.rb" - "app/lib/ckeditor/backend/active_storage.rb"
- "config/initializers/disable_active_storage_pdf_auto_previews.rb"
- "vendor/**/*" - "vendor/**/*"
DisabledByDefault: true DisabledByDefault: true
@@ -186,6 +187,8 @@ Layout/MultilineMethodCallBraceLayout:
Layout/MultilineMethodCallIndentation: Layout/MultilineMethodCallIndentation:
Enabled: true Enabled: true
Exclude:
- "config/environments/production.rb"
Layout/MultilineOperationIndentation: Layout/MultilineOperationIndentation:
Enabled: true Enabled: true
@@ -698,6 +701,8 @@ Style/AndOr:
Style/ArgumentsForwarding: Style/ArgumentsForwarding:
Enabled: true Enabled: true
Exclude:
- "bin/setup"
Style/ArrayCoercion: Style/ArrayCoercion:
Enabled: true Enabled: true

View File

@@ -2,7 +2,7 @@ source "https://rubygems.org"
ruby file: ".ruby-version" ruby file: ".ruby-version"
gem "rails", "7.0.8.7" gem "rails", "7.1.5.1"
gem "acts-as-taggable-on", "~> 11.0.0" gem "acts-as-taggable-on", "~> 11.0.0"
gem "acts_as_votable", "~> 0.14.0" gem "acts_as_votable", "~> 0.14.0"

View File

@@ -2,70 +2,82 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
Ascii85 (2.0.1) Ascii85 (2.0.1)
actioncable (7.0.8.7) actioncable (7.1.5.1)
actionpack (= 7.0.8.7) actionpack (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailbox (7.0.8.7) zeitwerk (~> 2.6)
actionpack (= 7.0.8.7) actionmailbox (7.1.5.1)
activejob (= 7.0.8.7) actionpack (= 7.1.5.1)
activerecord (= 7.0.8.7) activejob (= 7.1.5.1)
activestorage (= 7.0.8.7) activerecord (= 7.1.5.1)
activesupport (= 7.0.8.7) activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.0.8.7) actionmailer (7.1.5.1)
actionpack (= 7.0.8.7) actionpack (= 7.1.5.1)
actionview (= 7.0.8.7) actionview (= 7.1.5.1)
activejob (= 7.0.8.7) activejob (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
actionpack (7.0.8.7) actionpack (7.1.5.1)
actionview (= 7.0.8.7) actionview (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
rack (~> 2.0, >= 2.2.4) nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.0, >= 1.2.0) rails-html-sanitizer (~> 1.6)
actiontext (7.0.8.7) actiontext (7.1.5.1)
actionpack (= 7.0.8.7) actionpack (= 7.1.5.1)
activerecord (= 7.0.8.7) activerecord (= 7.1.5.1)
activestorage (= 7.0.8.7) activestorage (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.0.8.7) actionview (7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.11)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.1, >= 1.2.0) rails-html-sanitizer (~> 1.6)
activejob (7.0.8.7) activejob (7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.0.8.7) activemodel (7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
activerecord (7.0.8.7) activerecord (7.1.5.1)
activemodel (= 7.0.8.7) activemodel (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
activestorage (7.0.8.7) timeout (>= 0.4.0)
actionpack (= 7.0.8.7) activestorage (7.1.5.1)
activejob (= 7.0.8.7) actionpack (= 7.1.5.1)
activerecord (= 7.0.8.7) activejob (= 7.1.5.1)
activesupport (= 7.0.8.7) activerecord (= 7.1.5.1)
activesupport (= 7.1.5.1)
marcel (~> 1.0) marcel (~> 1.0)
mini_mime (>= 1.1.0) activesupport (7.1.5.1)
activesupport (7.0.8.7) base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1) minitest (>= 5.1)
mutex_m
securerandom (>= 0.3)
tzinfo (~> 2.0) tzinfo (~> 2.0)
acts-as-taggable-on (11.0.0) acts-as-taggable-on (11.0.0)
activerecord (>= 7.0, < 8.0) activerecord (>= 7.0, < 8.0)
@@ -98,6 +110,7 @@ GEM
execjs (~> 2) execjs (~> 2)
base64 (0.2.0) base64 (0.2.0)
bcrypt (3.1.20) bcrypt (3.1.20)
benchmark (0.4.0)
better_html (2.1.1) better_html (2.1.1)
actionview (>= 6.0) actionview (>= 6.0)
activesupport (>= 6.0) activesupport (>= 6.0)
@@ -172,6 +185,7 @@ GEM
execjs execjs
coffee-script-source (1.12.2) coffee-script-source (1.12.2)
concurrent-ruby (1.3.4) concurrent-ruby (1.3.4)
connection_pool (2.5.0)
crass (1.0.6) crass (1.0.6)
csv (3.3.2) csv (3.3.2)
daemons (1.4.1) daemons (1.4.1)
@@ -196,6 +210,7 @@ GEM
devise (>= 4.3.0) devise (>= 4.3.0)
diff-lcs (1.6.0) diff-lcs (1.6.0)
docile (1.4.0) docile (1.4.0)
drb (2.2.1)
email_spec (2.3.0) email_spec (2.3.0)
htmlentities (~> 4.3.3) htmlentities (~> 4.3.3)
launchy (>= 2.1, < 4.0) launchy (>= 2.1, < 4.0)
@@ -478,22 +493,27 @@ GEM
rack (~> 2.2, >= 2.2.4) rack (~> 2.2, >= 2.2.4)
rack-proxy (0.7.6) rack-proxy (0.7.6)
rack rack
rack-session (1.0.2)
rack (< 3)
rack-test (2.2.0) rack-test (2.2.0)
rack (>= 1.3) rack (>= 1.3)
rails (7.0.8.7) rackup (1.0.1)
actioncable (= 7.0.8.7) rack (< 3)
actionmailbox (= 7.0.8.7) webrick
actionmailer (= 7.0.8.7) rails (7.1.5.1)
actionpack (= 7.0.8.7) actioncable (= 7.1.5.1)
actiontext (= 7.0.8.7) actionmailbox (= 7.1.5.1)
actionview (= 7.0.8.7) actionmailer (= 7.1.5.1)
activejob (= 7.0.8.7) actionpack (= 7.1.5.1)
activemodel (= 7.0.8.7) actiontext (= 7.1.5.1)
activerecord (= 7.0.8.7) actionview (= 7.1.5.1)
activestorage (= 7.0.8.7) activejob (= 7.1.5.1)
activesupport (= 7.0.8.7) activemodel (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.0.8.7) railties (= 7.1.5.1)
rails-dom-testing (2.2.0) rails-dom-testing (2.2.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
minitest minitest
@@ -504,13 +524,14 @@ GEM
rails-i18n (7.0.9) rails-i18n (7.0.9)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
railties (7.0.8.7) railties (7.1.5.1)
actionpack (= 7.0.8.7) actionpack (= 7.1.5.1)
activesupport (= 7.0.8.7) activesupport (= 7.1.5.1)
method_source irb
rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
thor (~> 1.0) thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.5) zeitwerk (~> 2.6)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.2.1) rake (13.2.1)
rbtree3 (0.7.1) rbtree3 (0.7.1)
@@ -617,6 +638,7 @@ GEM
sawyer (0.9.2) sawyer (0.9.2)
addressable (>= 2.3.5) addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3) faraday (>= 0.17.3, < 3)
securerandom (0.4.1)
selenium-webdriver (4.29.1) selenium-webdriver (4.29.1)
base64 (~> 0.2) base64 (~> 0.2)
logger (~> 1.4) logger (~> 1.4)
@@ -697,7 +719,8 @@ GEM
railties (>= 6.0.0) railties (>= 6.0.0)
webrick (1.8.2) webrick (1.8.2)
websocket (1.2.11) websocket (1.2.11)
websocket-driver (0.7.6) websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
whenever (1.0.0) whenever (1.0.0)
@@ -778,7 +801,7 @@ DEPENDENCIES
pronto-rubocop (~> 0.11.6) pronto-rubocop (~> 0.11.6)
pronto-stylelint (~> 0.11.0) pronto-stylelint (~> 0.11.0)
puma (~> 5.6.9) puma (~> 5.6.9)
rails (= 7.0.8.7) rails (= 7.1.5.1)
recipient_interceptor (~> 0.3.3) recipient_interceptor (~> 0.3.3)
redcarpet (~> 3.6.0) redcarpet (~> 3.6.0)
responders (~> 3.1.1) responders (~> 3.1.1)

View File

@@ -1,5 +1,7 @@
.banner { .banner {
@include full-width-background; @include full-width-background;
@include card;
padding: 0 rem-calc(16);
.debates-list &::before, .debates-list &::before,
.proposals-list &::before, .proposals-list &::before,
@@ -7,17 +9,20 @@
content: none; content: none;
} }
&:hover {
text-decoration: underline;
}
a { a {
display: block; &,
&:hover {
color: inherit;
}
}
> * { > :empty {
padding: 0 rem-calc(16);
&:empty {
display: none; display: none;
} }
}
}
+ .budget-header, + .budget-header,
+ .budgets-index > .budget-header, + .budgets-index > .budget-header,

View File

@@ -1,3 +1,3 @@
<div class="banner" style="background-color:<%= banner.background_color %>;"> <div class="banner" style="background-color:<%= banner.background_color %>;">
<%= sanitize link, attributes: %w[href style] %> <%= sanitize banner_content, attributes: %w[href style] %>
</div> </div>

View File

@@ -19,10 +19,8 @@ class Shared::BannerComponent < ApplicationComponent
private private
def link def banner_content
link_to banner.target_url do tag.h2(link_to(banner.title, banner.target_url), style: "color:#{banner.font_color}") +
tag.h2(banner.title, style: "color:#{banner.font_color}") +
tag.h3(banner.description, style: "color:#{banner.font_color}") tag.h3(banner.description, style: "color:#{banner.font_color}")
end end
end
end end

View File

@@ -38,7 +38,7 @@ module Budgets
def index def index
@investments = investments.page(params[:page]).per(PER_PAGE).for_render @investments = investments.page(params[:page]).per(PER_PAGE).for_render
@investment_ids = @investments.ids @investment_ids = @investments.unscope(:includes).ids
@investments_in_map = investments @investments_in_map = investments
@tag_cloud = tag_cloud @tag_cloud = tag_cloud

View File

@@ -3,7 +3,7 @@ class Legislation::Annotation < ApplicationRecord
acts_as_paranoid column: :hidden_at acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases include ActsAsParanoidAliases
serialize :ranges, Array serialize :ranges, type: Array
belongs_to :draft_version, foreign_key: "legislation_draft_version_id", inverse_of: :annotations belongs_to :draft_version, foreign_key: "legislation_draft_version_id", inverse_of: :annotations
belongs_to :author, -> { with_hidden }, class_name: "User", inverse_of: :legislation_annotations belongs_to :author, -> { with_hidden }, class_name: "User", inverse_of: :legislation_annotations

View File

@@ -5,7 +5,7 @@ require "fileutils"
APP_ROOT = File.expand_path("..", __dir__) APP_ROOT = File.expand_path("..", __dir__)
def system!(*args) def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==") system(*args, exception: true)
end end
FileUtils.chdir APP_ROOT do FileUtils.chdir APP_ROOT do

View File

@@ -21,7 +21,15 @@ Bundler.require(*Rails.groups)
module Consul module Consul
class Application < Rails::Application class Application < Rails::Application
config.load_defaults 7.0 def secrets
Rails.deprecator.silence { super }
end
def secret_key_base
Rails.deprecator.silence { super }
end
config.load_defaults 7.1
# Keep belongs_to fields optional by default, because that's the way # Keep belongs_to fields optional by default, because that's the way
# Rails 4 models worked # Rails 4 models worked
@@ -43,6 +51,9 @@ module Consul
# order to make upgrades easier. # order to make upgrades easier.
config.active_storage.variant_processor = :mini_magick config.active_storage.variant_processor = :mini_magick
# Keep using YAML to serialize the legislation_annotations ranges column
config.active_record.default_column_serializer = YAML
# Keep reading existing data in the legislation_annotations ranges column # Keep reading existing data in the legislation_annotations ranges column
config.active_record.yaml_column_permitted_classes = [ActiveSupport::HashWithIndifferentAccess, Symbol] config.active_record.yaml_column_permitted_classes = [ActiveSupport::HashWithIndifferentAccess, Symbol]

View File

@@ -7,7 +7,7 @@ Rails.application.configure do
# In the development environment your application's code is reloaded any time # In the development environment your application's code is reloaded any time
# it changes. This slows down response time but is perfect for development # it changes. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes. # since you don't have to restart the web server when you make code changes.
config.cache_classes = false config.enable_reloading = true
# Do not eager load code on boot. # Do not eager load code on boot.
config.eager_load = false config.eager_load = false
@@ -61,6 +61,9 @@ Rails.application.configure do
# Highlight code that triggered database queries in logs. # Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true config.active_record.verbose_query_logs = true
# Highlight code that enqueued background job in logs.
config.active_job.verbose_enqueue_logs = true
# Suppress logger output for asset requests. # Suppress logger output for asset requests.
config.assets.quiet = true config.assets.quiet = true
@@ -71,16 +74,13 @@ Rails.application.configure do
# config.action_view.annotate_rendered_view_with_filenames = true # config.action_view.annotate_rendered_view_with_filenames = true
config.eager_load_paths << "#{Rails.root}/spec/mailers/previews" config.eager_load_paths << "#{Rails.root}/spec/mailers/previews"
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews" config.action_mailer.preview_paths << "#{Rails.root}/spec/mailers/previews"
# Limit size of local logs
# TODO: replace with config.log_file_size after upgrading to Rails 7.1
logger = ActiveSupport::Logger.new(config.default_log_file, 1, 100.megabytes)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
# Uncomment if you wish to allow Action Cable access from any origin. # Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true # config.action_cable.disable_request_forgery_protection = true
# Raise error when a before_action's only/except options reference missing actions
# config.action_controller.raise_on_missing_callback_actions = true
end end
require Rails.root.join("config", "environments", "custom", "development") require Rails.root.join("config", "environments", "custom", "development")

View File

@@ -4,7 +4,7 @@ Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb. # Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests. # Code is not reloaded between requests.
config.cache_classes = true config.enable_reloading = false
# Eager load code on boot. This eager loads most of Rails and # Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers # your application in memory, allowing both threaded web servers
@@ -16,19 +16,18 @@ Rails.application.configure do
config.consider_all_requests_local = false config.consider_all_requests_local = false
config.action_controller.perform_caching = true config.action_controller.perform_caching = true
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files). # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true # config.require_master_key = true
# Disable serving static files from the `/public` folder by default since # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
# Compress JavaScripts and CSS. # Compress JavaScripts and CSS.
config.assets.js_compressor = Uglifier.new(harmony: true) config.assets.js_compressor = Uglifier.new(harmony: true)
# config.assets.css_compressor = :sass # config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed. # Do not fall back to assets pipeline if a precompiled asset is missed.
config.assets.compile = false config.assets.compile = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server. # Enable serving of images, stylesheets, and JavaScripts from an asset server.
@@ -43,17 +42,37 @@ Rails.application.configure do
# config.action_cable.url = "wss://example.com/cable" # config.action_cable.url = "wss://example.com/cable"
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
# Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
# config.assume_ssl = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# Configure force_ssl in secrets.yml # Configure force_ssl in secrets.yml
config.force_ssl = Rails.application.secrets.force_ssl config.force_ssl = Rails.application.secrets.force_ssl
# Include generic and useful information about system operation, but avoid logging too much # Use default logging formatter so that PID and timestamp are not suppressed.
# information to avoid inadvertent exposure of personally identifiable information (PII). config.log_formatter = ::Logger::Formatter.new
config.log_level = :warn
# Rotate logger
logger = ActiveSupport::Logger.new(config.default_log_file, "daily")
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
# Log to STDOUT if enabled
if ENV["RAILS_LOG_TO_STDOUT"].present?
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
end
# Prepend all log lines with the following tags. # Prepend all log lines with the following tags.
config.log_tags = [:request_id] config.log_tags = [:request_id]
# "info" includes generic and useful information about system operation, but avoids logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII). If you
# want to log everything, set the level to "debug".
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "warn")
# Use a different cache store in production. # Use a different cache store in production.
config.cache_store = :mem_cache_store, { namespace: proc { Tenant.current_schema }} config.cache_store = :mem_cache_store, { namespace: proc { Tenant.current_schema }}
@@ -82,26 +101,16 @@ Rails.application.configure do
# Don't log any deprecations. # Don't log any deprecations.
config.active_support.report_deprecations = false config.active_support.report_deprecations = false
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Rotate logger
logger = ActiveSupport::Logger.new(config.default_log_file, "daily")
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
# Use a different logger for distributed setups.
# require "syslog/logger"
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations. # Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false config.active_record.dump_schema_after_migration = false
# Enable DNS rebinding protection and other `Host` header attacks.
# config.hosts = [
# "example.com", # Allow requests from example.com
# /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
# ]
# Skip DNS rebinding protection for the default health check endpoint.
# config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
end end
require Rails.root.join("config", "environments", "custom", "production") require Rails.root.join("config", "environments", "custom", "production")

View File

@@ -15,12 +15,13 @@ Rails.application.configure do
config.i18n.default_locale = :en config.i18n.default_locale = :en
config.i18n.available_locales = %w[de en es fr nl pt-BR zh-CN] config.i18n.available_locales = %w[de en es fr nl pt-BR zh-CN]
# Turn false under Spring and add config.action_view.cache_template_loading = true. # While tests run files are not watched, reloading is not necessary.
config.cache_classes = true config.enable_reloading = false
# Eager loading loads your whole application. When running a single test locally, # Eager loading loads your entire application. When running a single test locally,
# this probably isn't necessary. It's a good idea to do in a continuous integration # this is usually not necessary, and can slow down your test suite. However, it's
# system, or in some way before deploying your code. # recommended that you enable it in continuous integration systems to ensure eager
# loading is working properly before deploying your code.
config.eager_load = ENV["CI"].present? config.eager_load = ENV["CI"].present?
# Configure public file server for tests with Cache-Control for performance. # Configure public file server for tests with Cache-Control for performance.
@@ -34,8 +35,8 @@ Rails.application.configure do
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
config.cache_store = :null_store config.cache_store = :null_store
# Raise exceptions instead of rendering exception templates. # Render exception templates for rescuable exceptions and raise for other exceptions.
config.action_dispatch.show_exceptions = false config.action_dispatch.show_exceptions = :rescuable
# Disable request forgery protection in test environment. # Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false config.action_controller.allow_forgery_protection = false
@@ -66,11 +67,8 @@ Rails.application.configure do
# Annotate rendered view with file names. # Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true # config.action_view.annotate_rendered_view_with_filenames = true
# Limit size of local logs # Raise error when a before_action's only/except options reference missing actions
# TODO: replace with config.log_file_size after upgrading to Rails 7.1 # config.action_controller.raise_on_missing_callback_actions = true
logger = ActiveSupport::Logger.new(config.default_log_file, 1, 100.megabytes)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
# Allow managing different tenants using the same application # Allow managing different tenants using the same application
config.multitenancy = true config.multitenancy = true

View File

@@ -1,8 +1,8 @@
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
# Configure parameters to be filtered from the log file. Use this to limit dissemination of # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported # Use this to limit dissemination of sensitive information.
# notations and behaviors. # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [ Rails.application.config.filter_parameters += [
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
] ]

View File

@@ -16,9 +16,9 @@
# # policy.report_uri "/csp-violation-report-endpoint" # # policy.report_uri "/csp-violation-report-endpoint"
# end # end
# #
# # Generate session nonces for permitted importmap and inline scripts # # Generate session nonces for permitted importmap, inline scripts, and inline styles.
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
# config.content_security_policy_nonce_directives = %w(script-src) # config.content_security_policy_nonce_directives = %w(script-src style-src)
# #
# # Report violations without enforcing the policy. # # Report violations without enforcing the policy.
# # config.content_security_policy_report_only = true # # config.content_security_policy_report_only = true

View File

@@ -0,0 +1,22 @@
ActiveSupport.on_load(:active_storage_attachment) do
# Code copied from Rails 7.2. TODO: remove after upgrading to Rails 7.2
# See: https://github.com/rails/rails/pull/51351/files
class ActiveStorage::Attachment
private
def transform_variants_later
preprocessed_variations = named_variants.filter_map { |_name, named_variant|
if named_variant.preprocessed?(record)
named_variant.transformations
end
}
if blob.preview_image_needed_before_processing_variants? && preprocessed_variations.any?
blob.create_preview_image_later(preprocessed_variations)
else
preprocessed_variations.each do |transformations|
blob.preprocessed(transformations)
end
end
end
end
end

View File

@@ -1,11 +1,13 @@
# Be sure to restart your server when you modify this file.
# Define an application-wide HTTP permissions policy. For further # Define an application-wide HTTP permissions policy. For further
# information see https://developers.google.com/web/updates/2018/06/feature-policy # information see: https://developers.google.com/web/updates/2018/06/feature-policy
#
# Rails.application.config.permissions_policy do |f| # Rails.application.config.permissions_policy do |policy|
# f.camera :none # policy.camera :none
# f.gyroscope :none # policy.gyroscope :none
# f.microphone :none # policy.microphone :none
# f.usb :none # policy.usb :none
# f.fullscreen :self # policy.fullscreen :self
# f.payment :self, "https://secure.example.com" # policy.payment :self, "https://secure.example.com"
# end # end

View File

@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2025_03_13_014205) do ActiveRecord::Schema[7.1].define(version: 2025_03_13_014205) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm" enable_extension "pg_trgm"
enable_extension "plpgsql" enable_extension "plpgsql"

View File

@@ -4,10 +4,11 @@ require "rails_helper"
describe GraphqlController, type: :request do describe GraphqlController, type: :request do
let(:proposal) { create(:proposal) } let(:proposal) { create(:proposal) }
let(:query_string) { "{ proposal(id: #{proposal.id}) { title } }" }
describe "handles GET request" do describe "handles GET request" do
specify "with query string inside query params" do specify "with query string inside query params" do
get "/graphql", params: { query: "{ proposal(id: #{proposal.id}) { title } }" } get "/graphql", params: { query: query_string }
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.parsed_body["data"]["proposal"]["title"]).to eq(proposal.title) expect(response.parsed_body["data"]["proposal"]["title"]).to eq(proposal.title)
@@ -33,7 +34,7 @@ describe GraphqlController, type: :request do
let(:json_headers) { { "CONTENT_TYPE" => "application/json" } } let(:json_headers) { { "CONTENT_TYPE" => "application/json" } }
specify "with json-encoded query string inside body" do specify "with json-encoded query string inside body" do
post "/graphql", params: { query: "{ proposal(id: #{proposal.id}) { title } }" }.to_json, post "/graphql", params: { query: query_string }.to_json,
headers: json_headers headers: json_headers
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
@@ -42,7 +43,7 @@ describe GraphqlController, type: :request do
specify "with raw query string inside body" do specify "with raw query string inside body" do
graphql_headers = { "CONTENT_TYPE" => "application/graphql" } graphql_headers = { "CONTENT_TYPE" => "application/graphql" }
post "/graphql", params: "{ proposal(id: #{proposal.id}) { title } }", post "/graphql", params: query_string,
headers: graphql_headers headers: graphql_headers
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
@@ -66,8 +67,6 @@ describe GraphqlController, type: :request do
end end
describe "correctly parses query variables" do describe "correctly parses query variables" do
let(:query_string) { "{ proposal(id: #{proposal.id}) { title } }" }
specify "when absent" do specify "when absent" do
get "/graphql", params: { query: query_string } get "/graphql", params: { query: query_string }
@@ -91,8 +90,13 @@ describe GraphqlController, type: :request do
before { Setting["feature.graphql_api"] = false } before { Setting["feature.graphql_api"] = false }
it "is disabled" do it "is disabled" do
expect { get "/graphql" }.to raise_exception(FeatureFlags::FeatureDisabled) get "/graphql", params: { query: query_string }
expect { post "/graphql" }.to raise_exception(FeatureFlags::FeatureDisabled)
expect(response).to have_http_status(:forbidden)
post "/graphql", params: { query: query_string }
expect(response).to have_http_status(:forbidden)
end end
end end
end end

View File

@@ -15,7 +15,7 @@ describe Officing::VotersController do
voter: { poll_id: poll.id, user_id: user.id }, voter: { poll_id: poll.id, user_id: user.id },
format: :js format: :js
} }
rescue ActionDispatch::IllegalStateError, ActiveRecord::RecordInvalid rescue ActiveRecord::RecordInvalid
end end
end.each(&:join) end.each(&:join)

View File

@@ -13,7 +13,7 @@ describe Polls::AnswersController do
option_id: question.question_options.find_by(title: "Answer A").id, option_id: question.question_options.find_by(title: "Answer A").id,
format: :js format: :js
} }
rescue ActionDispatch::IllegalStateError, ActiveRecord::RecordInvalid rescue ActiveRecord::RecordInvalid
end end
end.each(&:join) end.each(&:join)

View File

@@ -135,16 +135,14 @@ describe Legislation::DraftVersion do
<p>Something about this.</p> <p>Something about this.</p>
<table> <table><thead>
<thead>
<tr> <tr>
<th>id</th> <th>id</th>
<th>name</th> <th>name</th>
<th>age</th> <th>age</th>
<th>gender</th> <th>gender</th>
</tr> </tr>
</thead> </thead><tbody>
<tbody>
<tr> <tr>
<td>1</td> <td>1</td>
<td>Roberta</td> <td>Roberta</td>
@@ -157,8 +155,7 @@ describe Legislation::DraftVersion do
<td>25</td> <td>25</td>
<td>F</td> <td>F</td>
</tr> </tr>
</tbody> </tbody></table>
</table>
BODY_HTML BODY_HTML
end end

View File

@@ -10,7 +10,7 @@ Dir["./spec/shared/**/*.rb"].sort.each { |f| require f }
RSpec.configure do |config| RSpec.configure do |config|
config.use_transactional_fixtures = true config.use_transactional_fixtures = true
config.fixture_path = "spec/fixtures/files" config.fixture_paths = ["spec/fixtures/files"]
config.filter_run_when_matching :focus config.filter_run_when_matching :focus
config.include RequestSpecHelper, type: :request config.include RequestSpecHelper, type: :request
@@ -102,7 +102,7 @@ RSpec.configure do |config|
allow(Rails.application).to receive(:env_config) do allow(Rails.application).to receive(:env_config) do
config.merge( config.merge(
"action_dispatch.show_exceptions" => true, "action_dispatch.show_exceptions" => :all,
"action_dispatch.show_detailed_exceptions" => false, "action_dispatch.show_detailed_exceptions" => false,
"consider_all_requests_local" => false "consider_all_requests_local" => false
) )

View File

@@ -86,7 +86,7 @@ describe "Admin banners magement", :admin do
visit proposals_path visit proposals_path
expect(page).to have_content "Such banner" expect(page).to have_content "Such banner"
expect(page).to have_link "Such banner many text wow link", href: "https://www.url.com" expect(page).to have_link "Such banner", href: "https://www.url.com"
end end
scenario "Publish a banner with a translation different than the current locale" do scenario "Publish a banner with a translation different than the current locale" do

View File

@@ -267,7 +267,7 @@ describe "Comments" do
scenario "Sanitizes comment body for security" do scenario "Sanitizes comment body for security" do
create(:comment, commentable: resource, create(:comment, commentable: resource,
body: "<script>alert('hola')</script> " \ body: "<script>alert('hola')</script> " \
"<a href=\"javascript:alert('sorpresa!')\">click me<a/> " \ "<a href=\"javascript:alert('sorpresa!')\">click me</a> " \
"http://www.url.com") "http://www.url.com")
visit polymorphic_path(resource) visit polymorphic_path(resource)

View File

@@ -296,7 +296,7 @@ describe "Debates" do
scenario "JS injection is prevented but autolinking is respected", :no_js do scenario "JS injection is prevented but autolinking is respected", :no_js do
author = create(:user) author = create(:user)
js_injection_string = "<script>alert('hey')</script> " \ js_injection_string = "<script>alert('hey')</script> " \
"<a href=\"javascript:alert('surprise!')\">click me<a/> " \ "<a href=\"javascript:alert('surprise!')\">click me</a> " \
"http://example.org" "http://example.org"
login_as(author) login_as(author)

View File

@@ -3,7 +3,7 @@ require "rails_helper"
describe "Multitenancy", :seed_tenants do describe "Multitenancy", :seed_tenants do
before { create(:tenant, schema: "mars") } before { create(:tenant, schema: "mars") }
scenario "Disabled features", :no_js do scenario "Disabled features", :show_exceptions do
create(:tenant, schema: "venus") create(:tenant, schema: "venus")
Tenant.switch("mars") { Setting["process.debates"] = true } Tenant.switch("mars") { Setting["process.debates"] = true }
Tenant.switch("venus") { Setting["process.debates"] = nil } Tenant.switch("venus") { Setting["process.debates"] = nil }
@@ -15,7 +15,9 @@ describe "Multitenancy", :seed_tenants do
end end
with_subdomain("venus") do with_subdomain("venus") do
expect { visit debates_path }.to raise_exception(FeatureFlags::FeatureDisabled) visit debates_path
expect(page).to have_title "Forbidden"
end end
end end

View File

@@ -514,7 +514,7 @@ describe "Proposals" do
scenario "JS injection is prevented but autolinking is respected", :no_js do scenario "JS injection is prevented but autolinking is respected", :no_js do
author = create(:user) author = create(:user)
js_injection_string = "<script>alert('hey')</script> " \ js_injection_string = "<script>alert('hey')</script> " \
"<a href=\"javascript:alert('surprise!')\">click me<a/> " \ "<a href=\"javascript:alert('surprise!')\">click me</a> " \
"http://example.org" "http://example.org"
login_as(author) login_as(author)