From d92e8c2cf27988bce9d55629117553c1f3a90686 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Tue, 18 Oct 2022 23:45:22 -0600 Subject: [PATCH 01/34] Modern Ruby + ActiveRecord, Update Travis Config (#416) * Update Travis configuration * Drop os, use default * Use focal for OS * Restore patch versions of ruby, rvm not pulling latest patch * Update local test/run.sh script for easier local testing * Add some old AR back, remove 3+ rubies, drop deprecated codeclimate gem * Lock sqlite3 for Ruby 2.5 * ActiveRecord 6.0 and 6.1 tests failing, add later * Drop 2.5 * Update gemspec, pry for dev support * 5.1.1 AR works, update test/run.sh * Fix support for ActiveRecord 5.2 --- .travis.yml | 57 ++---------- attr_encrypted.gemspec | 11 +-- lib/attr_encrypted/adapters/active_record.rb | 25 +++-- test/active_record_test.rb | 98 ++++++++++---------- test/run.sh | 22 +++-- test/test_helper.rb | 7 +- 6 files changed, 88 insertions(+), 132 deletions(-) diff --git a/.travis.yml b/.travis.yml index f75b2ede..f395ade5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,59 +1,14 @@ -sudo: false language: ruby +dist: focal +os: linux cache: bundler rvm: - - 2.0 - - 2.1 - - 2.2.2 - - 2.3.0 - - 2.4.0 - - 2.5.0 - - rbx + - 2.6.10 + - 2.7.6 env: - - ACTIVERECORD=3.0.0 - - ACTIVERECORD=3.1.0 - - ACTIVERECORD=3.2.0 - - ACTIVERECORD=4.0.0 - - ACTIVERECORD=4.1.0 - - ACTIVERECORD=4.2.0 - - ACTIVERECORD=5.0.0 - ACTIVERECORD=5.1.1 -matrix: - exclude: - - rvm: 2.0 - env: ACTIVERECORD=5.0.0 - - rvm: 2.0 - env: ACTIVERECORD=5.1.1 - - rvm: 2.1 - env: ACTIVERECORD=5.0.0 - - rvm: 2.1 - env: ACTIVERECORD=5.1.1 - - rvm: 2.4.0 - env: ACTIVERECORD=3.0.0 - - rvm: 2.4.0 - env: ACTIVERECORD=3.1.0 - - rvm: 2.4.0 - env: ACTIVERECORD=3.2.0 - - rvm: 2.4.0 - env: ACTIVERECORD=4.0.0 - - rvm: 2.4.0 - env: ACTIVERECORD=4.1.0 - - rvm: 2.5.0 - env: ACTIVERECORD=3.0.0 - - rvm: 2.5.0 - env: ACTIVERECORD=3.1.0 - - rvm: 2.5.0 - env: ACTIVERECORD=3.2.0 - - rvm: 2.5.0 - env: ACTIVERECORD=4.0.0 - - rvm: 2.5.0 - env: ACTIVERECORD=4.1.0 - - rvm: rbx - env: ACTIVERECORD=5.0.0 - - rvm: rbx - env: ACTIVERECORD=5.1.1 - allow_failures: - - rvm: rbx + - ACTIVERECORD=5.2.8 +jobs: fast_finish: true addons: code_climate: diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 41f96ed9..798f4704 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -19,15 +19,12 @@ Gem::Specification.new do |s| s.homepage = 'http://github.com/attr-encrypted/attr_encrypted' s.license = 'MIT' - s.has_rdoc = false - s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc'] - s.require_paths = ['lib'] s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- test/*`.split("\n") - s.required_ruby_version = '>= 2.0.0' + s.required_ruby_version = '>= 2.6.0' s.add_dependency('encryptor', ['~> 3.0.0']) # support for testing with specific active record version @@ -42,10 +39,6 @@ Gem::Specification.new do |s| s.add_development_dependency('rake') s.add_development_dependency('minitest') s.add_development_dependency('sequel') - if RUBY_VERSION < '2.1.0' - s.add_development_dependency('nokogiri', '< 1.7.0') - s.add_development_dependency('public_suffix', '< 3.0.0') - end if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_sym == :jruby s.add_development_dependency('activerecord-jdbcsqlite3-adapter') s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke @@ -53,9 +46,9 @@ Gem::Specification.new do |s| s.add_development_dependency('sqlite3') end s.add_development_dependency('dm-sqlite-adapter') + s.add_development_dependency('pry') s.add_development_dependency('simplecov') s.add_development_dependency('simplecov-rcov') - s.add_development_dependency("codeclimate-test-reporter", '<= 0.6.0') s.cert_chain = ['certs/saghaulor.pem'] s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/ diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index fca9343e..fb53cc1d 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -53,21 +53,15 @@ def attr_encrypted(*attrs) super options = attrs.extract_options! attr = attrs.pop - attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0" + attribute attr options.merge! 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) - end - else - define_method("#{attr}_changed?") do - attribute_changed?(attr) - end + define_method("#{attr}_changed?") do |options = {}| + attribute_changed?(attr, options) end define_method("#{attr}_change") do @@ -75,6 +69,19 @@ def attr_encrypted(*attrs) end define_method("#{attr}_with_dirtiness=") do |value| + ## Source: https://github.com/priyankatapar/attr_encrypted/commit/7e8702bd5418c927a39d8dd72c0adbea522d5663 + # In ActiveRecord 5.2+, due to changes to the way virtual + # attributes are handled, @attributes[attr].value is nil which + # breaks attribute_was. Setting it here returns us to the expected + # behavior. + if ::ActiveRecord::VERSION::STRING >= "5.2" + # This is needed support attribute_was before a record has + # been saved + set_attribute_was(attr, __send__(attr)) if value != __send__(attr) + # This is needed to support attribute_was after a record has + # been saved + @attributes.write_from_user(attr.to_s, value) if value != __send__(attr) + end attribute_will_change!(attr) if value != __send__(attr) __send__("#{attr}_without_dirtiness=", value) end diff --git a/test/active_record_test.rb b/test/active_record_test.rb index 8ec31aea..9eaedeaf 100644 --- a/test/active_record_test.rb +++ b/test/active_record_test.rb @@ -45,16 +45,14 @@ def create_tables ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError) -if ::ActiveRecord::VERSION::STRING > "4.0" - module Rack - module Test - class UploadedFile; end - end +module Rack + module Test + class UploadedFile; end end - - require 'action_controller/metal/strong_parameters' end +require 'action_controller/metal/strong_parameters' + class Person < ActiveRecord::Base self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt attr_encrypted :email, key: SECRET_KEY @@ -106,7 +104,6 @@ class PersonWithSerialization < ActiveRecord::Base class UserWithProtectedAttribute < ActiveRecord::Base self.table_name = 'users' attr_encrypted :password, key: SECRET_KEY - attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0" end class PersonUsingAlias < ActiveRecord::Base @@ -221,52 +218,53 @@ def test_attribute_was_works_when_options_for_old_encrypted_value_are_different_ assert_equal pw.reverse, account.password end - if ::ActiveRecord::VERSION::STRING > "4.0" - def test_should_assign_attributes - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login) - assert_equal 'modified', @user.login + if ::ActiveRecord::VERSION::STRING >= "5.2" + def test_should_create_will_save_change_to_predicate + person = Person.create!(email: 'test@example.com') + refute person.will_save_change_to_email? + person.email = 'test@example.com' + refute person.will_save_change_to_email? + person.email = 'test2@example.com' + assert person.will_save_change_to_email? end - def test_should_not_assign_protected_attributes - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login) - assert !@user.is_admin? + def test_should_create_saved_change_to_predicate + person = Person.create!(email: 'test@example.com') + assert person.saved_change_to_email? + person.reload + person.email = 'test@example.com' + refute person.saved_change_to_email? + person.email = nil + refute person.saved_change_to_email? + person.email = 'test2@example.com' + refute person.saved_change_to_email? + person.save + assert person.saved_change_to_email? end + end - def test_should_raise_exception_if_not_permitted - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - assert_raises ActiveModel::ForbiddenAttributesError do - @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true) - end - end + def test_should_assign_attributes + @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) + @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login) + assert_equal 'modified', @user.login + end - def test_should_raise_exception_on_init_if_not_permitted - assert_raises ActiveModel::ForbiddenAttributesError do - @user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true) - end - end - else - def test_should_assign_attributes - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - @user.attributes = { login: 'modified', is_admin: true } - assert_equal 'modified', @user.login - end + def test_should_not_assign_protected_attributes + @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) + @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login) + assert !@user.is_admin? + end - def test_should_not_assign_protected_attributes - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - @user.attributes = { login: 'modified', is_admin: true } - assert !@user.is_admin? + def test_should_raise_exception_if_not_permitted + @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) + assert_raises ActiveModel::ForbiddenAttributesError do + @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true) end + end - def test_should_assign_protected_attributes - @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false) - if ::ActiveRecord::VERSION::STRING > "3.1" - @user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true) - else - @user.send(:attributes=, { login: 'modified', is_admin: true }, false) - end - assert @user.is_admin? + def test_should_raise_exception_on_init_if_not_permitted + assert_raises ActiveModel::ForbiddenAttributesError do + @user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true) end end @@ -291,11 +289,9 @@ def test_should_allow_proc_based_mode assert_nil @person.encrypted_credentials_iv end - if ::ActiveRecord::VERSION::STRING > "3.1" - def test_should_allow_assign_attributes_with_nil - @person = Person.new - assert_nil(@person.assign_attributes nil) - end + def test_should_allow_assign_attributes_with_nil + @person = Person.new + assert_nil(@person.assign_attributes nil) end def test_that_alias_encrypts_column diff --git a/test/run.sh b/test/run.sh index 7e9b777e..cfdef5ed 100755 --- a/test/run.sh +++ b/test/run.sh @@ -1,12 +1,20 @@ -#!/usr/bin/env sh -e +#!/usr/bin/env bash -for RUBY in 1.9.3 2.0.0 2.1 2.2 +set -e + +for RUBY in 2.6.10 2.7.6 do - for RAILS in 2.3.8 3.0.0 3.1.0 3.2.0 4.0.0 4.1.0 4.2.0 + for ACTIVERECORD in 5.1.1 5.2.8 do - if [[ $RUBY -gt 1.9.3 && $RAILS -lt 4.0.0 ]]; then - continue - fi - RBENV_VERSION=$RUBY ACTIVERECORD=$RAILS bundle && bundle exec rake + echo ">>> Testing with Ruby ${RUBY} and ActiveRecord ${ACTIVERECORD}." + export RBENV_VERSION=$RUBY + export ACTIVERECORD=$ACTIVERECORD + + rbenv install $RUBY --skip-existing + bundle install + bundle check + bundle exec rake test + rm Gemfile.lock + echo ">>> Finished testing with Ruby ${RUBY} and ActiveRecord ${ACTIVERECORD}." done done diff --git a/test/test_helper.rb b/test/test_helper.rb index c352a138..f8283fff 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,14 +1,13 @@ # frozen_string_literal: true +require 'pry' require 'simplecov' require 'simplecov-rcov' -require "codeclimate-test-reporter" SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( [ SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::RcovFormatter, - CodeClimate::TestReporter::Formatter + SimpleCov::Formatter::RcovFormatter ] ) @@ -16,8 +15,6 @@ add_filter 'test' end -CodeClimate::TestReporter.start - require 'minitest/autorun' # Rails 4.0.x pins to an old minitest From 4ec77d30714efd7d3c6ea5be64319d4dbf7fe1b7 Mon Sep 17 00:00:00 2001 From: Igor Drozdov Date: Thu, 20 Oct 2022 00:42:23 +0200 Subject: [PATCH 02/34] Add support for Ruby 2.7 and its kwargs (#383) In Ruby 3.0, positional arguments and keyword arguments will be separated. Ruby 2.7 will warn for behaviors that will change in Ruby 3.0. Co-authored-by: Igor Drozdov --- lib/attr_encrypted/adapters/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index fb53cc1d..78163a66 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -61,7 +61,7 @@ def attr_encrypted(*attrs) end define_method("#{attr}_changed?") do |options = {}| - attribute_changed?(attr, options) + attribute_changed?(attr, **options) end define_method("#{attr}_change") do From e2c7d31e1314c6d280ffbdd57787d548ee1a43b2 Mon Sep 17 00:00:00 2001 From: Mike Vastola Date: Fri, 21 Oct 2022 10:44:38 -0400 Subject: [PATCH 03/34] Fixed bug where we were comparing versions as strings (#419) --- lib/attr_encrypted/adapters/active_record.rb | 6 ++++-- test/active_record_test.rb | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index 78163a66..3111cbd5 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -4,6 +4,8 @@ module AttrEncrypted module Adapters module ActiveRecord + RAILS_VERSION = Gem::Version.new(::ActiveRecord::VERSION::STRING).freeze + def self.extended(base) # :nodoc: base.class_eval do @@ -32,7 +34,7 @@ def perform_attribute_assignment(method, new_attributes, *args) end private :perform_attribute_assignment - if ::ActiveRecord::VERSION::STRING > "3.1" + if Gem::Requirement.new('> 3.1').satisfied_by?(RAILS_VERSION) alias_method :assign_attributes_without_attr_encrypted, :assign_attributes def assign_attributes(*args) perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args @@ -74,7 +76,7 @@ def attr_encrypted(*attrs) # attributes are handled, @attributes[attr].value is nil which # breaks attribute_was. Setting it here returns us to the expected # behavior. - if ::ActiveRecord::VERSION::STRING >= "5.2" + if Gem::Requirement.new('>= 5.2').satisfied_by?(RAILS_VERSION) # This is needed support attribute_was before a record has # been saved set_attribute_was(attr, __send__(attr)) if value != __send__(attr) diff --git a/test/active_record_test.rb b/test/active_record_test.rb index 9eaedeaf..3eb14988 100644 --- a/test/active_record_test.rb +++ b/test/active_record_test.rb @@ -2,6 +2,7 @@ require_relative 'test_helper' +RAILS_VERSION = Gem::Version.new(::ActiveRecord::VERSION::STRING).freeze ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') def create_tables @@ -218,7 +219,7 @@ def test_attribute_was_works_when_options_for_old_encrypted_value_are_different_ assert_equal pw.reverse, account.password end - if ::ActiveRecord::VERSION::STRING >= "5.2" + if Gem::Requirement.new('>= 5.2').satisfied_by?(RAILS_VERSION) def test_should_create_will_save_change_to_predicate person = Person.create!(email: 'test@example.com') refute person.will_save_change_to_email? From 15b47b67dc83fadc5e2ebfcf32992fe2c265c4db Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 21 Oct 2022 17:08:15 -0600 Subject: [PATCH 04/34] Fixed a typo in README.md (#421) Changed inccorectly -> incorrectly on line 412 Co-authored-by: Gabriel --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 87ac7219..31ff425c 100644 --- a/README.md +++ b/README.md @@ -414,7 +414,7 @@ Then modify your models using attr\_encrypted to account for the changes in defa ## Upgrading from attr_encrypted v2.x to v3.x -A bug was discovered in Encryptor v2.0.0 that inccorectly set the IV when using an AES-\*-GCM algorithm. Unfornately fixing this major security issue results in the inability to decrypt records encrypted using an AES-*-GCM algorithm from Encryptor v2.0.0. Please see [Upgrading to Encryptor v3.0.0](https://github.com/attr-encrypted/encryptor#upgrading-from-v200-to-v300) for more info. +A bug was discovered in Encryptor v2.0.0 that incorrectly set the IV when using an AES-\*-GCM algorithm. Unfornately fixing this major security issue results in the inability to decrypt records encrypted using an AES-*-GCM algorithm from Encryptor v2.0.0. Please see [Upgrading to Encryptor v3.0.0](https://github.com/attr-encrypted/encryptor#upgrading-from-v200-to-v300) for more info. It is strongly advised that you re-encrypt your data encrypted with Encryptor v2.0.0. However, you'll have to take special care to re-encrypt. To decrypt data encrypted with Encryptor v2.0.0 using an AES-\*-GCM algorithm you can use the `:v2_gcm_iv` option. From 1b0c912e8e76782035d6810087b9562f569c9975 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 21 Oct 2022 17:09:29 -0600 Subject: [PATCH 05/34] Fix typo in README (#422) Co-authored-by: Alex Brinkman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31ff425c..53558b84 100644 --- a/README.md +++ b/README.md @@ -442,7 +442,7 @@ It is recommended that you implement a strategy to insure that you do not mix th While choosing to encrypt at the attribute level is the most secure solution, it is not without drawbacks. Namely, you cannot search the encrypted data, and because you can't search it, you can't index it either. You also can't use joins on the encrypted data. Data that is securely encrypted is effectively noise. So any operations that rely on the data not being noise will not work. If you need to do any of the aforementioned operations, please consider using database and file system encryption along with transport encryption as it moves through your stack. #### Data leaks -Please also consider where your data leaks. If you're using attr_encrypted with Rails, it's highly likely that this data will enter your app as a request parameter. You'll want to be sure that you're filtering your request params from you logs or else your data is sitting in the clear in your logs. [Parameter Filtering in Rails](http://apidock.com/rails/ActionDispatch/Http/FilterParameters) Please also consider other possible leak points. +Please also consider where your data leaks. If you're using attr_encrypted with Rails, it's highly likely that this data will enter your app as a request parameter. You'll want to be sure that you're filtering your request params from your logs or else your data is sitting in the clear in your logs. [Parameter Filtering in Rails](http://apidock.com/rails/ActionDispatch/Http/FilterParameters) Please also consider other possible leak points. #### Storage requirements When storing your encrypted data, please consider the length requirements of the db column that you're storing the cipher text in. Older versions of Mysql attempt to 'help' you by truncating strings that are too large for the column. When this happens, you will not be able to decrypt your data. [MySQL Strict Trans](http://www.davidpashley.com/2009/02/15/silently-truncated/) From f3355d4cf4e2dbaf9a8ec97edffcc58e652f2e68 Mon Sep 17 00:00:00 2001 From: Mike Vastola Date: Thu, 22 Dec 2022 14:25:54 -0500 Subject: [PATCH 06/34] Add (failable) tests to Travis for RoR 6/6.1/7 --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index f395ade5..85466ad3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,19 @@ rvm: env: - ACTIVERECORD=5.1.1 - ACTIVERECORD=5.2.8 + - ACTIVERECORD=6.0.6 + - ACTIVERECORD=6.1.7 + - ACTIVERECORD=7.0.4 jobs: fast_finish: true + allow_failures: + - env: ACTIVERECORD=6.0.6 + - env: ACTIVERECORD=6.1.7 + - env: ACTIVERECORD=7.0.4 + exclude: + - rvm: 2.6.10 + env: ACTIVERECORD=7.0.4 + addons: code_climate: repo_token: a90435ed4954dd6e9f3697a20c5bc3754f67d94703f870e8fc7b00f69f5b2d06 From 67bcfa2e091f84517763a49d35819280b471f018 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 16 Dec 2022 08:07:49 -0700 Subject: [PATCH 07/34] Restrict set_attribute_was patch to Rails versions >= 5.2, < 6 Signed-off-by: Josh Branham --- lib/attr_encrypted/adapters/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index 3111cbd5..cd631916 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -76,7 +76,7 @@ def attr_encrypted(*attrs) # attributes are handled, @attributes[attr].value is nil which # breaks attribute_was. Setting it here returns us to the expected # behavior. - if Gem::Requirement.new('>= 5.2').satisfied_by?(RAILS_VERSION) + if Gem::Requirement.new('~> 5.2').satisfied_by?(RAILS_VERSION) # This is needed support attribute_was before a record has # been saved set_attribute_was(attr, __send__(attr)) if value != __send__(attr) From a70d87b251b2c59982b378d72c47960f9a9048ee Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 16 Dec 2022 08:27:39 -0700 Subject: [PATCH 08/34] Don't use Gem requirement comparison with frozen Gem::Version --- lib/attr_encrypted/adapters/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index cd631916..d97c368a 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -76,7 +76,7 @@ def attr_encrypted(*attrs) # attributes are handled, @attributes[attr].value is nil which # breaks attribute_was. Setting it here returns us to the expected # behavior. - if Gem::Requirement.new('~> 5.2').satisfied_by?(RAILS_VERSION) + if RAILS_VERSION < Gem::Version.new(6.0) && RAILS_VERSION >= Gem::Version.new(5.2) # This is needed support attribute_was before a record has # been saved set_attribute_was(attr, __send__(attr)) if value != __send__(attr) From e369e61a59d9c1eab158a1fd429bf1ca7d249fcb Mon Sep 17 00:00:00 2001 From: Mike Vastola Date: Thu, 22 Dec 2022 15:18:23 -0500 Subject: [PATCH 09/34] Disallow failures for RoR 6.0+ tests on travis As those should be passing or otherwise dealt with by the time this is merged --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85466ad3..b122db64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,11 +12,7 @@ env: - ACTIVERECORD=6.1.7 - ACTIVERECORD=7.0.4 jobs: - fast_finish: true - allow_failures: - - env: ACTIVERECORD=6.0.6 - - env: ACTIVERECORD=6.1.7 - - env: ACTIVERECORD=7.0.4 + fast_finish: false exclude: - rvm: 2.6.10 env: ACTIVERECORD=7.0.4 From a2db662ddba24899c9be0acd434a02bf66258abd Mon Sep 17 00:00:00 2001 From: Vimal V Nair Date: Fri, 17 Mar 2023 22:47:36 +0530 Subject: [PATCH 10/34] Use #write_cast_value to register the original value before change for Rails >= 5.2 Use #write_cast_value instead of #set_attribute_was patch --- lib/attr_encrypted/adapters/active_record.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index d97c368a..a6cb299e 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -76,10 +76,10 @@ def attr_encrypted(*attrs) # attributes are handled, @attributes[attr].value is nil which # breaks attribute_was. Setting it here returns us to the expected # behavior. - if RAILS_VERSION < Gem::Version.new(6.0) && RAILS_VERSION >= Gem::Version.new(5.2) + if RAILS_VERSION >= Gem::Version.new(5.2) # This is needed support attribute_was before a record has # been saved - set_attribute_was(attr, __send__(attr)) if value != __send__(attr) + @attributes.write_cast_value(attr.to_s, __send__(attr)) if value != __send__(attr) # This is needed to support attribute_was after a record has # been saved @attributes.write_from_user(attr.to_s, value) if value != __send__(attr) From da75c9bac487d9cca6d0dd8e27b378544af536b4 Mon Sep 17 00:00:00 2001 From: Vimal V Nair Date: Fri, 17 Mar 2023 23:47:06 +0530 Subject: [PATCH 11/34] Prefix 'attr_encrypted' to encrypted_attributes method to avoid clash with Rails 7 Prefix 'attr_encrypted' to encrypt and decrypt methods to avoid clash with Rails 7 Adopted from PR: https://github.com/attr-encrypted/attr_encrypted/pull/425 --- README.md | 2 +- lib/attr_encrypted.rb | 56 ++++++++++---------- lib/attr_encrypted/adapters/active_record.rb | 12 ++--- test/active_record_test.rb | 10 ++-- test/attr_encrypted_test.rb | 24 ++++----- test/legacy_attr_encrypted_test.rb | 12 ++--- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 53558b84..3414801f 100644 --- a/README.md +++ b/README.md @@ -425,7 +425,7 @@ It is recommended that you implement a strategy to insure that you do not mix th attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: is_decrypting?(:ssn) def is_decrypting?(attribute) - encrypted_attributes[attribute][:operation] == :decrypting + attr_encrypted_encrypted_attributes[attribute][:operation] == :decrypting end end diff --git a/lib/attr_encrypted.rb b/lib/attr_encrypted.rb index 88e5f65e..4537cd59 100644 --- a/lib/attr_encrypted.rb +++ b/lib/attr_encrypted.rb @@ -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 = {}) + 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, 'test@example.com') - def encrypt(attribute, value, options = {}) - options = encrypted_attributes[attribute.to_sym].merge(options) + # encrypted_email = User.attr_encrypted_encrypt(:email, 'test@example.com') + def attr_encrypted_encrypt(attribute, value, options = {}) + 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 @@ -303,7 +303,7 @@ def encrypted_attributes # User.encrypt_email('SOME_ENCRYPTED_EMAIL_STRING') def method_missing(method, *arguments, &block) if method.to_s =~ /^((en|de)crypt)_(.+)$/ && attr_encrypted?($3) - send($1, $3, *arguments) + send("attr_encrypted_#{$1}", $3, *arguments) else super end @@ -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) + 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, 'test@example.com') - 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, 'test@example.com') + def attr_encrypted_encrypt(attribute, value) + 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| diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index a6cb299e..62cec13d 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -13,7 +13,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 @@ -29,8 +29,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 @@ -56,7 +56,7 @@ def attr_encrypted(*attrs) options = attrs.extract_options! attr = attrs.pop attribute attr - options.merge! encrypted_attributes[attr] + options.merge! attr_encrypted_encrypted_attributes[attr] define_method("#{attr}_was") do attribute_was(attr) @@ -131,10 +131,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 diff --git a/test/active_record_test.rb b/test/active_record_test.rb index 3eb14988..54be18fa 100644 --- a/test/active_record_test.rb +++ b/test/active_record_test.rb @@ -84,7 +84,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 @@ -278,14 +278,14 @@ def test_should_allow_proc_based_mode @person = PersonWithProcMode.create(email: 'test@example.com', 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 diff --git a/test/attr_encrypted_test.rb b/test/attr_encrypted_test.rb index 84cb130a..0df966a4 100644 --- a/test/attr_encrypted_test.rb +++ b/test/attr_encrypted_test.rb @@ -83,11 +83,11 @@ 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 @@ -95,7 +95,7 @@ def test_attr_encrypted_should_return_true_for_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 = 'test@example.com' - assert_equal 'test@example.com', @user1.decrypt(:email, @user1.encrypted_email) + assert_equal 'test@example.com', @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 diff --git a/test/legacy_attr_encrypted_test.rb b/test/legacy_attr_encrypted_test.rb index 875086d2..49cbec9b 100644 --- a/test/legacy_attr_encrypted_test.rb +++ b/test/legacy_attr_encrypted_test.rb @@ -58,11 +58,11 @@ def self.call(object) class LegacyAttrEncryptedTest < Minitest::Test def test_should_store_email_in_encrypted_attributes - assert LegacyUser.encrypted_attributes.include?(:email) + assert LegacyUser.attr_encrypted_encrypted_attributes.include?(:email) end def test_should_not_store_salt_in_encrypted_attributes - assert !LegacyUser.encrypted_attributes.include?(:salt) + assert !LegacyUser.attr_encrypted_encrypted_attributes.include?(:salt) end def test_attr_encrypted_should_return_true_for_email @@ -70,7 +70,7 @@ def test_attr_encrypted_should_return_true_for_email end def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line - refute_equal LegacyUser.encrypted_attributes[:email][:attribute], LegacyUser.encrypted_attributes[:without_encoding][:attribute] + refute_equal LegacyUser.attr_encrypted_encrypted_attributes[:email][:attribute], LegacyUser.attr_encrypted_encrypted_attributes[:without_encoding][:attribute] end def test_attr_encrypted_should_return_false_for_salt @@ -201,7 +201,7 @@ def test_should_use_options_found_in_the_attr_encrypted_options_attribute end def test_should_inherit_encrypted_attributes - assert_equal [LegacyUser.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, LegacyAdmin.encrypted_attributes.keys.collect { |key| key.to_s }.sort + assert_equal [LegacyUser.attr_encrypted_encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, LegacyAdmin.attr_encrypted_encrypted_attributes.keys.collect { |key| key.to_s }.sort end def test_should_inherit_attr_encrypted_options @@ -211,7 +211,7 @@ def test_should_inherit_attr_encrypted_options def test_should_not_inherit_unrelated_attributes assert LegacySomeOtherClass.attr_encrypted_options.empty? - assert LegacySomeOtherClass.encrypted_attributes.empty? + assert LegacySomeOtherClass.attr_encrypted_encrypted_attributes.empty? end def test_should_evaluate_a_symbol_option @@ -268,7 +268,7 @@ def test_should_not_encrypt_with_true_unless end def test_should_work_with_aliased_attr_encryptor - assert LegacyUser.encrypted_attributes.include?(:aliased) + assert LegacyUser.attr_encrypted_encrypted_attributes.include?(:aliased) end def test_should_always_reset_options From de318e049bdb99abd9b9c238a434ef046a403473 Mon Sep 17 00:00:00 2001 From: Vimal V Nair Date: Sat, 18 Mar 2023 13:08:15 +0530 Subject: [PATCH 12/34] Hardcoding sqlite3 gem version to 1.5.4 since newer sqlite3 versions removed native gem support for Ruby 2.6 --- attr_encrypted.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 798f4704..e45b0a85 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -43,7 +43,7 @@ Gem::Specification.new do |s| s.add_development_dependency('activerecord-jdbcsqlite3-adapter') s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke else - s.add_development_dependency('sqlite3') + s.add_development_dependency('sqlite3', '= 1.5.4') end s.add_development_dependency('dm-sqlite-adapter') s.add_development_dependency('pry') From b5658765e3b7c31065e397ef5be5e6914a7e2afc Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Tue, 28 Mar 2023 07:22:21 -0600 Subject: [PATCH 13/34] Release 4.0.0 --- CHANGELOG.md | 60 ++++++++++++++++++++++++----------- README.md | 6 +--- attr_encrypted.gemspec | 6 ++-- lib/attr_encrypted/version.rb | 4 +-- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52ef721b..536e714c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ -# attr_encrypted # +# attr_encrypted + +## 4.0.0 + +* Added: Support for Ruby >= 3.0. +* Added: Rails 7 support. +* Changed: Using `#encrypted_attributes` is no longer supported. Instead, use `#attr_encrypted_encrypted_attributes` to avoid + collision with Active Record 7 native encryption. + +## 3.1.0 -## 3.1.0 ## * Added: Abitilty to encrypt empty values. (@tamird) * Added: MIT license * Added: MRI 2.5.x support (@saghaulor) @@ -11,23 +19,28 @@ * Fixed: Only check empty on strings, allows for encrypting non-string type objects * Fixed: Fixed how accessors for db columns are defined in the ActiveRecord adapter, preventing premature definition. (@nagachika) -## 3.0.3 ## +## 3.0.3 + * Fixed: attr_was would decrypt the attribute upon every call. This is inefficient and introduces problems when the options change between decrypting an old value and encrypting a new value; for example, when rotating the encryption key. As such, the new approach caches the decrypted value of the old encrypted value such that the old options are no longer needed. (@johnny-lai) (@saghaulor) -## 3.0.2 ## +## 3.0.2 + * Changed: Removed alias_method_chain for compatibility with Rails v5.x (@grosser) * Changed: Updated Travis build matrix to include Rails 5. (@saghaulor) (@connorshea) * Changed: Removed `.silence_stream` from tests as it has been removed from Rails 5. (@sblackstone) -## 3.0.1 ## +## 3.0.1 + * Fixed: attr_was method no longer calls undefined methods. (@saghaulor) -## 3.0.0 ## +## 3.0.0 + * Changed: Updated gemspec to use Encryptor v3.0.0. (@saghaulor) * Changed: Updated README with instructions related to moving from v2.0.0 to v3.0.0. (@saghaulor) * Fixed: ActiveModel::Dirty methods in the ActiveRecord adapter. (@saghaulor) -## 2.0.0 ## +## 2.0.0 + * Added: Now using Encryptor v2.0.0 (@saghaulor) * Added: Options are copied to the instance. (@saghaulor) * Added: Operation option is set during encryption/decryption to allow options to be evaluated in the context of the current operation. (@saghaulor) @@ -48,51 +61,62 @@ * Removed: Support for Rails < 3.x (@saghaulor) * Removed: Unnecessary use of `alias_method` from ActiveRecord adapter. (@saghaulor) -## 1.4.0 ## +## 1.4.0 + * Added: ActiveModel::Dirty#attribute_was (@saghaulor) * Added: ActiveModel::Dirty#attribute_changed? (@mwean) -## 1.3.5 ## +## 1.3.5 + * Changed: Fixed gemspec to explicitly depend on Encryptor v1.3.0 (@saghaulor) * Fixed: Evaluate `:mode` option as a symbol or proc. (@cheynewallace) -## 1.3.4 ## +## 1.3.4 + * Added: ActiveRecord::Base.reload support. (@rcook) * Fixed: ActiveRecord adapter no longer forces attribute hashes to be string-keyed. (@tamird) * Fixed: Mass assignment protection in ActiveRecord 4. (@tamird) * Changed: Now using rubygems over https. (@tamird) * Changed: Let ActiveRecord define attribute methods. (@saghaulor) -## 1.3.3 ## +## 1.3.3 + * Added: Alias attr_encryptor and attr_encrpted. (@Billy Monk) -## 1.3.2 ## +## 1.3.2 + * Fixed: Bug regarding strong parameters. (@S. Brent Faulkner) * Fixed: Bug regarding loading per instance IV and salt. (@S. Brent Faulkner) * Fixed: Bug regarding assigning nil. (@S. Brent Faulkner) * Added: Support for protected attributes. (@S. Brent Faulkner) * Added: Support for ActiveRecord 4. (@S. Brent Faulkner) -## 1.3.1 ## +## 1.3.1 + * Added: Support for Rails 2.3.x and 3.1.x. (@S. Brent Faulkner) -## 1.3.0 ## +## 1.3.0 + * Fixed: Serialization bug. (@Billy Monk) * Added: Support for :per_attribute_iv_and_salt mode. (@rcook) * Fixed: Added dependencies to gemspec. (@jmazzi) -## 1.2.1 ## +## 1.2.1 + * Added: Force encoding when not marshaling. (@mosaicxm) * Fixed: Issue specifying multiple attributes on the same line. (@austintaylor) * Added: Typecasting to String before encryption (@shuber) * Added: `"#{attribute}?"` method. (@shuber) -## 1.2.0 ## +## 1.2.0 + * Changed: General code refactoring (@shuber) -## 1.1.2 ## +## 1.1.2 + * No significant changes -## 1.1.1 ## +## 1.1.1 + * Changled: Updated README. (@shuber) * Added: `before_type_cast` alias to ActiveRecord adapter. (@shuber) diff --git a/README.md b/README.md index 3414801f..cddb8cf0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -## Maintainer(s) wanted!!! - -**If you have an interest in maintaining this project... please see https://github.com/attr-encrypted/attr_encrypted/issues/379** - # attr_encrypted [![Build Status](https://secure.travis-ci.org/attr-encrypted/attr_encrypted.svg)](https://travis-ci.org/attr-encrypted/attr_encrypted) [![Test Coverage](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/coverage.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted/coverage) [![Code Climate](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) [![security](https://hakiri.io/github/attr-encrypted/attr_encrypted/master.svg)](https://hakiri.io/github/attr-encrypted/attr_encrypted/master) @@ -16,7 +12,7 @@ It works with ANY class, however, you get a few extra features when you're using Add attr_encrypted to your gemfile: ```ruby - gem "attr_encrypted", "~> 3.1.0" + gem "attr_encrypted" ``` Then install the gem: diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index e45b0a85..0bd1b9c5 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -53,9 +53,7 @@ Gem::Specification.new do |s| s.cert_chain = ['certs/saghaulor.pem'] s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/ - s.post_install_message = "\n\n\nWARNING: Several insecure default options and features were deprecated in attr_encrypted v2.0.0.\n -Additionally, there was a bug in Encryptor v2.0.0 that insecurely encrypted data when using an AES-*-GCM algorithm.\n -This bug was fixed but introduced breaking changes between v2.x and v3.x.\n -Please see the README for more information regarding upgrading to attr_encrypted v3.0.0.\n\n\n" + s.post_install_message = "\n\n\nWARNING: Using `#encrypted_attributes` is no longer supported. Instead, use `#attr_encrypted_encrypted_attributes` to avoid + collision with Active Record 7 native encryption.\n\n\n" end diff --git a/lib/attr_encrypted/version.rb b/lib/attr_encrypted/version.rb index 723ebe9f..c3440d67 100644 --- a/lib/attr_encrypted/version.rb +++ b/lib/attr_encrypted/version.rb @@ -3,8 +3,8 @@ module AttrEncrypted # Contains information about this gem's version module Version - MAJOR = 3 - MINOR = 1 + MAJOR = 4 + MINOR = 0 PATCH = 0 # Returns a version string by joining MAJOR, MINOR, and PATCH with '.' From 7e857a5f6199fa9577658bd8979f722841f9e252 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Thu, 6 Apr 2023 07:57:32 -0600 Subject: [PATCH 14/34] Drop gem signing (#436) --- attr_encrypted.gemspec | 3 --- certs/saghaulor.pem | 21 --------------------- 2 files changed, 24 deletions(-) delete mode 100644 certs/saghaulor.pem diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 0bd1b9c5..029a965c 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -50,9 +50,6 @@ Gem::Specification.new do |s| s.add_development_dependency('simplecov') s.add_development_dependency('simplecov-rcov') - s.cert_chain = ['certs/saghaulor.pem'] - s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/ - s.post_install_message = "\n\n\nWARNING: Using `#encrypted_attributes` is no longer supported. Instead, use `#attr_encrypted_encrypted_attributes` to avoid collision with Active Record 7 native encryption.\n\n\n" diff --git a/certs/saghaulor.pem b/certs/saghaulor.pem deleted file mode 100644 index 8b3fa376..00000000 --- a/certs/saghaulor.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlzYWdo -YXVsb3IxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv -bTAeFw0xODAyMTIwMzMzMThaFw0xOTAyMTIwMzMzMThaMEAxEjAQBgNVBAMMCXNh -Z2hhdWxvcjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD -Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvOLqbSmj5txfw39a -Ki0g3BJWGrfGBiSRq9aThUGzoiaqyDo/m1WMQdgPioZG+P923okChEWFjhSymBQU -eMdys6JRPm5ortp5sh9gesOWoozqb8R55d8rr1V7pY533cCut53Kb1wiitjkfXjR -efT2HPh6nV6rYjGMJek/URaCNzsZo7HCkRsKdezP+BKr4V4wOka69tfJX5pcvFvR -iiqfaiP4RK12hYdsFnSVKiKP7SAFTFiYcohbL8TUW6ezQQqJCK0M6fu74EWVCnBS -gFVjj931BuD8qhuxMiB6uC6FKxemB5TRGBLzn7RcrOMAo2inMAopjkGeQJUAyVCm -J5US3wIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU -hJEuSZgvuuIhIsxQ/0pRQTBVzokwHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls -LmNvbTAeBgNVHRIEFzAVgRNzYWdoYXVsb3JAZ21haWwuY29tMA0GCSqGSIb3DQEB -BQUAA4IBAQCsBS2cxqTmV4nXJEH/QbdgjVDAZbK6xf2gpM3vCRlYsy7Wz6GEoOpD -bzRkjxZwGNbhXShMUZwm6zahYQ/L1/HFztLoMBMkm8EIfPxH0PDrP4aWl0oyWxmU -OLm0/t9icSWRPPJ1tLJvuAaDdVpY5dEHd6VdnNJGQC5vHKRInt1kEyqEttIJ/xmJ -leSEFyMeoFsR+C/WPG9WSC+xN0eXqakCu6YUJoQzCn/7znv8WxpHEbeZjNIHq0qb -nbqZ/ZW1bwzj1T/NIbnMr37wqV29XwkI4+LbewMkb6/bDPYl0qZpAkCxKtGYCCJp -l6KPs9K/72yH00dxuAhiTXikTkcLXeQJ ------END CERTIFICATE----- From 0462d56950b1163619c99bdd2b996b317b4b2cf7 Mon Sep 17 00:00:00 2001 From: Matt Larraz Date: Mon, 24 Apr 2023 18:27:56 -0400 Subject: [PATCH 15/34] Drop support for DataMapper (#439) This project has been dead since 2018 --- README.md | 6 +-- attr_encrypted.gemspec | 1 - lib/attr_encrypted.rb | 2 +- lib/attr_encrypted/adapters/data_mapper.rb | 24 --------- test/data_mapper_test.rb | 59 ---------------------- test/legacy_data_mapper_test.rb | 57 --------------------- test/test_helper.rb | 1 - 7 files changed, 4 insertions(+), 146 deletions(-) delete mode 100644 lib/attr_encrypted/adapters/data_mapper.rb delete mode 100644 test/data_mapper_test.rb delete mode 100644 test/legacy_data_mapper_test.rb diff --git a/README.md b/README.md index cddb8cf0..be9c8863 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Generates attr_accessors that transparently encrypt and decrypt attributes. -It works with ANY class, however, you get a few extra features when you're using it with `ActiveRecord`, `DataMapper`, or `Sequel`. +It works with ANY class, however, you get a few extra features when you're using it with `ActiveRecord` or `Sequel`. ## Installation @@ -23,7 +23,7 @@ Then install the gem: ## Usage -If you're using an ORM like `ActiveRecord`, `DataMapper`, or `Sequel`, using attr_encrypted is easy: +If you're using an ORM like `ActiveRecord` or `Sequel`, using attr_encrypted is easy: ```ruby class User @@ -364,7 +364,7 @@ NOTE: This only works if all records are encrypted with the same encryption key __NOTE: This feature is deprecated and will be removed in the next major release.__ -### DataMapper and Sequel +### Sequel #### Default options diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 029a965c..2c30d419 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -35,7 +35,6 @@ Gem::Specification.new do |s| end s.add_development_dependency('activerecord', activerecord_version) s.add_development_dependency('actionpack', activerecord_version) - s.add_development_dependency('datamapper') s.add_development_dependency('rake') s.add_development_dependency('minitest') s.add_development_dependency('sequel') diff --git a/lib/attr_encrypted.rb b/lib/attr_encrypted.rb index 4537cd59..5cb46c3f 100644 --- a/lib/attr_encrypted.rb +++ b/lib/attr_encrypted.rb @@ -54,7 +54,7 @@ def self.extended(base) # :nodoc: # string instead of just 'true'. See # http://www.ruby-doc.org/core/classes/Array.html#M002245 # for more encoding directives. - # Defaults to false unless you're using it with ActiveRecord, DataMapper, or Sequel. + # Defaults to false unless you're using it with ActiveRecord or Sequel. # # encode_iv: Defaults to true. diff --git a/lib/attr_encrypted/adapters/data_mapper.rb b/lib/attr_encrypted/adapters/data_mapper.rb deleted file mode 100644 index 03fb5caa..00000000 --- a/lib/attr_encrypted/adapters/data_mapper.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -if defined?(DataMapper) - module AttrEncrypted - module Adapters - module DataMapper - def self.extended(base) # :nodoc: - class << base - alias_method :included_without_attr_encrypted, :included - alias_method :included, :included_with_attr_encrypted - end - end - - def included_with_attr_encrypted(base) - included_without_attr_encrypted(base) - base.extend AttrEncrypted - base.attr_encrypted_options[:encode] = true - end - end - end - end - - DataMapper::Resource.extend AttrEncrypted::Adapters::DataMapper -end diff --git a/test/data_mapper_test.rb b/test/data_mapper_test.rb deleted file mode 100644 index 3fb284a6..00000000 --- a/test/data_mapper_test.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -require_relative 'test_helper' - -DataMapper.setup(:default, 'sqlite3::memory:') - -class Client - include DataMapper::Resource - - property :id, Serial - property :encrypted_email, String - property :encrypted_email_iv, String - property :encrypted_email_salt, String - - property :encrypted_credentials, Text - property :encrypted_credentials_iv, Text - property :encrypted_credentials_salt, Text - - self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt - - attr_encrypted :email, :key => SECRET_KEY - attr_encrypted :credentials, :key => SECRET_KEY, :marshal => true - - def initialize(attrs = {}) - super attrs - self.credentials ||= { :username => 'example', :password => 'test' } - end -end - -DataMapper.auto_migrate! - -class DataMapperTest < Minitest::Test - - def setup - Client.all.each(&:destroy) - end - - def test_should_encrypt_email - @client = Client.new :email => 'test@example.com' - assert @client.save - refute_nil @client.encrypted_email - refute_equal @client.email, @client.encrypted_email - assert_equal @client.email, Client.first.email - end - - def test_should_marshal_and_encrypt_credentials - @client = Client.new - assert @client.save - refute_nil @client.encrypted_credentials - refute_equal @client.credentials, @client.encrypted_credentials - assert_equal @client.credentials, Client.first.credentials - assert Client.first.credentials.is_a?(Hash) - end - - def test_should_encode_by_default - assert Client.attr_encrypted_options[:encode] - end - -end diff --git a/test/legacy_data_mapper_test.rb b/test/legacy_data_mapper_test.rb deleted file mode 100644 index 03916dd9..00000000 --- a/test/legacy_data_mapper_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -require_relative 'test_helper' - -DataMapper.setup(:default, 'sqlite3::memory:') - -class LegacyClient - include DataMapper::Resource - self.attr_encrypted_options[:insecure_mode] = true - self.attr_encrypted_options[:algorithm] = 'aes-256-cbc' - self.attr_encrypted_options[:mode] = :single_iv_and_salt - - property :id, Serial - property :encrypted_email, String - property :encrypted_credentials, Text - property :salt, String - - attr_encrypted :email, :key => 'a secret key', mode: :single_iv_and_salt - attr_encrypted :credentials, :key => Proc.new { |client| Encryptor.encrypt(:value => client.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true, mode: :single_iv_and_salt - - def initialize(attrs = {}) - super attrs - self.salt ||= Digest::SHA1.hexdigest((Time.now.to_i * rand(5)).to_s) - self.credentials ||= { :username => 'example', :password => 'test' } - end -end - -DataMapper.auto_migrate! - -class LegacyDataMapperTest < Minitest::Test - - def setup - LegacyClient.all.each(&:destroy) - end - - def test_should_encrypt_email - @client = LegacyClient.new :email => 'test@example.com' - assert @client.save - refute_nil @client.encrypted_email - refute_equal @client.email, @client.encrypted_email - assert_equal @client.email, LegacyClient.first.email - end - - def test_should_marshal_and_encrypt_credentials - @client = LegacyClient.new - assert @client.save - refute_nil @client.encrypted_credentials - refute_equal @client.credentials, @client.encrypted_credentials - assert_equal @client.credentials, LegacyClient.first.credentials - assert LegacyClient.first.credentials.is_a?(Hash) - end - - def test_should_encode_by_default - assert LegacyClient.attr_encrypted_options[:encode] - end - -end diff --git a/test/test_helper.rb b/test/test_helper.rb index f8283fff..43fa0116 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -23,7 +23,6 @@ end require 'active_record' -require 'data_mapper' require 'digest/sha2' require 'sequel' ActiveSupport::Deprecation.behavior = :raise From b802253d6fbd9b059646d7e27568b7067146318f Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 28 Apr 2023 20:19:31 -0600 Subject: [PATCH 16/34] Update README.md (#441) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be9c8863..7b57f2a9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # attr_encrypted -[![Build Status](https://secure.travis-ci.org/attr-encrypted/attr_encrypted.svg)](https://travis-ci.org/attr-encrypted/attr_encrypted) [![Test Coverage](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/coverage.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted/coverage) [![Code Climate](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) [![security](https://hakiri.io/github/attr-encrypted/attr_encrypted/master.svg)](https://hakiri.io/github/attr-encrypted/attr_encrypted/master) +[![Build Status](https://app.travis-ci.com/attr-encrypted/attr_encrypted.svg?branch=master)](https://travis-ci.org/attr-encrypted/attr_encrypted) [![Test Coverage](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/coverage.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted/coverage) [![Code Climate](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) Generates attr_accessors that transparently encrypt and decrypt attributes. From 799d60b0917c3427a5fe6eb6b08002781a2625aa Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Sat, 29 Apr 2023 09:01:34 -0600 Subject: [PATCH 17/34] Start testing ruby 3 (#440) * Start testing ruby 3 * Exclude older AR and newer Ruby combos * Add Ruby 3.0.6 as well * Exclude 3.0.6 and AR 5.x --- .travis.yml | 15 +++++++++++++++ CHANGELOG.md | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/.travis.yml b/.travis.yml index b122db64..c8c18961 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ cache: bundler rvm: - 2.6.10 - 2.7.6 + - 3.0.6 + - 3.1.4 + - 3.2.2 env: - ACTIVERECORD=5.1.1 - ACTIVERECORD=5.2.8 @@ -16,6 +19,18 @@ jobs: exclude: - rvm: 2.6.10 env: ACTIVERECORD=7.0.4 + - rvm: 3.0.6 + env: ACTIVERECORD=5.1.1 + - rvm: 3.0.6 + env: ACTIVERECORD=5.2.8 + - rvm: 3.1.4 + env: ACTIVERECORD=5.1.1 + - rvm: 3.1.4 + env: ACTIVERECORD=5.2.8 + - rvm: 3.2.2 + env: ACTIVERECORD=5.1.1 + - rvm: 3.2.2 + env: ACTIVERECORD=5.2.8 addons: code_climate: diff --git a/CHANGELOG.md b/CHANGELOG.md index 536e714c..13b826b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # attr_encrypted +## Unreleased + +* Drop support for `datamapper` which has not had a release since October 2011. This is in an attempt to make + maintenance and testing easier moving forward. + ## 4.0.0 * Added: Support for Ruby >= 3.0. From dee8d41439ee6026889d2fb3308905c0e3c2cbc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Barri=C3=A9?= Date: Sat, 29 Apr 2023 17:07:57 +0200 Subject: [PATCH 18/34] Use ActiveRecord.deprecator when available (#437) Rails 7.1 will deprecate using the singleton ActiveSupport::Deprecation instance. This directly uses the one from ActiveRecord. Co-authored-by: Josh Branham --- test/legacy_active_record_test.rb | 12 +++++++++--- test/test_helper.rb | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/test/legacy_active_record_test.rb b/test/legacy_active_record_test.rb index 80231857..27038825 100644 --- a/test/legacy_active_record_test.rb +++ b/test/legacy_active_record_test.rb @@ -29,9 +29,15 @@ class LegacyPerson < ActiveRecord::Base attr_encrypted :email, :key => 'a secret key' attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true - ActiveSupport::Deprecation.silenced = true - def after_initialize; end - ActiveSupport::Deprecation.silenced = false + if ActiveRecord.respond_to?(:deprecator) + ActiveRecord.deprecator.silence do + def after_initialize; end + end + else + ActiveSupport::Deprecation.silenced = true + def after_initialize; end + ActiveSupport::Deprecation.silenced = false + end after_initialize :initialize_salt_and_credentials diff --git a/test/test_helper.rb b/test/test_helper.rb index 43fa0116..a8289fd8 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -25,7 +25,11 @@ require 'active_record' require 'digest/sha2' require 'sequel' -ActiveSupport::Deprecation.behavior = :raise +if ActiveRecord.respond_to?(:deprecator) + ActiveRecord.deprecator.behavior = :raise +else + ActiveSupport::Deprecation.behavior = :raise +end $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $:.unshift(File.dirname(__FILE__)) From 6bab9dea9218f310df59c0399a0b4011b8110021 Mon Sep 17 00:00:00 2001 From: Matt Larraz Date: Fri, 26 May 2023 15:48:09 -0400 Subject: [PATCH 19/34] Use Github Actions for CI (#442) * Use Github Actions for CI * Add back old Rails versions * Only test Rails 5 on Ruby 2.7 --------- Co-authored-by: Josh Branham --- .github/workflows/CI.yml | 40 ++++++++++++++++++++++++++++++++++++++++ attr_encrypted.gemspec | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/CI.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 00000000..ffb28493 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +jobs: + test: + name: Ruby ${{ matrix.ruby }} / ActiveRecord ${{ matrix.active_record }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + active_record: + - '6.0' + - '6.1' + - '7.0' + ruby: + - '2.7' + - '3.0' + - '3.1' + - '3.2' + include: + - active_record: '5.1' + ruby: '2.7' + - active_record: '5.2' + ruby: '2.7' + env: + ACTIVERECORD: ${{ matrix.active_record }} + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - run: | + bundle exec rake test diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 2c30d419..089ec267 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -29,7 +29,7 @@ Gem::Specification.new do |s| s.add_dependency('encryptor', ['~> 3.0.0']) # support for testing with specific active record version activerecord_version = if ENV.key?('ACTIVERECORD') - "~> #{ENV['ACTIVERECORD']}" + "~> #{ENV['ACTIVERECORD']}.0" else '>= 2.0.0' end From d93c01739f06157e8ae216c471d355609427a216 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Sun, 21 Jan 2024 20:14:01 -0700 Subject: [PATCH 20/34] Fix minitest guard for rails 4 breaking specs (#448) Co-authored-by: Josh Branham --- test/test_helper.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index a8289fd8..379c8923 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -16,15 +16,10 @@ end require 'minitest/autorun' - -# Rails 4.0.x pins to an old minitest -unless defined?(MiniTest::Test) - MiniTest::Test = MiniTest::Unit::TestCase -end - require 'active_record' require 'digest/sha2' require 'sequel' + if ActiveRecord.respond_to?(:deprecator) ActiveRecord.deprecator.behavior = :raise else From 502d44e766a31043efde9dac89ee4c00ef46dea8 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Sun, 21 Jan 2024 20:18:55 -0700 Subject: [PATCH 21/34] Add Josh and Mike to authors (#447) * Add Josh and Mike to authors Signed-off-by: Josh Branham * Update attr_encrypted.gemspec Signed-off-by: Josh Branham --------- Signed-off-by: Josh Branham --- attr_encrypted.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 089ec267..a556d411 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -14,8 +14,8 @@ Gem::Specification.new do |s| s.summary = 'Encrypt and decrypt attributes' s.description = 'Generates attr_accessors that encrypt and decrypt attributes transparently' - s.authors = ['Sean Huber', 'S. Brent Faulkner', 'William Monk', 'Stephen Aghaulor'] - s.email = ['seah@shuber.io', 'sbfaulkner@gmail.com', 'billy.monk@gmail.com', 'saghaulor@gmail.com'] + s.authors = ['Sean Huber', 'S. Brent Faulkner', 'William Monk', 'Stephen Aghaulor', 'Josh Branham', 'Mike Vastola'] + s.email = ['seah@shuber.io', 'sbfaulkner@gmail.com', 'billy.monk@gmail.com', 'saghaulor@gmail.com', 'josh.php@gmail.com', 'Mike@Vasto.la'] s.homepage = 'http://github.com/attr-encrypted/attr_encrypted' s.license = 'MIT' From 83f52d4c45b691676680e8ce29378ef7842b1739 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Sun, 21 Jan 2024 20:25:30 -0700 Subject: [PATCH 22/34] Add GitHub Actions badge to README (#449) * Update README.md Signed-off-by: Josh Branham * Update README.md Signed-off-by: Josh Branham --------- Signed-off-by: Josh Branham --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b57f2a9..bfae1b1d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # attr_encrypted -[![Build Status](https://app.travis-ci.com/attr-encrypted/attr_encrypted.svg?branch=master)](https://travis-ci.org/attr-encrypted/attr_encrypted) [![Test Coverage](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/coverage.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted/coverage) [![Code Climate](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) +![workflow](https://github.com/attr-encrypted/attr_encrypted/actions/workflows/CI.yml/badge.svg) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) Generates attr_accessors that transparently encrypt and decrypt attributes. From 81e3e4fb328f4deb51705ade33e34d1fc7fba106 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 26 Jan 2024 17:36:52 -0700 Subject: [PATCH 23/34] Deprecate testing with travis (#450) --- .travis.yml | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c8c18961..00000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -language: ruby -dist: focal -os: linux -cache: bundler -rvm: - - 2.6.10 - - 2.7.6 - - 3.0.6 - - 3.1.4 - - 3.2.2 -env: - - ACTIVERECORD=5.1.1 - - ACTIVERECORD=5.2.8 - - ACTIVERECORD=6.0.6 - - ACTIVERECORD=6.1.7 - - ACTIVERECORD=7.0.4 -jobs: - fast_finish: false - exclude: - - rvm: 2.6.10 - env: ACTIVERECORD=7.0.4 - - rvm: 3.0.6 - env: ACTIVERECORD=5.1.1 - - rvm: 3.0.6 - env: ACTIVERECORD=5.2.8 - - rvm: 3.1.4 - env: ACTIVERECORD=5.1.1 - - rvm: 3.1.4 - env: ACTIVERECORD=5.2.8 - - rvm: 3.2.2 - env: ACTIVERECORD=5.1.1 - - rvm: 3.2.2 - env: ACTIVERECORD=5.2.8 - -addons: - code_climate: - repo_token: a90435ed4954dd6e9f3697a20c5bc3754f67d94703f870e8fc7b00f69f5b2d06 From 17ac2f003e58869a697841769b95fc134081dcd9 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Thu, 2 May 2024 23:25:22 +0900 Subject: [PATCH 24/34] Add rails7.1 and Ruby3.3 to CI matrix (#453) --- .github/workflows/CI.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ffb28493..74c380ae 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,6 +17,7 @@ jobs: - '6.0' - '6.1' - '7.0' + - '7.1' ruby: - '2.7' - '3.0' @@ -27,6 +28,8 @@ jobs: ruby: '2.7' - active_record: '5.2' ruby: '2.7' + - active_record: '7.1' + ruby: '3.3' env: ACTIVERECORD: ${{ matrix.active_record }} steps: From efe06f3803c784afaffe79c00e21f64a27b22f6e Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Thu, 30 May 2024 09:22:36 -0600 Subject: [PATCH 25/34] Release v4.1.0 (#455) --- CHANGELOG.md | 4 ++-- README.md | 1 - lib/attr_encrypted/version.rb | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13b826b2..a67308ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # attr_encrypted -## Unreleased +## 4.1.0 -* Drop support for `datamapper` which has not had a release since October 2011. This is in an attempt to make +* Changed: Dropped support for `datamapper` which has not had a release since October 2011. This is in an attempt to make maintenance and testing easier moving forward. ## 4.0.0 diff --git a/README.md b/README.md index bfae1b1d..da841989 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ Generates attr_accessors that transparently encrypt and decrypt attributes. It works with ANY class, however, you get a few extra features when you're using it with `ActiveRecord` or `Sequel`. - ## Installation Add attr_encrypted to your gemfile: diff --git a/lib/attr_encrypted/version.rb b/lib/attr_encrypted/version.rb index c3440d67..8f554135 100644 --- a/lib/attr_encrypted/version.rb +++ b/lib/attr_encrypted/version.rb @@ -4,7 +4,7 @@ module AttrEncrypted # Contains information about this gem's version module Version MAJOR = 4 - MINOR = 0 + MINOR = 1 PATCH = 0 # Returns a version string by joining MAJOR, MINOR, and PATCH with '.' From e96f4adeb7ed5596f092d499b8661b3525fe78a2 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Tue, 17 Sep 2024 06:36:51 +0900 Subject: [PATCH 26/34] Fix SystemStackError when extending the reload method with Module#prepend (#457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example, when using the master branch of activerecord-multi-tenant, if activerecord-multi-tenant and attr_encrypted are listed in the Gemfile in that order, calling the reload method raises a SystemStackError. This happens because activerecord-multi-tenant extends Active Record’s reload method using prepend, while attr_encrypted extends it using an alias method. Here’s an example of how extending the same method with both prepend and alias methods in that order can result in a SystemStackError ``` class Hello def hello 'hello' end end Hello.prepend(Module.new do def hello super end end) Hello.class_eval do alias orig_hello hello def hello "#{orig_hello} world" end end Hello.new.hello #=> SystemStackError ``` However, reversing the order works: ``` class Hello def hello 'hello' end end Hello.class_eval do alias orig_hello hello def hello "#{orig_hello} world" end end Hello.prepend(Module.new do def hello super end end) Hello.new.hello #=> "hello world" ``` This issue can be resolved by standardizing the method extension to use prepend to avoid conflicts. --- lib/attr_encrypted/adapters/active_record.rb | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index 62cec13d..c1ee258a 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -6,19 +6,18 @@ module Adapters module ActiveRecord RAILS_VERSION = Gem::Version.new(::ActiveRecord::VERSION::STRING).freeze - def self.extended(base) # :nodoc: - base.class_eval do - - # https://github.com/attr-encrypted/attr_encrypted/issues/68 - alias_method :reload_without_attr_encrypted, :reload - def reload(*args, &block) - result = reload_without_attr_encrypted(*args, &block) - self.class.attr_encrypted_encrypted_attributes.keys.each do |attribute_name| - instance_variable_set("@#{attribute_name}", nil) - end - result + module Reload + def reload(...) + result = super + self.class.attr_encrypted_encrypted_attributes.keys.each do |attribute_name| + instance_variable_set("@#{attribute_name}", nil) end + result + end + end + def self.extended(base) # :nodoc: + base.class_eval do attr_encrypted_options[:encode] = true class << self @@ -148,5 +147,6 @@ def method_missing_with_attr_encrypted(method, *args, &block) ActiveSupport.on_load(:active_record) do extend AttrEncrypted extend AttrEncrypted::Adapters::ActiveRecord + prepend AttrEncrypted::Adapters::ActiveRecord::Reload end end From 18ef8b65c951751497fca2aacb25a814590a5758 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Fri, 20 Sep 2024 08:28:53 -0600 Subject: [PATCH 27/34] Release 4.1.1 (#458) --- CHANGELOG.md | 4 ++++ lib/attr_encrypted/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a67308ca..0274743e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # attr_encrypted +## 4.1.1 + +* Fixed: Fix SystemStackError when extending the reload method with Module#prepend. + ## 4.1.0 * Changed: Dropped support for `datamapper` which has not had a release since October 2011. This is in an attempt to make diff --git a/lib/attr_encrypted/version.rb b/lib/attr_encrypted/version.rb index 8f554135..200faf50 100644 --- a/lib/attr_encrypted/version.rb +++ b/lib/attr_encrypted/version.rb @@ -5,7 +5,7 @@ module AttrEncrypted module Version MAJOR = 4 MINOR = 1 - PATCH = 0 + PATCH = 1 # Returns a version string by joining MAJOR, MINOR, and PATCH with '.' # From 96bf315855d7dd7a9d6304c0f3640714c1532466 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Thu, 23 Jan 2025 17:52:43 +0900 Subject: [PATCH 28/34] Add Rails7.2, 8.0 and Ruby 3.4 to CI matrix Also updated actions/checkout to the latest v4. --- .github/workflows/CI.yml | 44 ++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 74c380ae..434df2fe 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -13,27 +13,37 @@ jobs: strategy: fail-fast: false matrix: - active_record: - - '6.0' - - '6.1' - - '7.0' - - '7.1' - ruby: - - '2.7' - - '3.0' - - '3.1' - - '3.2' include: - - active_record: '5.1' - ruby: '2.7' - - active_record: '5.2' - ruby: '2.7' - - active_record: '7.1' - ruby: '3.3' + - { active_record: '5.1', ruby: '2.7' } + - { active_record: '5.2', ruby: '2.7' } + - { active_record: '6.0', ruby: '2.7' } + - { active_record: '6.0', ruby: '3.0' } + - { active_record: '6.0', ruby: '3.1' } + - { active_record: '6.0', ruby: '3.2' } + - { active_record: '6.1', ruby: '2.7' } + - { active_record: '6.1', ruby: '3.0' } + - { active_record: '6.1', ruby: '3.1' } + - { active_record: '6.1', ruby: '3.2' } + - { active_record: '7.0', ruby: '2.7' } + - { active_record: '7.0', ruby: '3.0' } + - { active_record: '7.0', ruby: '3.1' } + - { active_record: '7.0', ruby: '3.2' } + - { active_record: '7.1', ruby: '2.7' } + - { active_record: '7.1', ruby: '3.0' } + - { active_record: '7.1', ruby: '3.1' } + - { active_record: '7.1', ruby: '3.2' } + - { active_record: '7.1', ruby: '3.3' } + - { active_record: '7.2', ruby: '3.1' } + - { active_record: '7.2', ruby: '3.2' } + - { active_record: '7.2', ruby: '3.3' } + - { active_record: '7.2', ruby: '3.4' } + - { active_record: '8.0', ruby: '3.2' } + - { active_record: '8.0', ruby: '3.3' } + - { active_record: '8.0', ruby: '3.4' } env: ACTIVERECORD: ${{ matrix.active_record }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From 71b586245e45e685cd5d90383ff931c3cf683976 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Thu, 23 Jan 2025 18:23:10 +0900 Subject: [PATCH 29/34] Fix CI failures for Rails 6.0 to 7.0. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CI failures for Rails 6.0 to 7.0 are caused by changes introduced in concurrent-ruby v1.3.5. ref: [Rails 7.0.8 fails to create an app with most recent concurrent-ruby version · Issue #54260 · rails/rails](https://github.com/rails/rails/issues/54260) Update concurrent-ruby to a version below 1.3.5 to fix the tests. --- Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index fa75df15..3118e7fd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ source 'https://rubygems.org' gemspec + +gem "concurrent-ruby", "< 1.3.5" From bf354d36d75e34c96b95a2718e59c9a180621992 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Thu, 23 Jan 2025 18:30:39 +0900 Subject: [PATCH 30/34] Set the sqlite3 version to 2.1.0 or higher for Rails 8.0. To run CI with Rails 8.0, sqlite3 version 2.1.0 or higher is required. --- attr_encrypted.gemspec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index a556d411..c676024b 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -42,7 +42,11 @@ Gem::Specification.new do |s| s.add_development_dependency('activerecord-jdbcsqlite3-adapter') s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke else - s.add_development_dependency('sqlite3', '= 1.5.4') + if ENV['ACTIVERECORD'] && Gem::Version.new(ENV['ACTIVERECORD']) >= Gem::Version.new('8.0') + s.add_development_dependency('sqlite3', '> 2.1.0') + else + s.add_development_dependency('sqlite3', '= 1.5.4') + end end s.add_development_dependency('dm-sqlite-adapter') s.add_development_dependency('pry') From 515f862df44c3cf951e6cec59557506c7cfe3726 Mon Sep 17 00:00:00 2001 From: Shinichi Maeshima Date: Thu, 23 Jan 2025 18:16:15 +0900 Subject: [PATCH 31/34] Remove the unused dm-sqlite-adapter dm-sqlite-adapter is a SQLite adapter for DataMapper. https://github.com/datamapper/dm-sqlite-adapter Since support for DataMapper was dropped in version 4.1.0, this gem is no longer needed as a dependency. --- attr_encrypted.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index c676024b..8dd52ec4 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -48,7 +48,6 @@ Gem::Specification.new do |s| s.add_development_dependency('sqlite3', '= 1.5.4') end end - s.add_development_dependency('dm-sqlite-adapter') s.add_development_dependency('pry') s.add_development_dependency('simplecov') s.add_development_dependency('simplecov-rcov') From 38b2e857fe93e226159d56f65e35b5c657261d03 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Thu, 23 Jan 2025 08:34:11 -0700 Subject: [PATCH 32/34] Set required_ruby_version >= 2.7.0 (#464) --- attr_encrypted.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/attr_encrypted.gemspec b/attr_encrypted.gemspec index 8dd52ec4..699b0705 100644 --- a/attr_encrypted.gemspec +++ b/attr_encrypted.gemspec @@ -24,14 +24,14 @@ Gem::Specification.new do |s| s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- test/*`.split("\n") - s.required_ruby_version = '>= 2.6.0' + s.required_ruby_version = '>= 2.7.0' s.add_dependency('encryptor', ['~> 3.0.0']) # support for testing with specific active record version activerecord_version = if ENV.key?('ACTIVERECORD') "~> #{ENV['ACTIVERECORD']}.0" else - '>= 2.0.0' + '>= 6.0.0' end s.add_development_dependency('activerecord', activerecord_version) s.add_development_dependency('actionpack', activerecord_version) From 49bc41de274846190a79c5af54094ead062764a5 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Thu, 23 Jan 2025 08:42:39 -0700 Subject: [PATCH 33/34] Release 4.2.0 --- CHANGELOG.md | 6 ++++++ lib/attr_encrypted/version.rb | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0274743e..1f2a69eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # attr_encrypted +## 4.2.0 + +* Changed: Set minimum Ruby version as 2.7. +* Added: Rails 7.2 and 8.0 support. +* Fixed: Further removal of `datamapper` support. + ## 4.1.1 * Fixed: Fix SystemStackError when extending the reload method with Module#prepend. diff --git a/lib/attr_encrypted/version.rb b/lib/attr_encrypted/version.rb index 200faf50..244ead08 100644 --- a/lib/attr_encrypted/version.rb +++ b/lib/attr_encrypted/version.rb @@ -4,8 +4,8 @@ module AttrEncrypted # Contains information about this gem's version module Version MAJOR = 4 - MINOR = 1 - PATCH = 1 + MINOR = 2 + PATCH = 0 # Returns a version string by joining MAJOR, MINOR, and PATCH with '.' # From c2aa160c2327f2613fbca913e9fd20bce6e98880 Mon Sep 17 00:00:00 2001 From: Josh Branham Date: Thu, 23 Jan 2025 11:11:36 -0700 Subject: [PATCH 34/34] Release 4.2.0 (#465)