Skip to content

Commit

Permalink
Ensure ActiveRecord::Encryption.config is always ready before access.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
maximerety committed Aug 24, 2024
1 parent 0794abb commit 6c2d1f9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 2 deletions.
15 changes: 15 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
* 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`.

*Maxime Réty*

* Support use of alternative database interfaces via the `database_cli` ActiveRecord configuration option.

```ruby
Expand Down
2 changes: 2 additions & 0 deletions activerecord/lib/active_record/encryption.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ def self.eager_load!
Cipher.eager_load!
end
end

ActiveSupport.run_load_hooks :active_record_encryption, Encryption
end
7 changes: 5 additions & 2 deletions activerecord/lib/active_record/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -356,16 +356,19 @@ class Railtie < Rails::Railtie # :nodoc:
end

initializer "active_record_encryption.configuration" do |app|
ActiveSupport.on_load(:active_record) do
ActiveRecord::Encryption.configure \
ActiveSupport.on_load(:active_record_encryption) do
ActiveRecord::Encryption.configure(
primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
**app.config.active_record.encryption
)

auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
end

ActiveSupport.on_load(:active_record) do
# Support extended queries for deterministic attributes and validations
if ActiveRecord::Encryption.config.extend_queries
ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
Expand Down
1 change: 1 addition & 0 deletions guides/source/configuring.md
Original file line number Diff line number Diff line change
Expand Up @@ -3755,6 +3755,7 @@ These are the load hooks you can use in your own code. To hook into the initiali
| `ActiveModel::Model` | `active_model` |
| `ActiveModel::Translation` | `active_model_translation` |
| `ActiveRecord::Base` | `active_record` |
| `ActiveRecord::Encryption` | `active_record_encryption` |
| `ActiveRecord::TestFixtures` | `active_record_fixtures` |
| `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` | `active_record_postgresqladapter` |
| `ActiveRecord::ConnectionAdapters::Mysql2Adapter` | `active_record_mysql2adapter` |
Expand Down
23 changes: 23 additions & 0 deletions railties/test/application/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3731,6 +3731,29 @@ class Post < ActiveRecord::Base
assert_not_includes ActiveRecord::Base.filter_attributes, :content
end

test "ActiveRecord::Encryption.config is ready when accessed before loading ActiveRecord::Base" do
add_to_config <<-RUBY
config.enable_reloading = false
config.eager_load = false
config.active_record.encryption.primary_key = "dummy_key"
config.active_record.encryption.extend_queries = true
RUBY

app "development"

# Encryption config is ready to be accessed
assert_equal "dummy_key", ActiveRecord::Encryption.config.primary_key
assert ActiveRecord::Encryption.config.extend_queries

# ActiveRecord::Base is not loaded yet (lazy loading preserved)
active_record_loaded = ActiveRecord.autoload?(:Base).nil?
assert_not active_record_loaded

# When ActiveRecord::Base loaded, extended queries should be installed
assert ActiveRecord::Base.include?(ActiveRecord::Encryption::ExtendedDeterministicQueries::CoreQueries)
end

test "ActiveRecord::Encryption.config is ready for encrypted attributes when app is lazy loaded" do
add_to_config <<-RUBY
config.enable_reloading = false
Expand Down

0 comments on commit 6c2d1f9

Please sign in to comment.