Skip to content

Commit e7432ae

Browse files
committed
[Fix rails#48922] Use context from the encrypted attribute type in encrypted_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.
1 parent 1b56816 commit e7432ae

File tree

4 files changed

+22
-2
lines changed

4 files changed

+22
-2
lines changed

activerecord/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
2+
3+
*Maxime Réty*
4+
15
* The object returned by `explain` now responds to `pluck`, `first`,
26
`last`, `average`, `count`, `maximum`, `minimum`, and `sum`. Those
37
new methods run `EXPLAIN` on the corresponding queries:

activerecord/lib/active_record/encryption/encryptable_record.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,13 @@ def validate_column_size(attribute_name)
144144

145145
# Returns whether a given attribute is encrypted or not.
146146
def encrypted_attribute?(attribute_name)
147-
ActiveRecord::Encryption.encryptor.encrypted? read_attribute_before_type_cast(attribute_name)
147+
name = attribute_name.to_s
148+
name = self.class.attribute_aliases[name] || name
149+
150+
return false unless self.class.encrypted_attributes&.include? name.to_sym
151+
152+
type = type_for_attribute(name)
153+
type.encrypted? read_attribute_before_type_cast(name)
148154
end
149155

150156
# Returns the ciphertext for +attribute_name+.

activerecord/lib/active_record/encryption/encrypted_attribute_type.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ def serialize(value)
4444
end
4545
end
4646

47+
def encrypted?(value)
48+
with_context { encryptor.encrypted? value }
49+
end
50+
4751
def changed_in_place?(raw_old_value, new_value)
4852
old_value = raw_old_value.nil? ? nil : deserialize(raw_old_value)
4953
old_value != new_value

activerecord/test/cases/encryption/encryption_schemes_test.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ActiveRecord::Encryption::EncryptionSchemesTest < ActiveRecord::Encryption
99

1010
author = create_author_with_name_encrypted_with_previous_scheme
1111
assert_equal "dhh", author.reload.name
12+
assert author.encrypted_attribute? :name
1213
end
1314

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

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

3639
Author.find(author.id).update! name: "1"
3740
assert_equal "1", author.reload.name
3841
assert_equal author, EncryptedAuthor2.find_by_name("1")
42+
assert_not author.encrypted_attribute? :name
3943
end
4044

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

193197
def encrypted?(text)
194-
text == encrypted_text
198+
decrypt(text)
199+
rescue ActiveRecord::Encryption::Errors::Decryption
200+
false
195201
end
196202
end
197203

0 commit comments

Comments
 (0)