Skip to content

Commit c3c3394

Browse files
authored
Encryption: allow turning on support_unencrypted_data at a per-attribute level (rails#51100)
rails#49072 allowed you to turn `support_unencrypted_data` on a global level, then turn it off for specific attributes. But it didn't allow the inverse: you couldn't turn the config off globally, and then turn it on for a specific attribute. This PR adds support for that.
1 parent 32d9623 commit c3c3394

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

activerecord/CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
* Encryption now supports `support_unencrypted_data: true` being set per-attribute.
2+
3+
Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
4+
Now, if the global config is turned off, you can still opt in for a specific attribute.
5+
6+
```ruby
7+
# ActiveRecord::Encryption.config.support_unencrypted_data = true
8+
class User < ActiveRecord::Base
9+
encrypts :name, support_unencrypted_data: false # only supports encrypted data
10+
encrypts :email # supports encrypted or unencrypted data
11+
end
12+
```
13+
14+
```ruby
15+
# ActiveRecord::Encryption.config.support_unencrypted_data = false
16+
class User < ActiveRecord::Base
17+
encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
18+
encrypts :email # only supports encrypted data
19+
end
20+
```
21+
22+
*Alex Ghiculescu*
23+
124
* Model generator no longer needs a database connection to validate column types.
225

326
*Mike Dalessio*

activerecord/lib/active_record/encryption/encryptable_record.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ module EncryptableRecord
3030
# will use the oldest encryption scheme to encrypt new data by default. You can change this by setting
3131
# <tt>deterministic: { fixed: false }</tt>. That will make it use the newest encryption scheme for encrypting new
3232
# data.
33-
# * <tt>:support_unencrypted_data</tt> - If `config.active_record.encryption.support_unencrypted_data` is +true+,
34-
# you can set this to +false+ to opt out of unencrypted data support for this attribute. This is useful for
35-
# scenarios where you encrypt one column, and want to disable support for unencrypted data without having to tweak
36-
# the global setting.
33+
# * <tt>:support_unencrypted_data</tt> - When true, unencrypted data can be read normally. When false, it will raise errors.
34+
# Falls back to +config.active_record.encryption.support_unencrypted_data+ if no value is provided.
35+
# This is useful for scenarios where you encrypt one column, and want to disable support for unencrypted data
36+
# without having to tweak the global setting.
3737
# * <tt>:downcase</tt> - When true, it converts the encrypted content to downcase automatically. This allows to
3838
# effectively ignore case when querying data. Notice that the case is lost. Use +:ignore_case+ if you are interested
3939
# in preserving it.

activerecord/lib/active_record/encryption/encrypted_attribute_type.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def previous_types # :nodoc:
5959
end
6060

6161
def support_unencrypted_data?
62-
ActiveRecord::Encryption.config.support_unencrypted_data && scheme.support_unencrypted_data? && !previous_type?
62+
scheme.support_unencrypted_data? && !previous_type?
6363
end
6464

6565
private

activerecord/test/cases/encryption/extended_deterministic_queries_test.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require "cases/encryption/helper"
44
require "models/book_encrypted"
5+
require "active_support/core_ext/object/with"
56

67
class ActiveRecord::Encryption::ExtendedDeterministicQueriesTest < ActiveRecord::EncryptionTestCase
78
setup do
@@ -78,4 +79,20 @@ class ActiveRecord::Encryption::ExtendedDeterministicQueriesTest < ActiveRecord:
7879
assert EncryptedBookWithUnencryptedDataOptedIn.find_by(name: "Dune") # core
7980
assert EncryptedBookWithUnencryptedDataOptedIn.where("id > 0").find_by(name: "Dune") # relation
8081
end
82+
83+
test "if support_unencrypted_data config is disabled, but support_unencrypted_data is opted in at an attribute level, can find unencrypted data" do
84+
ActiveRecord::Encryption.config.with(support_unencrypted_data: false) do
85+
UnencryptedBook.create! name: "Dune"
86+
assert EncryptedBookWithUnencryptedDataOptedIn.find_by(name: "Dune") # core
87+
assert EncryptedBookWithUnencryptedDataOptedIn.where("id > 0").find_by(name: "Dune") # relation
88+
end
89+
end
90+
91+
test "if support_unencrypted_data config is disabled, but support_unencrypted_data is opted in at an attribute level, can find encrypted data" do
92+
ActiveRecord::Encryption.config.with(support_unencrypted_data: false) do
93+
EncryptedBook.create! name: "Dune"
94+
assert EncryptedBookWithUnencryptedDataOptedIn.find_by(name: "Dune") # core
95+
assert EncryptedBookWithUnencryptedDataOptedIn.where("id > 0").find_by(name: "Dune") # relation
96+
end
97+
end
8198
end

0 commit comments

Comments
 (0)