diff --git a/CHANGELOG.md b/CHANGELOG.md index 975defb4..ca168f75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ * bug fixes * Do not modify `:except` option given to `#serializable_hash`. (by @dpep) +* deprecations + * `Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION` is deprecated in favor of `Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION` (@hanachin) + ### 4.7.2 - 2020-06-10 * enhancements diff --git a/lib/devise/models/authenticatable.rb b/lib/devise/models/authenticatable.rb index 9d456fa3..3df93112 100644 --- a/lib/devise/models/authenticatable.rb +++ b/lib/devise/models/authenticatable.rb @@ -2,6 +2,7 @@ require 'devise/hooks/activatable' require 'devise/hooks/csrf_cleaner' +require 'devise/rails/deprecated_constant_accessor' module Devise module Models @@ -55,11 +56,14 @@ module Devise module Authenticatable extend ActiveSupport::Concern - BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at, + UNSAFE_ATTRIBUTES_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at, :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at, :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at] + include Devise::DeprecatedConstantAccessor + deprecate_constant "BLACKLIST_FOR_SERIALIZATION", "Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION" + included do class_attribute :devise_modules, instance_writer: false self.devise_modules ||= [] @@ -109,7 +113,7 @@ module Devise if options[:force_except] options[:except].concat Array(options[:force_except]) else - options[:except].concat BLACKLIST_FOR_SERIALIZATION + options[:except].concat UNSAFE_ATTRIBUTES_FOR_SERIALIZATION end super(options) diff --git a/lib/devise/rails/deprecated_constant_accessor.rb b/lib/devise/rails/deprecated_constant_accessor.rb new file mode 100644 index 00000000..d1eff92f --- /dev/null +++ b/lib/devise/rails/deprecated_constant_accessor.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +begin + require 'active_support/deprecation/constant_accessor' + + module Devise + DeprecatedConstantAccessor = ActiveSupport::Deprecation::DeprecatedConstantAccessor #:nodoc: + end +rescue LoadError + + # Copy of constant deprecation module from Rails / Active Support version 6, so we can use it + # with Rails <= 5.0 versions. This can be removed once we support only Rails 5.1 or greater. + module Devise + module DeprecatedConstantAccessor #:nodoc: + def self.included(base) + require "active_support/inflector/methods" + + extension = Module.new do + def const_missing(missing_const_name) + if class_variable_defined?(:@@_deprecated_constants) + if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s]) + replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", Rails::VERSION::MAJOR == 4 ? caller : caller_locations) + return ActiveSupport::Inflector.constantize(replacement[:new].to_s) + end + end + super + end + + def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance) + class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants) + class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator } + end + end + base.singleton_class.prepend extension + end + end + end + +end diff --git a/test/models/serializable_test.rb b/test/models/serializable_test.rb index 245da05a..52a19813 100644 --- a/test/models/serializable_test.rb +++ b/test/models/serializable_test.rb @@ -46,6 +46,10 @@ class SerializableTest < ActiveSupport::TestCase assert_key "username", @user.as_json({ only: :username, except: [:email].freeze }.freeze)["user"] end + test 'constant `BLACKLIST_FOR_SERIALIZATION` is deprecated' do + assert_deprecated { Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION } + end + def assert_key(key, subject) assert subject.key?(key), "Expected #{subject.inspect} to have key #{key.inspect}" end