mirror of https://github.com/rails/rails
[Fix #50604] Restore compatibility of ARE configs with eager loading mode
Configure ActiveRecord::Encryption (ARE) on ActiveRecord::Base (AR) loading, so that ARE configs are ready before AR models start using `encrypts` to declare encrypted attributes. This means that you can add ARE configurations in initializers, as long as you don't trigger the loading of ActiveRecord::Base or your AR models in prior initializers.
This commit is contained in:
parent
f5910f74d4
commit
d997c554b3
|
@ -1,3 +1,9 @@
|
|||
* Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
|
||||
of Active Record models, when an application is eager loaded. As a result, encrypted attributes
|
||||
could be misconfigured in some cases.
|
||||
|
||||
*Maxime Réty*
|
||||
|
||||
* Deprecate defining an `enum` with keyword arguments.
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -378,23 +378,20 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|||
end
|
||||
|
||||
initializer "active_record_encryption.configuration" do |app|
|
||||
auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
|
||||
|
||||
config.after_initialize do |app|
|
||||
ActiveSupport.on_load(:active_record) 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),
|
||||
**config.active_record.encryption
|
||||
**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
|
||||
|
||||
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
|
||||
ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
|
||||
end
|
||||
# Support extended queries for deterministic attributes and validations
|
||||
if ActiveRecord::Encryption.config.extend_queries
|
||||
ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
|
||||
ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -31,6 +31,13 @@ class ::MySanitizerVendor < ::Rails::HTML::Sanitizer
|
|||
end
|
||||
end
|
||||
|
||||
class ::MyCustomKeyProvider
|
||||
attr_reader :primary_key
|
||||
def initialize(primary_key); @primary_key = primary_key; end
|
||||
end
|
||||
|
||||
class ::MyOldKeyProvider; end
|
||||
|
||||
module ApplicationTests
|
||||
class ConfigurationTest < ActiveSupport::TestCase
|
||||
include ActiveSupport::Testing::Isolation
|
||||
|
@ -3819,6 +3826,74 @@ module ApplicationTests
|
|||
assert_not_includes ActiveRecord::Base.filter_attributes, :content
|
||||
end
|
||||
|
||||
test "ActiveRecord::Encryption.config is ready for encrypted attributes when app is lazy loaded" do
|
||||
add_to_config <<-RUBY
|
||||
config.enable_reloading = false
|
||||
config.eager_load = false
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/active_record.rb", <<-RUBY
|
||||
Rails.application.config.active_record.encryption.primary_key = "dummy_key"
|
||||
Rails.application.config.active_record.encryption.previous = [ { key_provider: MyOldKeyProvider.new } ]
|
||||
|
||||
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
||||
ActiveRecord::Migration.verbose = false
|
||||
ActiveRecord::Schema.define(version: 1) do
|
||||
create_table :posts do |t|
|
||||
t.string :content
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.schema_cache.add("posts")
|
||||
RUBY
|
||||
|
||||
app_file "app/models/post.rb", <<-RUBY
|
||||
class Post < ActiveRecord::Base
|
||||
encrypts :content, key_provider: MyCustomKeyProvider.new(ActiveRecord::Encryption.config.primary_key)
|
||||
end
|
||||
RUBY
|
||||
|
||||
app "development"
|
||||
|
||||
assert_kind_of ::MyOldKeyProvider, Post.attribute_types["content"].previous_schemes.first.key_provider
|
||||
assert_kind_of ::MyCustomKeyProvider, Post.attribute_types["content"].scheme.key_provider
|
||||
assert_equal "dummy_key", Post.attribute_types["content"].scheme.key_provider.primary_key
|
||||
end
|
||||
|
||||
test "ActiveRecord::Encryption.config is ready for encrypted attributes when app is eager loaded" do
|
||||
add_to_config <<-RUBY
|
||||
config.enable_reloading = false
|
||||
config.eager_load = true
|
||||
RUBY
|
||||
|
||||
app_file "app/models/post.rb", <<-RUBY
|
||||
class Post < ActiveRecord::Base
|
||||
encrypts :content, key_provider: MyCustomKeyProvider.new(ActiveRecord::Encryption.config.primary_key)
|
||||
end
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/active_record.rb", <<-RUBY
|
||||
Rails.application.config.active_record.encryption.primary_key = "dummy_key"
|
||||
Rails.application.config.active_record.encryption.previous = [ { key_provider: MyOldKeyProvider.new } ]
|
||||
|
||||
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
||||
ActiveRecord::Migration.verbose = false
|
||||
ActiveRecord::Schema.define(version: 1) do
|
||||
create_table :posts do |t|
|
||||
t.string :content
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.schema_cache.add("posts")
|
||||
RUBY
|
||||
|
||||
app "production"
|
||||
|
||||
assert_kind_of ::MyOldKeyProvider, Post.attribute_types["content"].previous_schemes.first&.key_provider
|
||||
assert_kind_of ::MyCustomKeyProvider, Post.attribute_types["content"].scheme.key_provider
|
||||
assert_equal "dummy_key", Post.attribute_types["content"].scheme.key_provider.primary_key
|
||||
end
|
||||
|
||||
test "ActiveStorage.routes_prefix can be configured via config.active_storage.routes_prefix" do
|
||||
app_file "config/environments/development.rb", <<-RUBY
|
||||
Rails.application.configure do
|
||||
|
|
Loading…
Reference in New Issue