Skip to content

Commit 6f7f624

Browse files
maximeretyrafaelfranca
authored andcommitted
Ensure ActiveRecord::Encryption.config is always ready before access.
Previously, ActiveRecord::Encryption configuration was deferred until ActiveRecord::Base was loaded. Therefore, accessing ActiveRecord::Encryption.config properties before ActiveRecord::Base was loaded would give incorrect results. ActiveRecord::Encryption now has its own loading hook so that its configuration is set as soon as needed. When ActiveRecord::Base is loaded, even lazily, it in turn triggers the loading of ActiveRecord::Encryption, thus preserving the original behavior of having its config ready before any use of ActiveRecord::Base.
1 parent 7059d3c commit 6f7f624

File tree

5 files changed

+46
-2
lines changed

5 files changed

+46
-2
lines changed

activerecord/CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
2+
3+
Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
4+
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
5+
`ActiveRecord::Base` was loaded would give incorrect results.
6+
7+
`ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
8+
soon as needed.
9+
10+
When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
11+
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
12+
before any use of `ActiveRecord::Base`.
13+
14+
*Maxime Réty*
15+
116
* Add `TimeZoneConverter#==` method, so objects will be properly compared by
217
their type, scale, limit & precision.
318

activerecord/lib/active_record/encryption.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ def self.eager_load!
5353
Cipher.eager_load!
5454
end
5555
end
56+
57+
ActiveSupport.run_load_hooks :active_record_encryption, Encryption
5658
end

activerecord/lib/active_record/railtie.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,16 +356,19 @@ class Railtie < Rails::Railtie # :nodoc:
356356
end
357357

358358
initializer "active_record_encryption.configuration" do |app|
359-
ActiveSupport.on_load(:active_record) do
360-
ActiveRecord::Encryption.configure \
359+
ActiveSupport.on_load(:active_record_encryption) do
360+
ActiveRecord::Encryption.configure(
361361
primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
362362
deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
363363
key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
364364
**app.config.active_record.encryption
365+
)
365366

366367
auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
367368
auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
369+
end
368370

371+
ActiveSupport.on_load(:active_record) do
369372
# Support extended queries for deterministic attributes and validations
370373
if ActiveRecord::Encryption.config.extend_queries
371374
ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support

guides/source/configuring.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,6 +3755,7 @@ These are the load hooks you can use in your own code. To hook into the initiali
37553755
| `ActiveModel::Model` | `active_model` |
37563756
| `ActiveModel::Translation` | `active_model_translation` |
37573757
| `ActiveRecord::Base` | `active_record` |
3758+
| `ActiveRecord::Encryption` | `active_record_encryption` |
37583759
| `ActiveRecord::TestFixtures` | `active_record_fixtures` |
37593760
| `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` | `active_record_postgresqladapter` |
37603761
| `ActiveRecord::ConnectionAdapters::Mysql2Adapter` | `active_record_mysql2adapter` |

railties/test/application/configuration_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,6 +3731,29 @@ class Post < ActiveRecord::Base
37313731
assert_not_includes ActiveRecord::Base.filter_attributes, :content
37323732
end
37333733

3734+
test "ActiveRecord::Encryption.config is ready when accessed before loading ActiveRecord::Base" do
3735+
add_to_config <<-RUBY
3736+
config.enable_reloading = false
3737+
config.eager_load = false
3738+
3739+
config.active_record.encryption.primary_key = "dummy_key"
3740+
config.active_record.encryption.extend_queries = true
3741+
RUBY
3742+
3743+
app "development"
3744+
3745+
# Encryption config is ready to be accessed
3746+
assert_equal "dummy_key", ActiveRecord::Encryption.config.primary_key
3747+
assert ActiveRecord::Encryption.config.extend_queries
3748+
3749+
# ActiveRecord::Base is not loaded yet (lazy loading preserved)
3750+
active_record_loaded = ActiveRecord.autoload?(:Base).nil?
3751+
assert_not active_record_loaded
3752+
3753+
# When ActiveRecord::Base loaded, extended queries should be installed
3754+
assert ActiveRecord::Base.include?(ActiveRecord::Encryption::ExtendedDeterministicQueries::CoreQueries)
3755+
end
3756+
37343757
test "ActiveRecord::Encryption.config is ready for encrypted attributes when app is lazy loaded" do
37353758
add_to_config <<-RUBY
37363759
config.enable_reloading = false

0 commit comments

Comments
 (0)