mirror of https://github.com/rails/rails
Support encrypted attributes on columns with default values
Before, it was failing to read these columns because their contents were not encrypted, unless you enabled `config.active_record.encryption.support_unencrypted_data`. Now, it will detect the change at creation time for these records and effectively encrypt those values, preventing the problem. Fixes #44314 #43664 Closes #44993 Co-authored-by: Dima Fatko <fatkodima123@gmail.com>
This commit is contained in:
parent
480edd4906
commit
238432d1cb
|
@ -1,3 +1,11 @@
|
|||
* Support encrypted attributes on columns with default db values.
|
||||
|
||||
This adds support for encrypted attributes defined on columns with default values.
|
||||
It will encrypt those values at creation time. Before, it would raise an
|
||||
error unless `config.active_record.encryption.support_unencrypted_data` was true.
|
||||
|
||||
*Jorge Manrubia* and *Dima Fatko*
|
||||
|
||||
* Allow overriding `reading_request?` in `DatabaseSelector::Resolver`
|
||||
|
||||
The default implementation checks if a request is a `get?` or `head?`,
|
||||
|
|
|
@ -82,7 +82,7 @@ module ActiveRecord
|
|||
def encrypt_attribute(name, attribute_scheme)
|
||||
encrypted_attributes << name.to_sym
|
||||
|
||||
attribute name do |cast_type|
|
||||
attribute name, default: -> { columns_hash[name.to_s]&.default } do |cast_type|
|
||||
ActiveRecord::Encryption::EncryptedAttributeType.new scheme: attribute_scheme, cast_type: cast_type
|
||||
end
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def changed_in_place?(raw_old_value, new_value)
|
||||
old_value = raw_old_value.nil? ? nil : deserialize(raw_old_value)
|
||||
old_value = raw_old_value.nil? ? nil : deserialize_previous_value_to_determine_change(raw_old_value)
|
||||
old_value != new_value
|
||||
end
|
||||
|
||||
|
@ -135,6 +135,14 @@ module ActiveRecord
|
|||
def clean_text_scheme
|
||||
@clean_text_scheme ||= ActiveRecord::Encryption::Scheme.new(downcase: downcase?, encryptor: ActiveRecord::Encryption::NullEncryptor.new)
|
||||
end
|
||||
|
||||
def deserialize_previous_value_to_determine_change(raw_old_value)
|
||||
deserialize(raw_old_value)
|
||||
# We tolerate unencrypted data when determining if a column changed
|
||||
# to support default DB values in encrypted attributes
|
||||
rescue ActiveRecord::Encryption::Errors::Decryption
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -292,6 +292,11 @@ class ActiveRecord::Encryption::EncryptableRecordTest < ActiveRecord::Encryption
|
|||
assert_equal Encoding::US_ASCII, book.reload.name.encoding
|
||||
end
|
||||
|
||||
test "support encrypted attributes defined on columns with default values" do
|
||||
book = EncryptedBook.create!
|
||||
assert_encrypted_attribute(book, :name, "<untitled>")
|
||||
end
|
||||
|
||||
private
|
||||
class FailingKeyProvider
|
||||
def decryption_key(message) end
|
||||
|
|
|
@ -141,7 +141,7 @@ ActiveRecord::Schema.define do
|
|||
create_table :encrypted_books, id: :integer, force: true do |t|
|
||||
t.references :author
|
||||
t.string :format
|
||||
t.column :name, :string
|
||||
t.column :name, :string, default: "<untitled>"
|
||||
t.column :original_name, :string
|
||||
|
||||
t.datetime :created_at
|
||||
|
|
Loading…
Reference in New Issue