diff --git a/.rubocop.yml b/.rubocop.yml index ca7a3de9a..9b9a9089a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -11,7 +11,7 @@ inherit_mode: - Include AllCops: - TargetRubyVersion: 3.1 + TargetRubyVersion: 3.2 DisabledByDefault: true SuggestExtensions: false NewCops: enable diff --git a/.ruby-version b/.ruby-version index ef538c281..be94e6f53 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.2 +3.2.2 diff --git a/Gemfile b/Gemfile index e03fc22c8..74571dd79 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ source 'https://rubygems.org' +gem 'rails', '~> 7.0.4' # allows update to security fixes at any time + gem 'aasm' gem 'acsv' gem 'active_link_to' # Automatically set a class on active links @@ -67,7 +69,6 @@ gem 'premailer-rails' gem 'puma' # Use Puma as the app server gem 'pundit' gem 'rack-attack' -gem 'rails' gem 'rails-i18n' # Locales par défaut gem 'rake-progressbar', require: false gem 'redcarpet' diff --git a/Gemfile.lock b/Gemfile.lock index 64ec024eb..5ba9cb14b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,40 +4,47 @@ GEM aasm (5.2.0) concurrent-ruby (~> 1.0) acsv (0.0.1) - actioncable (6.1.7.1) - actionpack (= 6.1.7.1) - activesupport (= 6.1.7.1) + actioncable (7.0.4.3) + actionpack (= 7.0.4.3) + activesupport (= 7.0.4.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.7.1) - actionpack (= 6.1.7.1) - activejob (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + actionmailbox (7.0.4.3) + actionpack (= 7.0.4.3) + activejob (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) mail (>= 2.7.1) - actionmailer (6.1.7.1) - actionpack (= 6.1.7.1) - actionview (= 6.1.7.1) - activejob (= 6.1.7.1) - activesupport (= 6.1.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.4.3) + actionpack (= 7.0.4.3) + actionview (= 7.0.4.3) + activejob (= 7.0.4.3) + activesupport (= 7.0.4.3) mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp rails-dom-testing (~> 2.0) - actionpack (6.1.7.1) - actionview (= 6.1.7.1) - activesupport (= 6.1.7.1) - rack (~> 2.0, >= 2.0.9) + actionpack (7.0.4.3) + actionview (= 7.0.4.3) + activesupport (= 7.0.4.3) + rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.7.1) - actionpack (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + actiontext (7.0.4.3) + actionpack (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) + globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (6.1.7.1) - activesupport (= 6.1.7.1) + actionview (7.0.4.3) + activesupport (= 7.0.4.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -45,9 +52,9 @@ GEM active_link_to (1.0.5) actionpack addressable - active_model_serializers (0.10.12) - actionpack (>= 4.1, < 6.2) - activemodel (>= 4.1, < 6.2) + active_model_serializers (0.10.13) + actionpack (>= 4.1, < 7.1) + activemodel (>= 4.1, < 7.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_storage_validations (0.9.6) @@ -55,31 +62,30 @@ GEM activemodel (>= 5.2.0) activestorage (>= 5.2.0) activesupport (>= 5.2.0) - activejob (6.1.7.1) - activesupport (= 6.1.7.1) + activejob (7.0.4.3) + activesupport (= 7.0.4.3) globalid (>= 0.3.6) - activemodel (6.1.7.1) - activesupport (= 6.1.7.1) - activerecord (6.1.7.1) - activemodel (= 6.1.7.1) - activesupport (= 6.1.7.1) - activestorage (6.1.7.1) - actionpack (= 6.1.7.1) - activejob (= 6.1.7.1) - activerecord (= 6.1.7.1) - activesupport (= 6.1.7.1) + activemodel (7.0.4.3) + activesupport (= 7.0.4.3) + activerecord (7.0.4.3) + activemodel (= 7.0.4.3) + activesupport (= 7.0.4.3) + activestorage (7.0.4.3) + actionpack (= 7.0.4.3) + activejob (= 7.0.4.3) + activerecord (= 7.0.4.3) + activesupport (= 7.0.4.3) marcel (~> 1.0) mini_mime (>= 1.1.0) activestorage-openstack (1.5.1) fog-openstack (~> 1.0) marcel rails (>= 5.2.2) - activesupport (6.1.7.1) + activesupport (7.0.4.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) administrate (0.18.0) @@ -95,12 +101,10 @@ GEM aes_key_wrap (1.1.0) after_party (1.11.2) anchored (1.1.0) - annotate (3.1.1) - activerecord (>= 3.2, < 7.0) + annotate (3.2.0) + activerecord (>= 3.2, < 8.0) rake (>= 10.4, < 14.0) ast (2.4.2) - attr_encrypted (3.1.0) - encryptor (~> 3.0.0) attr_required (1.0.1) axe-core-api (4.2.1) capybara @@ -119,7 +123,7 @@ GEM axlsx_styler (1.1.0) activesupport (>= 3.1) caxlsx (>= 2.0.2) - bcrypt (3.1.16) + bcrypt (3.1.18) better_html (1.0.16) actionview (>= 4.0) activesupport (>= 4.0) @@ -175,14 +179,15 @@ GEM css_parser (1.9.0) addressable daemons (1.3.1) - deep_cloneable (3.0.0) - activerecord (>= 3.1.0, < 7) + date (3.3.3) + deep_cloneable (3.2.0) + activerecord (>= 3.1.0, < 8) delayed_cron_job (0.7.4) delayed_job (>= 4.1) delayed_job (4.1.11) activesupport (>= 3.0, < 8.0) - delayed_job_active_record (4.1.5) - activerecord (>= 3.0, < 6.2) + delayed_job_active_record (4.1.7) + activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) delayed_job_web (1.4.4) activerecord (> 3.0.0) @@ -191,7 +196,7 @@ GEM sinatra (>= 1.4.4) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.7.3) + devise (4.9.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -199,16 +204,14 @@ GEM warden (~> 1.2.3) devise-i18n (1.9.2) devise (>= 4.7.1) - devise-two-factor (4.0.2) - activesupport (< 7.1) - attr_encrypted (>= 1.3, < 4, != 2) + devise-two-factor (5.0.0) + activesupport (~> 7.0) devise (~> 4.0) - railties (< 7.1) + railties (~> 7.0) rotp (~> 6.0) - diff-lcs (1.4.4) - digest (3.1.0) - discard (1.2.0) - activerecord (>= 4.2, < 7) + diff-lcs (1.5.0) + discard (1.2.1) + activerecord (>= 4.2, < 8) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) @@ -224,7 +227,6 @@ GEM concurrent-ruby (~> 1.0) http (>= 3.0) ruby2_keywords - encryptor (3.0.0) erubi (1.12.0) et-orbi (1.2.4) tzinfo @@ -285,7 +287,7 @@ GEM raabro (~> 1.4) geo_coord (0.2.0) geocoder (1.6.5) - globalid (1.0.1) + globalid (1.1.0) activesupport (>= 5.0) gon (6.4.0) actionpack (>= 3.0.20) @@ -341,7 +343,7 @@ GEM http-form_data (2.3.0) http_accept_language (2.1.1) httpclient (2.8.3) - i18n (1.12.0) + i18n (1.13.0) concurrent-ruby (~> 1.0) i18n-tasks (1.0.9) activesupport (>= 4.0.2) @@ -362,7 +364,6 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (2.0.0) rails (>= 5.0) - io-wait (0.2.1) ipaddress (0.8.3) jquery-rails (4.5.1) rails-dom-testing (>= 1, < 3) @@ -412,10 +413,10 @@ GEM railties (>= 4) request_store (~> 1.0) logstash-event (1.2.02) - loofah (2.19.1) + loofah (2.20.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.8.0.1) + mail (2.8.1) mini_mime (>= 0.1.1) net-imap net-pop @@ -436,28 +437,24 @@ GEM rake mini_magick (4.11.0) mini_mime (1.1.2) - mini_portile2 (2.8.1) + mini_portile2 (2.8.2) minitest (5.18.0) msgpack (1.4.2) multi_json (1.15.0) multipart-post (2.1.1) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) - net-imap (0.2.3) - digest + net-imap (0.3.4) + date net-protocol - strscan - net-pop (0.1.1) - digest + net-pop (0.1.2) net-protocol + net-protocol (0.2.1) timeout - net-protocol (0.1.1) - io-wait - timeout - net-smtp (0.2.1) + net-smtp (0.3.3) net-protocol netrc (0.11.0) - nio4r (2.5.8) + nio4r (2.5.9) nokogiri (1.14.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) @@ -478,7 +475,7 @@ GEM parser (3.2.2.0) ast (~> 2.4.1) pdf-core (0.9.0) - pg (1.2.3) + pg (1.4.6) phonelib (0.6.53) prawn (2.4.0) pdf-core (~> 0.9.0) @@ -497,12 +494,12 @@ GEM actionmailer (>= 3) premailer (~> 1.7, >= 1.7.9) promise.rb (0.7.4) - pry (0.13.1) + pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - pry-byebug (3.9.0) + pry-byebug (3.10.1) byebug (~> 11.0) - pry (~> 0.13.0) + pry (>= 0.13, < 0.15) pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (5.0.1) @@ -512,7 +509,7 @@ GEM activesupport (>= 3.0.0) raabro (1.4.0) racc (1.6.2) - rack (2.2.6.4) + rack (2.2.7) rack-attack (6.5.0) rack (>= 1.0, < 3) rack-mini-profiler (3.0.0) @@ -532,21 +529,20 @@ GEM rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (6.1.7.1) - actioncable (= 6.1.7.1) - actionmailbox (= 6.1.7.1) - actionmailer (= 6.1.7.1) - actionpack (= 6.1.7.1) - actiontext (= 6.1.7.1) - actionview (= 6.1.7.1) - activejob (= 6.1.7.1) - activemodel (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + rails (7.0.4.3) + actioncable (= 7.0.4.3) + actionmailbox (= 7.0.4.3) + actionmailer (= 7.0.4.3) + actionpack (= 7.0.4.3) + actiontext (= 7.0.4.3) + actionview (= 7.0.4.3) + activejob (= 7.0.4.3) + activemodel (= 7.0.4.3) + activerecord (= 7.0.4.3) + activestorage (= 7.0.4.3) + activesupport (= 7.0.4.3) bundler (>= 1.15.0) - railties (= 6.1.7.1) - sprockets-rails (>= 2.0.0) + railties (= 7.0.4.3) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -564,12 +560,13 @@ GEM rails-i18n (7.0.3) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (6.1.7.1) - actionpack (= 6.1.7.1) - activesupport (= 6.1.7.1) + railties (7.0.4.3) + actionpack (= 7.0.4.3) + activesupport (= 7.0.4.3) method_source rake (>= 12.2) thor (~> 1.0) + zeitwerk (~> 2.5) rainbow (3.1.1) rake (13.0.6) rake-progressbar (0.0.5) @@ -580,9 +577,9 @@ GEM regexp_parser (2.8.0) request_store (1.5.0) rack (>= 1.4) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) + responders (3.1.0) + actionpack (>= 5.2) + railties (>= 5.2) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) @@ -596,29 +593,29 @@ GEM builder (>= 3.0) dry-inflector (~> 0.1) rubyzip (>= 1.0) - rotp (6.2.0) + rotp (6.2.2) rouge (3.30.0) rqrcode (1.2.0) chunky_png (~> 1.0) rqrcode_core (~> 0.2) rqrcode_core (0.2.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-rails (5.0.0) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.10.2) + rspec-support (~> 3.12.0) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-support (3.12.0) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.50.2) @@ -718,7 +715,7 @@ GEM axlsx_styler (>= 1.0.0, < 2) caxlsx (>= 2.0.2, < 4) rodf (>= 1.0.0, < 2) - spring (2.1.1) + spring (4.1.1) spring-commands-rspec (1.0.4) spring (>= 0.9.1) sprockets (4.2.0) @@ -731,7 +728,6 @@ GEM stackprof (0.2.21) strong_migrations (0.8.0) activerecord (>= 5.2) - strscan (3.0.4) swd (1.3.0) activesupport (>= 3) attr_required (>= 0.0.5) @@ -744,7 +740,7 @@ GEM thread_safe (0.3.6) tilt (2.0.11) timecop (0.9.4) - timeout (0.1.1) + timeout (0.3.2) ttfunk (1.7.0) turbo-rails (1.3.2) actionpack (>= 6.0.0) @@ -767,8 +763,9 @@ GEM activemodel (>= 3.0.0) public_suffix vcr (6.1.0) - view_component (2.63.0) - activesupport (>= 5.0.0, < 8.0) + view_component (2.82.0) + activesupport (>= 5.2.0, < 8.0) + concurrent-ruby (~> 1.0) method_source (~> 1.0) virtus (2.0.0) axiom-types (~> 0.1) @@ -815,7 +812,7 @@ GEM nokogiri (~> 1.11) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.7) + zeitwerk (2.6.8) zip_tricks (5.6.0) zipline (1.4.1) actionpack (>= 6.0, < 8.0) @@ -911,7 +908,7 @@ DEPENDENCIES rack-attack rack-mini-profiler rack_session_access - rails + rails (~> 7.0.4) rails-controller-testing rails-erd rails-i18n diff --git a/app/components/attachment/edit_component.rb b/app/components/attachment/edit_component.rb index d21199de5..37d6ffe62 100644 --- a/app/components/attachment/edit_component.rb +++ b/app/components/attachment/edit_component.rb @@ -93,7 +93,7 @@ class Attachment::EditComponent < ApplicationComponent nil end - def field_name + def field_name(object_name = nil, method_name = nil, *method_names, multiple: false, index: nil) helpers.field_name(@form_object_name || ActiveModel::Naming.param_key(@attached_file.record), attribute_name) end diff --git a/app/components/dossiers/export_component/export_component.html.haml b/app/components/dossiers/export_component/export_component.html.haml index 12bc03cd7..d60b6b490 100644 --- a/app/components/dossiers/export_component/export_component.html.haml +++ b/app/components/dossiers/export_component/export_component.html.haml @@ -11,7 +11,7 @@ - elsif export.available? - menu.with_item do %div - = link_to ready_link_label(export), export.file.service_url, target: "_blank", rel: "noopener", role: 'menuitem' + = link_to ready_link_label(export), export.file.url, target: "_blank", rel: "noopener", role: 'menuitem' - if export.old? = button_to download_export_path(export_format: export.format, force_export: true), refresh_button_options(export).merge(role: 'menuitem') do .icon.retry diff --git a/app/controllers/administrateurs/exports_controller.rb b/app/controllers/administrateurs/exports_controller.rb index 44d953356..c8e105db1 100644 --- a/app/controllers/administrateurs/exports_controller.rb +++ b/app/controllers/administrateurs/exports_controller.rb @@ -15,7 +15,7 @@ module Administrateurs end format.html do - redirect_to export.file.service_url + redirect_to url_from(export.file.url) end end else diff --git a/app/controllers/agent_connect/agent_controller.rb b/app/controllers/agent_connect/agent_controller.rb index 18a781235..15d9f16d1 100644 --- a/app/controllers/agent_connect/agent_controller.rb +++ b/app/controllers/agent_connect/agent_controller.rb @@ -15,7 +15,7 @@ class AgentConnect::AgentController < ApplicationController cookies.encrypted[STATE_COOKIE_NAME] = state cookies.encrypted[NONCE_COOKIE_NAME] = nonce - redirect_to uri + redirect_to uri, allow_other_host: true end def callback diff --git a/app/controllers/france_connect/particulier_controller.rb b/app/controllers/france_connect/particulier_controller.rb index 5817a3185..92ae65efa 100644 --- a/app/controllers/france_connect/particulier_controller.rb +++ b/app/controllers/france_connect/particulier_controller.rb @@ -4,7 +4,7 @@ class FranceConnect::ParticulierController < ApplicationController def login if FranceConnectService.enabled? - redirect_to FranceConnectService.authorization_uri + redirect_to FranceConnectService.authorization_uri, allow_other_host: true else redirect_to new_user_session_path end diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 47c930eae..2f3ec8a82 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -19,7 +19,7 @@ module Instructeurs def attestation if dossier.attestation.pdf.attached? - redirect_to dossier.attestation.pdf.service_url + redirect_to dossier.attestation.pdf.url end end diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 5e497ddc6..74f46a0cd 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -175,7 +175,7 @@ module Instructeurs end format.html do - redirect_to export.file.service_url + redirect_to url_from(export.file.url) end end else diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 022f79bee..96a67addc 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -73,7 +73,7 @@ module Users def attestation if dossier.attestation&.pdf&.attached? - redirect_to dossier.attestation.pdf.service_url + redirect_to dossier.attestation.pdf.url else flash.notice = t('.no_longer_available') redirect_to dossier_path(dossier) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 276a3e716..41cbb9254 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -36,7 +36,7 @@ class Users::SessionsController < Devise::SessionsController case connected_with_france_connect when User.loged_in_with_france_connects.fetch(:particulier) - redirect_to FRANCE_CONNECT[:particulier][:logout_endpoint] + redirect_to FRANCE_CONNECT[:particulier][:logout_endpoint], allow_other_host: true return end end diff --git a/app/graphql/loaders/association.rb b/app/graphql/loaders/association.rb index 693bc9b58..cf7257a6a 100644 --- a/app/graphql/loaders/association.rb +++ b/app/graphql/loaders/association.rb @@ -42,7 +42,10 @@ module Loaders end def preload_association(records) - ::ActiveRecord::Associations::Preloader.new.preload(records, @association_schema) + ::ActiveRecord::Associations::Preloader.new( + records: records, + associations: @association_schema + ).call end def read_association(record) diff --git a/app/graphql/types/file.rb b/app/graphql/types/file.rb index 22a8e1afd..9845a92ee 100644 --- a/app/graphql/types/file.rb +++ b/app/graphql/types/file.rb @@ -11,7 +11,7 @@ module Types if object.is_a?(Hash) object[:url] else - object.service_url + object.url end end end diff --git a/app/helpers/form_tag_helper.rb b/app/helpers/form_tag_helper.rb deleted file mode 100644 index 68971b454..000000000 --- a/app/helpers/form_tag_helper.rb +++ /dev/null @@ -1,39 +0,0 @@ -module FormTagHelper - # from Rails 7 ActionView::Helpers::FormTagHelper - # https://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-field_id - # Should be removed when we upgrade to Rails 7 - def field_id(object_name, method_name, *suffixes, index: nil, namespace: nil) - if object_name.respond_to?(:model_name) - object_name = object_name.model_name.singular - end - - sanitized_object_name = object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_") - - sanitized_method_name = method_name.to_s.delete_suffix("?") - - [ - namespace, - sanitized_object_name.presence, - (index unless sanitized_object_name.empty?), - sanitized_method_name, - *suffixes - ].tap(&:compact!).join("_") - end - - # from Rails 7 ActionView::Helpers::FormTagHelper - # https://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-field_name - # Should be removed when we upgrade to Rails 7 - def field_name(object_name, method_name, *method_names, multiple: false, index: nil) - names = method_names.map! { |name| "[#{name}]" }.join - - # a little duplication to construct fewer strings - case - when object_name.blank? - "#{method_name}#{names}#{multiple ? "[]" : ""}" - when index - "#{object_name}[#{index}][#{method_name}]#{names}#{multiple ? "[]" : ""}" - else - "#{object_name}[#{method_name}]#{names}#{multiple ? "[]" : ""}" - end - end -end diff --git a/app/jobs/cron/datagouv/export_and_publish_demarches_publiques_job.rb b/app/jobs/cron/datagouv/export_and_publish_demarches_publiques_job.rb index 095e9b1bd..c11b8eec4 100644 --- a/app/jobs/cron/datagouv/export_and_publish_demarches_publiques_job.rb +++ b/app/jobs/cron/datagouv/export_and_publish_demarches_publiques_job.rb @@ -5,7 +5,7 @@ class Cron::Datagouv::ExportAndPublishDemarchesPubliquesJob < Cron::CronJob def perform(*args) gzip_filepath = [ 'tmp/', - Time.zone.now.to_formatted_s(:number), + Time.zone.now.to_fs(:number), '-demarches.json.gz' ].join diff --git a/app/models/champs/boolean_champ.rb b/app/models/champs/boolean_champ.rb index 562fc3dee..5539369dc 100644 --- a/app/models/champs/boolean_champ.rb +++ b/app/models/champs/boolean_champ.rb @@ -17,6 +17,7 @@ # etablissement_id :integer # external_id :string # parent_id :bigint +# row_id :string # type_de_champ_id :integer # class Champs::BooleanChamp < Champ diff --git a/app/models/champs/piece_justificative_champ.rb b/app/models/champs/piece_justificative_champ.rb index 6ac018a07..f7e7a878b 100644 --- a/app/models/champs/piece_justificative_champ.rb +++ b/app/models/champs/piece_justificative_champ.rb @@ -55,7 +55,7 @@ class Champs::PieceJustificativeChamp < Champ return nil if attachment.nil? if attachment.virus_scanner.safe? || attachment.virus_scanner.pending? - attachment.service_url + attachment.url end end end diff --git a/app/models/champs/rna_champ.rb b/app/models/champs/rna_champ.rb index 781e21014..5bf7c78f0 100644 --- a/app/models/champs/rna_champ.rb +++ b/app/models/champs/rna_champ.rb @@ -13,12 +13,12 @@ # value_json :jsonb # created_at :datetime # updated_at :datetime -# dossier_id :integer not null +# dossier_id :integer # etablissement_id :integer # external_id :string # parent_id :bigint -# type_de_champ_id :integer not null # row_id :string +# type_de_champ_id :integer # class Champs::RNAChamp < Champ include RNAChampAssociationFetchableConcern diff --git a/app/models/concerns/blob_signed_id_concern.rb b/app/models/concerns/blob_signed_id_concern.rb index 8e7d1e09b..f12b2616d 100644 --- a/app/models/concerns/blob_signed_id_concern.rb +++ b/app/models/concerns/blob_signed_id_concern.rb @@ -5,8 +5,8 @@ module BlobSignedIdConcern # We override signed_id to add `expires_in` option to generated hash. # This is a measure to ensure that we never under any circumstance # expose permanent attachment url - def signed_id - ActiveStorage.verifier.generate(id, purpose: :blob_id, expires_in: Rails.application.config.active_storage.service_urls_expire_in) + def signed_id(**options) + ActiveStorage.verifier.generate(id, **options, purpose: :blob_id, expires_in: Rails.application.config.active_storage.service_urls_expire_in) end end end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 8eb6e95b5..7ad38bb52 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -31,9 +31,9 @@ # motivation :text # prefill_token :string # prefilled :boolean -# private_search_terms :text +# private_search_terms :string # processed_at :datetime -# search_terms :text +# search_terms :string # state :string # termine_close_to_expiration_notice_sent_at :datetime # created_at :datetime diff --git a/app/models/export.rb b/app/models/export.rb index fa8c6910e..d9f3b4c8d 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -86,7 +86,7 @@ class Export < ApplicationRecord def flash_message if available? - "L’export au format \"#{format}\" est prêt. Vous pouvez le télécharger" + "L’export au format \"#{format}\" est prêt. Vous pouvez le télécharger" else "Nous générons cet export. Veuillez revenir dans quelques minutes pour le télécharger." end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 019c0cd09..b40c8080f 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # aasm_state :string default("brouillon") +# allow_expert_messaging :boolean default(TRUE), not null # allow_expert_review :boolean default(TRUE), not null # api_entreprise_token :string # api_particulier_scopes :text default([]), is an Array @@ -17,10 +18,10 @@ # description :string # dossiers_count_computed_at :datetime # duree_conservation_dossiers_dans_ds :integer -# duree_conservation_etendue_par_ds :boolean default(FALSE) +# duree_conservation_etendue_par_ds :boolean default(FALSE), not null # encrypted_api_particulier_token :string -# estimated_duration_visible :boolean default(TRUE), not null # estimated_dossiers_count :integer +# estimated_duration_visible :boolean default(TRUE), not null # euro_flag :boolean default(FALSE) # experts_require_administrateur_invitation :boolean default(FALSE) # for_individual :boolean default(FALSE) @@ -28,11 +29,10 @@ # instructeurs_self_management_enabled :boolean # juridique_required :boolean default(TRUE) # libelle :string -# lien_demarche :string # lien_dpo :string # lien_notice :string # lien_site_web :string -# max_duree_conservation_dossiers_dans_ds :integer default(12) +# max_duree_conservation_dossiers_dans_ds :integer default(12), not null # migrated_champ_routage :boolean # monavis_embed :text # opendata :boolean default(TRUE) diff --git a/app/models/super_admin.rb b/app/models/super_admin.rb index 9fe9b4590..c7a1f9926 100644 --- a/app/models/super_admin.rb +++ b/app/models/super_admin.rb @@ -16,6 +16,7 @@ # last_sign_in_ip :string # locked_at :datetime # otp_required_for_login :boolean +# otp_secret :string # remember_created_at :datetime # reset_password_sent_at :datetime # reset_password_token :string @@ -43,6 +44,7 @@ class SuperAdmin < ApplicationRecord def disable_otp! self.assign_attributes( { + otp_secret: nil, encrypted_otp_secret: nil, encrypted_otp_secret_iv: nil, encrypted_otp_secret_salt: nil, @@ -66,4 +68,75 @@ class SuperAdmin < ApplicationRecord def send_devise_notification(notification, *args) devise_mailer.send(notification, self, *args).deliver_later end + + private + + # From https://github.com/tinfoil/devise-two-factor/blob/main/UPGRADING.md + # Remove me after super admin have been migrated to the new OTP system. + # Decrypt and return the `encrypted_otp_secret` attribute which was used in + # prior versions of devise-two-factor + # @return [String] The decrypted OTP secret + def legacy_otp_secret + return nil unless self[:encrypted_otp_secret] + return nil unless self.class.otp_secret_encryption_key + + hmac_iterations = 2000 # a default set by the Encryptor gem + key = self.class.otp_secret_encryption_key + salt = Base64.decode64(encrypted_otp_secret_salt) + iv = Base64.decode64(encrypted_otp_secret_iv) + + raw_cipher_text = Base64.decode64(encrypted_otp_secret) + # The last 16 bytes of the ciphertext are the authentication tag - we use + # Galois Counter Mode which is an authenticated encryption mode + cipher_text = raw_cipher_text[0..-17] + auth_tag = raw_cipher_text[-16..-1] + + # this alrorithm lifted from + # https://github.com/attr-encrypted/encryptor/blob/master/lib/encryptor.rb#L54 + + # create an OpenSSL object which will decrypt the AES cipher with 256 bit + # keys in Galois Counter Mode (GCM). See + # https://ruby.github.io/openssl/OpenSSL/Cipher.html + cipher = OpenSSL::Cipher.new('aes-256-gcm') + + # tell the cipher we want to decrypt. Symmetric algorithms use a very + # similar process for encryption and decryption, hence the same object can + # do both. + cipher.decrypt + + # Use a Password-Based Key Derivation Function to generate the key actually + # used for encryptoin from the key we got as input. + cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, salt, hmac_iterations, cipher.key_len) + + # set the Initialization Vector (IV) + cipher.iv = iv + + # The tag must be set after calling Cipher#decrypt, Cipher#key= and + # Cipher#iv=, but before calling Cipher#final. After all decryption is + # performed, the tag is verified automatically in the call to Cipher#final. + # + # If the auth_tag does not verify, then #final will raise OpenSSL::Cipher::CipherError + cipher.auth_tag = auth_tag + + # auth_data must be set after auth_tag has been set when decrypting See + # http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-auth_data-3D + # we are not adding any authenticated data but OpenSSL docs say this should + # still be called. + cipher.auth_data = '' + + # #update is (somewhat confusingly named) the method which actually + # performs the decryption on the given chunk of data. Our OTP secret is + # short so we only need to call it once. + # + # It is very important that we call #final because: + # + # 1. The authentication tag is checked during the call to #final + # 2. Block based cipher modes (e.g. CBC) work on fixed size chunks. We need + # to call #final to get it to process the last chunk properly. The output + # of #final should be appended to the decrypted value. This isn't + # required for streaming cipher modes but including it is a best practice + # so that your code will continue to function correctly even if you later + # change to a block cipher mode. + cipher.update(cipher_text) + cipher.final + end end diff --git a/app/models/trusted_device_token.rb b/app/models/trusted_device_token.rb index 06d84a4a9..53ba9fa9c 100644 --- a/app/models/trusted_device_token.rb +++ b/app/models/trusted_device_token.rb @@ -3,7 +3,7 @@ # Table name: trusted_device_tokens # # id :bigint not null, primary key -# token :string not null +# token :string # created_at :datetime not null # updated_at :datetime not null # instructeur_id :bigint diff --git a/app/validators/jwt_token_validator.rb b/app/validators/jwt_token_validator.rb index ec1ca427d..031a9d1ab 100644 --- a/app/validators/jwt_token_validator.rb +++ b/app/validators/jwt_token_validator.rb @@ -3,7 +3,7 @@ class JwtTokenValidator < ActiveModel::EachValidator begin JWT.decode value, nil, false rescue - record.errors[attribute] << (options[:message] || "n'est pas un jeton valide") + record.errors.add attribute, :invalid, message: (options[:message] || "n'est pas un jeton valide") end end end diff --git a/app/validators/mon_avis_embed_validator.rb b/app/validators/mon_avis_embed_validator.rb index 4e4483988..b4fb33f59 100644 --- a/app/validators/mon_avis_embed_validator.rb +++ b/app/validators/mon_avis_embed_validator.rb @@ -3,7 +3,7 @@ class MonAvisEmbedValidator < ActiveModel::Validator # We need to ensure the embed code is not any random string in order to avoid injections r = Regexp.new('\s*Je donne mon avis\s*', Regexp::MULTILINE) if record.monavis_embed.present? && !r.match?(record.monavis_embed) - record.errors[:base] << "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme." + record.errors.add :base, :invalid, message: "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme." end end end diff --git a/bin/rake b/bin/rake index 7327f471e..4fbf10b96 100755 --- a/bin/rake +++ b/bin/rake @@ -1,5 +1,4 @@ #!/usr/bin/env ruby -load File.expand_path("spring", __dir__) require_relative "../config/boot" require "rake" Rake.application.run diff --git a/bin/setup b/bin/setup index f07a41744..0d283a126 100755 --- a/bin/setup +++ b/bin/setup @@ -2,7 +2,7 @@ require "fileutils" # path to your application root. -APP_ROOT = File.expand_path('..', __dir__) +APP_ROOT = File.expand_path("..", __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") @@ -13,9 +13,9 @@ FileUtils.chdir APP_ROOT do # This script is idempotent, so that you can run it at any time and get an expectable outcome. # Add necessary setup steps to this file. - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") # Install JavaScript dependencies system! 'node --version' @@ -29,13 +29,17 @@ FileUtils.chdir APP_ROOT do FileUtils.cp 'config/env.example', '.env' end - # Create the database, load the schema, and initialize it with the seed data + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + puts "\n== Preparing database ==" - system! 'bin/rails db:prepare' + system! "bin/rails db:prepare" puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' + system! "bin/rails log:clear tmp:clear" puts "\n== Restarting application server ==" - system! 'bin/rails restart' + system! "bin/rails restart" end diff --git a/config/application.rb b/config/application.rb index cf437e1c9..cf264ec08 100644 --- a/config/application.rb +++ b/config/application.rb @@ -98,5 +98,9 @@ module TPS html_tag.html_safe # this is generated by rails end # rubocop:enable Rails/OutputSafety + # + + config.active_record.encryption.primary_key = Rails.application.secrets.active_record_encryption.fetch(:primary_key) + config.active_record.encryption.key_derivation_salt = Rails.application.secrets.active_record_encryption.fetch(:key_derivation_salt) end end diff --git a/config/env.example b/config/env.example index 978dfd183..a3624b572 100644 --- a/config/env.example +++ b/config/env.example @@ -142,6 +142,10 @@ API_EDUCATION_URL="https://data.education.gouv.fr/api/records/1.0" # Encryption key for sensitive columns in the database ENCRYPTION_SERVICE_SALT="" +# ActiveRecord encryption keys. Generate them with bin/rails db:encryption:init (you can omit deterministic_key) +AR_ENCRYPTION_PRIMARY_KEY="" +AR_ENCRYPTION_KEY_DERIVATION_SALT="" + # Salt for invisible_captcha session data. # Must be the same value for all app instances behind a load-balancer. INVISIBLE_CAPTCHA_SECRET="kikooloool" diff --git a/config/initializers/cookie_rotator.rb b/config/initializers/cookie_rotator.rb new file mode 100644 index 000000000..63d4fabe5 --- /dev/null +++ b/config/initializers/cookie_rotator.rb @@ -0,0 +1,18 @@ +# TODO: Enable cookies rotation when new SHA256 will be enforced +# See new_framework_defaults_7.0.rb +# key_generator_hash_digest_class = OpenSSL::Digest::SHA256 will be +# +# Rails.application.config.after_initialize do +# Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| +# salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt +# secret_key_base = Rails.application.secret_key_base + +# key_generator = ActiveSupport::KeyGenerator.new( +# secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 +# ) +# key_len = ActiveSupport::MessageEncryptor.key_len +# secret = key_generator.generate_key(salt, key_len) + +# cookies.rotate :encrypted, secret +# end +# end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 18349e833..83c408320 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -227,7 +227,7 @@ Devise.setup do |config| # should add them to the navigational formats lists. # # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ['*/*', :html] + # config.navigational_formats = ['*/*', :html, :turbo_stream] # The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :delete @@ -253,4 +253,12 @@ Devise.setup do |config| # When using omniauth, Devise cannot automatically set Omniauth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' + + # When using Devise with Hotwire/Turbo, the http status for error responses + # and some redirects must match the following. The default in Devise for existing + # apps is `200 OK` and `302 Found respectively`, but new apps are generated with + # these new defaults that match Hotwire/Turbo behavior. + # Note: These might become the new default in future versions of Devise. + config.responder.error_status = :unprocessable_entity + config.responder.redirect_status = :see_other end diff --git a/config/initializers/dolist.rb b/config/initializers/dolist.rb index b38a97e2c..7835b532a 100644 --- a/config/initializers/dolist.rb +++ b/config/initializers/dolist.rb @@ -1,3 +1,5 @@ ActiveSupport.on_load(:action_mailer) do + require "dolist/api_sender" + ActionMailer::Base.add_delivery_method :dolist_api, Dolist::APISender end diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb index 422c6906d..3a80f22af 100644 --- a/config/initializers/lograge.rb +++ b/config/initializers/lograge.rb @@ -40,8 +40,10 @@ Rails.application.configure do config.lograge.keep_original_rails_log = true config.lograge.logger = ActiveSupport::Logger.new(Rails.root.join('log', "logstash_#{Rails.env}.log")) +end - if config.lograge.enabled +Rails.application.config.after_initialize do |app| + if app.config.lograge.enabled ActiveJob::ApplicationLogSubscriber.attach_to(:active_job) end end diff --git a/config/initializers/mail_observers.rb b/config/initializers/mail_observers.rb index 513d7cd1c..985682909 100644 --- a/config/initializers/mail_observers.rb +++ b/config/initializers/mail_observers.rb @@ -1,6 +1,8 @@ # Must be registered *before* loading custom delivery methods # otherwise the observer won't be invoked. # +require_relative "../../app/services/email_delivery_observer" + ActiveSupport.on_load(:action_mailer) do |mailer| mailer.register_observer EmailDeliveryObserver end diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb new file mode 100644 index 000000000..b90fb14e4 --- /dev/null +++ b/config/initializers/new_framework_defaults_7_0.rb @@ -0,0 +1,133 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 7.0 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `7.0`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +# `button_to` view helper will render `