1
0
Fork 0
mirror of https://github.com/heartcombo/devise.git synced 2022-11-09 12:18:31 -05:00

Provide a more robust behavior to serializers and add :force_except option

This commit is contained in:
José Valim 2011-06-30 10:43:33 -03:00
parent 5a98e4f4e8
commit 33d7644b4f
4 changed files with 85 additions and 14 deletions

View file

@ -1,5 +1,6 @@
* bug fix
* Improve Rails 3.1 compatibility
* Provide a more robust behavior to serializers and add :force_except option
== 1.4.1

View file

@ -1,4 +1,5 @@
require 'devise/hooks/activatable'
require 'devise/models/serializable'
module Devise
module Models
@ -46,6 +47,8 @@ module Devise
module Authenticatable
extend ActiveSupport::Concern
include Devise::Models::Serializable
included do
class_attribute :devise_modules, :instance_writer => false
self.devise_modules ||= []
@ -76,20 +79,6 @@ module Devise
def authenticatable_salt
end
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
%w(to_xml serializable_hash).each do |method|
class_eval <<-RUBY, __FILE__, __LINE__
def #{method}(options={})
if self.class.respond_to?(:accessible_attributes)
options = { :only => self.class.accessible_attributes.to_a }.merge(options || {})
super(options)
else
super
end
end
RUBY
end
module ClassMethods
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)

View file

@ -0,0 +1,43 @@
module Devise
module Models
# This module redefine to_xml and serializable_hash in models for more
# secure defaults. By default, it removes from the serializable model
# all attributes that are *not* accessible. You can remove this default
# by using :force_except and passing a new list of attributes you want
# to exempt. All attributes given to :except will simply add names to
# exempt to Devise internal list.
module Serializable
extend ActiveSupport::Concern
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
%w(to_xml serializable_hash).each do |method|
class_eval <<-RUBY, __FILE__, __LINE__
def #{method}(options=nil)
options ||= {}
if options.key?(:force_except)
options[:except] = options.delete(:force_except)
super(options)
elsif self.class.blacklist_keys?
except = Array(options[:except])
super(options.merge(:except => except + self.class.blacklist_keys))
else
super
end
end
RUBY
end
module ClassMethods
# Return true if we can retrieve blacklist keys from the record.
def blacklist_keys?
@has_except_keys ||= respond_to?(:accessible_attributes) && !accessible_attributes.to_a.empty?
end
# Returns keys that should be removed when serializing the record.
def blacklist_keys
@blacklist_keys ||= to_adapter.column_names.map(&:to_s) - accessible_attributes.to_a.map(&:to_s)
end
end
end
end
end

View file

@ -0,0 +1,38 @@
require 'test_helper'
class SerializableTest < ActiveSupport::TestCase
setup do
@user = create_user
end
test 'should not include unsafe keys on XML' do
assert_match /email/, @user.to_xml
assert_no_match /confirmation-token/, @user.to_xml
end
test 'should not include unsafe keys on XML even if a new except is provided' do
assert_no_match /email/, @user.to_xml(:except => :email)
assert_no_match /confirmation-token/, @user.to_xml(:except => :email)
end
test 'should include unsafe keys on XML if a force_except is provided' do
assert_no_match /email/, @user.to_xml(:force_except => :email)
assert_match /confirmation-token/, @user.to_xml(:force_except => :email)
end
test 'should not include unsafe keys on JSON' do
assert_match /"email":/, @user.to_json
assert_no_match /"confirmation_token":/, @user.to_json
end
test 'should not include unsafe keys on JSON even if a new except is provided' do
assert_no_match /"email":/, @user.to_json(:except => :email)
assert_no_match /"confirmation_token":/, @user.to_json(:except => :email)
end
test 'should include unsafe keys on JSON if a force_except is provided' do
assert_no_match /"email":/, @user.to_json(:force_except => :email)
assert_match /"confirmation_token":/, @user.to_json(:force_except => :email)
end
end