Skip to content

Commit

Permalink
[Fix rails#48922] Use context from the encrypted attribute type in en…
Browse files Browse the repository at this point in the history
…crypted_attribute?

Also fix implementation of TestEncryptor#encrypted?

The assertions fail because encrypted_attribute? delegates a decryption
attempt to the default encryptor (instead of the one configured) to
check if the value is actually encrypted.
  • Loading branch information
maximerety committed Jan 5, 2024
1 parent 8c4af05 commit 48ab52d
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 2 deletions.
4 changes: 4 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.

*Maxime Réty*

* Add `explain` support for methods like `last`, `pluck` and `count`

Let `explain` return a proxy that delegates these methods:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,13 @@ def validate_column_size(attribute_name)

# Returns whether a given attribute is encrypted or not.
def encrypted_attribute?(attribute_name)
ActiveRecord::Encryption.encryptor.encrypted? read_attribute_before_type_cast(attribute_name)
name = attribute_name.to_s
name = self.class.attribute_aliases[name] || name

return false unless self.class.encrypted_attributes&.include? name.to_sym

type = type_for_attribute(name)
type.encrypted? read_attribute_before_type_cast(name)
end

# Returns the ciphertext for +attribute_name+.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def serialize(value)
end
end

def encrypted?(value)
with_context { encryptor.encrypted? value }
end

def changed_in_place?(raw_old_value, new_value)
old_value = raw_old_value.nil? ? nil : deserialize(raw_old_value)
old_value != new_value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ActiveRecord::Encryption::EncryptionSchemesTest < ActiveRecord::Encryption

author = create_author_with_name_encrypted_with_previous_scheme
assert_equal "dhh", author.reload.name
assert author.encrypted_attribute? :name
end

test "when defining previous encryption schemes, you still get Decryption errors when using invalid clear values" do
Expand All @@ -24,6 +25,7 @@ class ActiveRecord::Encryption::EncryptionSchemesTest < ActiveRecord::Encryption
test "use a custom encryptor" do
author = EncryptedAuthor1.create name: "1"
assert_equal "1", author.name
assert author.encrypted_attribute? :name
end

test "support previous contexts" do
Expand All @@ -32,10 +34,12 @@ class ActiveRecord::Encryption::EncryptionSchemesTest < ActiveRecord::Encryption
author = EncryptedAuthor2.create name: "2"
assert_equal "2", author.name
assert_equal author, EncryptedAuthor2.find_by_name("2")
assert author.encrypted_attribute? :name

Author.find(author.id).update! name: "1"
assert_equal "1", author.reload.name
assert_equal author, EncryptedAuthor2.find_by_name("1")
assert_not author.encrypted_attribute? :name
end

test "use global previous schemes to decrypt data encrypted with previous schemes" do
Expand Down Expand Up @@ -191,7 +195,9 @@ def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
end

def encrypted?(text)
text == encrypted_text
decrypt(text)
rescue ActiveRecord::Encryption::Errors::Decryption
false
end
end

Expand Down

0 comments on commit 48ab52d

Please sign in to comment.