-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comparing another known ruby 3/rails 7 fork #2
Changes from all commits
3637c91
515cf71
eafd77a
1e33cab
df02ab0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ def self.extended(base) # :nodoc: | |
base.class_eval do | ||
include InstanceMethods | ||
attr_writer :attr_encrypted_options | ||
@attr_encrypted_options, @encrypted_attributes = {}, {} | ||
@attr_encrypted_options, @attr_encrypted_encrypted_attributes = {}, {} | ||
end | ||
end | ||
|
||
|
@@ -160,11 +160,11 @@ def attr_encrypted(*attributes) | |
end | ||
|
||
define_method(attribute) do | ||
instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name))) | ||
instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", attr_encrypted_decrypt(attribute, send(encrypted_attribute_name))) | ||
end | ||
|
||
define_method("#{attribute}=") do |value| | ||
send("#{encrypted_attribute_name}=", encrypt(attribute, value)) | ||
send("#{encrypted_attribute_name}=", attr_encrypted_encrypt(attribute, value)) | ||
instance_variable_set("@#{attribute}", value) | ||
end | ||
|
||
|
@@ -173,7 +173,7 @@ def attr_encrypted(*attributes) | |
value.respond_to?(:empty?) ? !value.empty? : !!value | ||
end | ||
|
||
encrypted_attributes[attribute.to_sym] = options.merge(attribute: encrypted_attribute_name) | ||
self.attr_encrypted_encrypted_attributes[attribute.to_sym] = options.merge(attribute: encrypted_attribute_name) | ||
end | ||
end | ||
|
||
|
@@ -223,7 +223,7 @@ def attr_encrypted_default_options | |
# User.attr_encrypted?(:name) # false | ||
# User.attr_encrypted?(:email) # true | ||
def attr_encrypted?(attribute) | ||
encrypted_attributes.has_key?(attribute.to_sym) | ||
attr_encrypted_encrypted_attributes.has_key?(attribute.to_sym) | ||
end | ||
|
||
# Decrypts a value for the attribute specified | ||
|
@@ -234,9 +234,9 @@ def attr_encrypted?(attribute) | |
# attr_encrypted :email | ||
# end | ||
# | ||
# email = User.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') | ||
def decrypt(attribute, encrypted_value, options = {}) | ||
options = encrypted_attributes[attribute.to_sym].merge(options) | ||
# email = User.attr_encrypted_decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') | ||
def attr_encrypted_decrypt(attribute, encrypted_value, options = {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renames the |
||
options = attr_encrypted_encrypted_attributes[attribute.to_sym].merge(options) | ||
if options[:if] && !options[:unless] && not_empty?(encrypted_value) | ||
encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode] | ||
value = options[:encryptor].send(options[:decrypt_method], options.merge!(value: encrypted_value)) | ||
|
@@ -260,9 +260,9 @@ def decrypt(attribute, encrypted_value, options = {}) | |
# attr_encrypted :email | ||
# end | ||
# | ||
# encrypted_email = User.encrypt(:email, '[email protected]') | ||
def encrypt(attribute, value, options = {}) | ||
options = encrypted_attributes[attribute.to_sym].merge(options) | ||
# encrypted_email = User.attr_encrypted_encrypt(:email, '[email protected]') | ||
def attr_encrypted_encrypt(attribute, value, options = {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renames the |
||
options = attr_encrypted_encrypted_attributes[attribute.to_sym].merge(options) | ||
if options[:if] && !options[:unless] && (options[:allow_empty_value] || not_empty?(value)) | ||
value = options[:marshal] ? options[:marshaler].send(options[:dump_method], value) : value.to_s | ||
encrypted_value = options[:encryptor].send(options[:encrypt_method], options.merge!(value: value)) | ||
|
@@ -286,9 +286,9 @@ def not_empty?(value) | |
# attr_encrypted :email, key: 'my secret key' | ||
# end | ||
# | ||
# User.encrypted_attributes # { email: { attribute: 'encrypted_email', key: 'my secret key' } } | ||
def encrypted_attributes | ||
@encrypted_attributes ||= superclass.encrypted_attributes.dup | ||
# User.attr_encrypted_encrypted_attributes # { email: { attribute: 'encrypted_email', key: 'my secret key' } } | ||
def attr_encrypted_encrypted_attributes | ||
@attr_encrypted_encrypted_attributes ||= superclass.attr_encrypted_encrypted_attributes.dup | ||
end | ||
|
||
# Forwards calls to :encrypt_#{attribute} or :decrypt_#{attribute} to the corresponding encrypt or decrypt method | ||
|
@@ -325,10 +325,10 @@ module InstanceMethods | |
# | ||
# @user = User.new('some-secret-key') | ||
# @user.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') | ||
def decrypt(attribute, encrypted_value) | ||
encrypted_attributes[attribute.to_sym][:operation] = :decrypting | ||
encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value) | ||
self.class.decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute)) | ||
def attr_encrypted_decrypt(attribute, encrypted_value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename the instance method to not collide with AR 7 |
||
attr_encrypted_encrypted_attributes[attribute.to_sym][:operation] = :decrypting | ||
attr_encrypted_encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value) | ||
self.class.attr_encrypted_decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute)) | ||
end | ||
|
||
# Encrypts a value for the attribute specified using options evaluated in the current object's scope | ||
|
@@ -345,20 +345,20 @@ def decrypt(attribute, encrypted_value) | |
# end | ||
# | ||
# @user = User.new('some-secret-key') | ||
# @user.encrypt(:email, '[email protected]') | ||
def encrypt(attribute, value) | ||
encrypted_attributes[attribute.to_sym][:operation] = :encrypting | ||
encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value) | ||
self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute)) | ||
# @user.attr_encrypted_encrypt(:email, '[email protected]') | ||
def attr_encrypted_encrypt(attribute, value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename the instance method to not collide with AR 7 |
||
attr_encrypted_encrypted_attributes[attribute.to_sym][:operation] = :encrypting | ||
attr_encrypted_encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value) | ||
self.class.attr_encrypted_encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute)) | ||
end | ||
|
||
# Copies the class level hash of encrypted attributes with virtual attribute names as keys | ||
# and their corresponding options as values to the instance | ||
# | ||
def encrypted_attributes | ||
@encrypted_attributes ||= begin | ||
def attr_encrypted_encrypted_attributes | ||
@attr_encrypted_encrypted_attributes ||= begin | ||
duplicated= {} | ||
self.class.encrypted_attributes.map { |key, value| duplicated[key] = value.dup } | ||
self.class.attr_encrypted_encrypted_attributes.map { |key, value| duplicated[key] = value.dup } | ||
duplicated | ||
end | ||
end | ||
|
@@ -368,7 +368,7 @@ def encrypted_attributes | |
# Returns attr_encrypted options evaluated in the current object's scope for the attribute specified | ||
def evaluated_attr_encrypted_options_for(attribute) | ||
evaluated_options = Hash.new | ||
attributes = encrypted_attributes[attribute.to_sym] | ||
attributes = attr_encrypted_encrypted_attributes[attribute.to_sym] | ||
attribute_option_value = attributes[:attribute] | ||
|
||
[:if, :unless, :value_present, :allow_empty_value].each do |option| | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ def self.extended(base) # :nodoc: | |
alias_method :reload_without_attr_encrypted, :reload | ||
def reload(*args, &block) | ||
result = reload_without_attr_encrypted(*args, &block) | ||
self.class.encrypted_attributes.keys.each do |attribute_name| | ||
self.class.attr_encrypted_encrypted_attributes.keys.each do |attribute_name| | ||
instance_variable_set("@#{attribute_name}", nil) | ||
end | ||
result | ||
|
@@ -27,8 +27,8 @@ class << self | |
def perform_attribute_assignment(method, new_attributes, *args) | ||
return if new_attributes.blank? | ||
|
||
send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args | ||
send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args | ||
send method, new_attributes.reject { |k, _| self.class.attr_encrypted_encrypted_attributes.key?(k.to_sym) }, *args | ||
send method, new_attributes.reject { |k, _| !self.class.attr_encrypted_encrypted_attributes.key?(k.to_sym) }, *args | ||
end | ||
private :perform_attribute_assignment | ||
|
||
|
@@ -54,15 +54,15 @@ def attr_encrypted(*attrs) | |
options = attrs.extract_options! | ||
attr = attrs.pop | ||
attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0" | ||
options.merge! encrypted_attributes[attr] | ||
options.merge! attr_encrypted_encrypted_attributes[attr] | ||
|
||
define_method("#{attr}_was") do | ||
attribute_was(attr) | ||
end | ||
|
||
if ::ActiveRecord::VERSION::STRING >= "4.1" | ||
define_method("#{attr}_changed?") do |options = {}| | ||
attribute_changed?(attr, options) | ||
attribute_changed?(attr, **options) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ruby 3 syntax |
||
end | ||
else | ||
define_method("#{attr}_changed?") do | ||
|
@@ -122,10 +122,10 @@ def method_missing_with_attr_encrypted(method, *args, &block) | |
if match = /^(find|scoped)_(all_by|by)_([_a-zA-Z]\w*)$/.match(method.to_s) | ||
attribute_names = match.captures.last.split('_and_') | ||
attribute_names.each_with_index do |attribute, index| | ||
if attr_encrypted?(attribute) && encrypted_attributes[attribute.to_sym][:mode] == :single_iv_and_salt | ||
if attr_encrypted?(attribute) && attr_encrypted_encrypted_attributes[attribute.to_sym][:mode] == :single_iv_and_salt | ||
args[index] = send("encrypt_#{attribute}", args[index]) | ||
warn "DEPRECATION WARNING: This feature will be removed in the next major release." | ||
attribute_names[index] = encrypted_attributes[attribute.to_sym][:attribute] | ||
attribute_names[index] = attr_encrypted_encrypted_attributes[attribute.to_sym][:attribute] | ||
end | ||
end | ||
method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,7 @@ class Account < ActiveRecord::Base | |
attr_encrypted :password, key: :password_encryption_key | ||
|
||
def encrypting?(attr) | ||
encrypted_attributes[attr][:operation] == :encrypting | ||
attr_encrypted_encrypted_attributes[attr][:operation] == :encrypting | ||
end | ||
|
||
def password_encryption_key | ||
|
@@ -279,14 +279,14 @@ def test_should_allow_proc_based_mode | |
@person = PersonWithProcMode.create(email: '[email protected]', credentials: 'password123') | ||
|
||
# Email is :per_attribute_iv_and_salt | ||
assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc | ||
assert_equal @person.class.encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt | ||
assert_equal @person.class.attr_encrypted_encrypted_attributes[:email][:mode].class, Proc | ||
assert_equal @person.class.attr_encrypted_encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt | ||
refute_nil @person.encrypted_email_salt | ||
refute_nil @person.encrypted_email_iv | ||
|
||
# Credentials is :single_iv_and_salt | ||
assert_equal @person.class.encrypted_attributes[:credentials][:mode].class, Proc | ||
assert_equal @person.class.encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt | ||
assert_equal @person.class.attr_encrypted_encrypted_attributes[:credentials][:mode].class, Proc | ||
assert_equal @person.class.attr_encrypted_encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt | ||
assert_nil @person.encrypted_credentials_salt | ||
assert_nil @person.encrypted_credentials_iv | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,19 +83,19 @@ def setup | |
end | ||
|
||
def test_should_store_email_in_encrypted_attributes | ||
assert User.encrypted_attributes.include?(:email) | ||
assert User.attr_encrypted_encrypted_attributes.include?(:email) | ||
end | ||
|
||
def test_should_not_store_salt_in_encrypted_attributes | ||
refute User.encrypted_attributes.include?(:salt) | ||
refute User.attr_encrypted_encrypted_attributes.include?(:salt) | ||
end | ||
|
||
def test_attr_encrypted_should_return_true_for_email | ||
assert User.attr_encrypted?('email') | ||
end | ||
|
||
def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line | ||
refute_equal User.encrypted_attributes[:email][:attribute], User.encrypted_attributes[:without_encoding][:attribute] | ||
refute_equal User.attr_encrypted_encrypted_attributes[:email][:attribute], User.attr_encrypted_encrypted_attributes[:without_encoding][:attribute] | ||
end | ||
|
||
def test_attr_encrypted_should_return_false_for_salt | ||
|
@@ -154,7 +154,7 @@ def test_should_decrypt_email | |
def test_should_decrypt_email_when_reading | ||
@user = User.new | ||
assert_nil @user.email | ||
options = @user.encrypted_attributes[:email] | ||
options = @user.attr_encrypted_encrypted_attributes[:email] | ||
iv = @user.send(:generate_iv, options[:algorithm]) | ||
encoded_iv = [iv].pack(options[:encode_iv]) | ||
salt = SecureRandom.random_bytes | ||
|
@@ -223,7 +223,7 @@ def test_should_use_options_found_in_the_attr_encrypted_options_attribute | |
end | ||
|
||
def test_should_inherit_encrypted_attributes | ||
assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort | ||
assert_equal [User.attr_encrypted_encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.attr_encrypted_encrypted_attributes.keys.collect { |key| key.to_s }.sort | ||
end | ||
|
||
def test_should_inherit_attr_encrypted_options | ||
|
@@ -233,7 +233,7 @@ def test_should_inherit_attr_encrypted_options | |
|
||
def test_should_not_inherit_unrelated_attributes | ||
assert SomeOtherClass.attr_encrypted_options.empty? | ||
assert SomeOtherClass.encrypted_attributes.empty? | ||
assert SomeOtherClass.attr_encrypted_encrypted_attributes.empty? | ||
end | ||
|
||
def test_should_evaluate_a_symbol_option | ||
|
@@ -304,7 +304,7 @@ def test_should_encrypt_empty_with_truthy_allow_empty_value_option | |
end | ||
|
||
def test_should_work_with_aliased_attr_encryptor | ||
assert User.encrypted_attributes.include?(:aliased) | ||
assert User.attr_encrypted_encrypted_attributes.include?(:aliased) | ||
end | ||
|
||
def test_should_always_reset_options | ||
|
@@ -381,12 +381,12 @@ def test_should_decrypt_second_record | |
@user2 = User.new | ||
@user2.email = '[email protected]' | ||
|
||
assert_equal '[email protected]', @user1.decrypt(:email, @user1.encrypted_email) | ||
assert_equal '[email protected]', @user1.attr_encrypted_decrypt(:email, @user1.encrypted_email) | ||
end | ||
|
||
def test_should_specify_the_default_algorithm | ||
assert YetAnotherClass.encrypted_attributes[:email][:algorithm] | ||
assert_equal YetAnotherClass.encrypted_attributes[:email][:algorithm], 'aes-256-gcm' | ||
assert YetAnotherClass.attr_encrypted_encrypted_attributes[:email][:algorithm] | ||
assert_equal YetAnotherClass.attr_encrypted_encrypted_attributes[:email][:algorithm], 'aes-256-gcm' | ||
end | ||
|
||
def test_should_not_encode_iv_when_encode_iv_is_false | ||
|
@@ -475,8 +475,8 @@ def test_encrypted_attributes_state_is_not_shared | |
|
||
another_user = User.new | ||
|
||
assert_equal :encrypting, user.encrypted_attributes[:ssn][:operation] | ||
assert_nil another_user.encrypted_attributes[:ssn][:operation] | ||
assert_equal :encrypting, user.attr_encrypted_encrypted_attributes[:ssn][:operation] | ||
assert_nil another_user.attr_encrypted_encrypted_attributes[:ssn][:operation] | ||
end | ||
|
||
def test_should_not_by_default_generate_key_when_attribute_is_empty | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
attr_encrypted(:secure_field)
is supposed to create two methods,#secure_field
and#secure_field=
. This ensures that those methods use theattr_encrypted
implementations for decrypt/encrypt.Otherwise, in rails 7 this would call the rails-versions of
#encrypt
/#decrypt
?