mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Merge branch 'master' into rails4
This commit is contained in:
commit
eb0ad1c21a
38 changed files with 284 additions and 100 deletions
|
@ -1,12 +1,18 @@
|
|||
== master
|
||||
== 2.2.4
|
||||
|
||||
* enhancements
|
||||
* Add `destroy_with_password` to `DatabaseAuthenticatable`. Allows destroying a record when `:current_password` matches, similarly to how `update_with_password` works. (by @michiel3)
|
||||
* Allow to override path after password resetting (by @worker8)
|
||||
* Add `#skip_confirmation_notification!` method to `Confirmable`. Allows skipping confirmation email without auto-confirming. (by @gregates)
|
||||
* allow_unconfirmed_access_for config from `:confirmable` module can be set to `nil` that means unconfirmed access for unlimited time. (by @nashby)
|
||||
* Support Rails' token strategy on authentication (by @robhurring)
|
||||
* Support explicitly setting the http authentication key via `config.http_authentication_key` (by @neo)
|
||||
|
||||
* bug fix
|
||||
* Do not redirect when accessing devise API via JSON. (by @sebastianwr)
|
||||
* Generating scoped devise views now uses the correct scoped shared links partial instead of the default devise one (by @nashby)
|
||||
* Fix inheriting mailer templates from `Devise::Mailer`
|
||||
* Fix a bug when procs are used as default mailer in Devise (by @tomasv)
|
||||
|
||||
== 2.2.3
|
||||
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -10,7 +10,7 @@ gem "rdoc"
|
|||
group :test do
|
||||
gem "omniauth-facebook"
|
||||
gem "omniauth-openid", "~> 1.0.1"
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
gem "webrat", "0.7.3", :require => false
|
||||
gem "mocha", "~> 0.13.1", :require => false
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ GIT
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (2.2.3)
|
||||
devise (2.2.4)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
|
@ -135,7 +135,7 @@ GEM
|
|||
tzinfo (0.3.37)
|
||||
warden (1.2.1)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
webrat (0.7.3)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
|
@ -157,4 +157,4 @@ DEPENDENCIES
|
|||
rails (~> 4.0.0.rc1)
|
||||
rdoc
|
||||
sqlite3
|
||||
webrat (= 0.7.2)
|
||||
webrat (= 0.7.3)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
![Devise Logo](https://raw.github.com/plataformatec/devise/master/devise.png)
|
||||
|
||||
By [Plataformatec](http://plataformatec.com.br/).
|
||||
|
||||
[![Gem Version](https://fury-badge.herokuapp.com/rb/devise.png)](http://badge.fury.io/rb/devise)
|
||||
[![Build Status](https://secure.travis-ci.org/plataformatec/devise.png?branch=master)](http://travis-ci.org/plataformatec/devise)
|
||||
[![Build Status](https://api.travis-ci.org/plataformatec/devise.png?branch=master)](http://travis-ci.org/plataformatec/devise)
|
||||
[![Code Climate](https://codeclimate.com/github/plataformatec/devise.png)](https://codeclimate.com/github/plataformatec/devise)
|
||||
|
||||
This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
|
||||
|
|
1
Rakefile
1
Rakefile
|
@ -22,6 +22,7 @@ Rake::TestTask.new(:test) do |t|
|
|||
t.libs << 'test'
|
||||
t.pattern = 'test/**/*_test.rb'
|
||||
t.verbose = true
|
||||
t.warning = false
|
||||
end
|
||||
|
||||
desc 'Generate documentation for Devise.'
|
||||
|
|
|
@ -32,7 +32,7 @@ class Devise::ConfirmationsController < DeviseController
|
|||
|
||||
# The path used after resending confirmation instructions.
|
||||
def after_resending_confirmation_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
new_session_path(resource_name) if is_navigational_format?
|
||||
end
|
||||
|
||||
# The path used after confirmation.
|
||||
|
|
|
@ -34,17 +34,20 @@ class Devise::PasswordsController < DeviseController
|
|||
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
|
||||
set_flash_message(:notice, flash_message) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => after_sign_in_path_for(resource)
|
||||
respond_with resource, :location => after_resetting_password_path_for(resource)
|
||||
else
|
||||
respond_with resource
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def after_resetting_password_path_for(resource)
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
# The path used after sending reset password instructions
|
||||
def after_sending_reset_password_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
new_session_path(resource_name) if is_navigational_format?
|
||||
end
|
||||
|
||||
# Check if a reset_password_token is provided in the request
|
||||
|
|
|
@ -33,12 +33,12 @@ class Devise::UnlocksController < DeviseController
|
|||
|
||||
# The path used after sending unlock password instructions
|
||||
def after_sending_unlock_instructions_path_for(resource)
|
||||
new_session_path(resource)
|
||||
new_session_path(resource) if is_navigational_format?
|
||||
end
|
||||
|
||||
# The path used after unlocking the resource
|
||||
def after_unlock_path_for(resource)
|
||||
new_session_path(resource)
|
||||
new_session_path(resource) if is_navigational_format?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -142,13 +142,18 @@ MESSAGE
|
|||
#
|
||||
# Please refer to README or en.yml locale file to check what messages are
|
||||
# available.
|
||||
def set_flash_message(key, kind, options={})
|
||||
def set_flash_message(key, kind, options = {})
|
||||
message = find_message(kind, options)
|
||||
flash[key] = message if message.present?
|
||||
end
|
||||
|
||||
# Get message for given
|
||||
def find_message(kind, options = {})
|
||||
options[:scope] = "devise.#{controller_name}"
|
||||
options[:default] = Array(options[:default]).unshift(kind.to_sym)
|
||||
options[:resource_name] = resource_name
|
||||
options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
|
||||
message = I18n.t("#{options[:resource_name]}.#{kind}", options)
|
||||
flash[key] = message if message.present?
|
||||
I18n.t("#{options[:resource_name]}.#{kind}", options)
|
||||
end
|
||||
|
||||
def clean_up_passwords(object)
|
||||
|
|
|
@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.license = "MIT"
|
||||
s.licenses = ["MIT"]
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
PATH
|
||||
remote: /Users/carlos/Projects/oss/devise
|
||||
remote: ..
|
||||
specs:
|
||||
devise (2.2.3)
|
||||
devise (2.2.4)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
|
@ -65,7 +65,7 @@ GEM
|
|||
origin (~> 1.0)
|
||||
tzinfo (~> 0.3.22)
|
||||
moped (1.4.5)
|
||||
multi_json (1.7.2)
|
||||
multi_json (1.7.3)
|
||||
multipart-post (1.2.0)
|
||||
nokogiri (1.5.9)
|
||||
oauth2 (0.8.1)
|
||||
|
|
|
@ -54,8 +54,8 @@ module Devise
|
|||
@@stretches = 10
|
||||
|
||||
# The default key used when authenticating over http auth.
|
||||
mattr_accessor :http_auth_key
|
||||
@@http_auth_key = nil
|
||||
mattr_accessor :http_authentication_key
|
||||
@@http_authentication_key = nil
|
||||
|
||||
# Keys used when authenticating a user.
|
||||
mattr_accessor :authentication_keys
|
||||
|
@ -317,7 +317,7 @@ module Devise
|
|||
# == Options:
|
||||
#
|
||||
# +model+ - String representing the load path to a custom *model* for this module (to autoload.)
|
||||
# +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
|
||||
# +controller+ - Symbol representing the name of an existing or custom *controller* for this module.
|
||||
# +route+ - Symbol representing the named *route* helper for this module.
|
||||
# +strategy+ - Symbol representing if this module got a custom *strategy*.
|
||||
#
|
||||
|
@ -445,7 +445,7 @@ module Devise
|
|||
end
|
||||
end
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
# Generate a friendly string randomly to be used as token.
|
||||
def self.friendly_token
|
||||
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
|
||||
end
|
||||
|
|
|
@ -70,7 +70,7 @@ module Devise
|
|||
template_path
|
||||
end
|
||||
|
||||
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
|
||||
# Setup a subject doing an I18n lookup. At first, it attempts to set a subject
|
||||
# based on the current mapping:
|
||||
#
|
||||
# en:
|
||||
|
|
|
@ -10,7 +10,7 @@ module Devise
|
|||
#
|
||||
# * +authentication_keys+: parameters used for authentication. By default [:email].
|
||||
#
|
||||
# * +http_auth_key+: map the username passed via HTTP Auth to this parameter. Defaults to
|
||||
# * +http_authentication_key+: map the username passed via HTTP Auth to this parameter. Defaults to
|
||||
# the first element in +authentication_keys+.
|
||||
#
|
||||
# * +request_keys+: parameters from the request object used for authentication.
|
||||
|
@ -18,7 +18,7 @@ module Devise
|
|||
# passed to find_for_authentication method and considered in your model lookup.
|
||||
#
|
||||
# For instance, if you set :request_keys to [:subdomain], :subdomain will be considered
|
||||
# as key on authentication. This can also be a hash where the value is a boolean expliciting
|
||||
# as key on authentication. This can also be a hash where the value is a boolean specifying
|
||||
# if the value is required or not.
|
||||
#
|
||||
# * +http_authenticatable+: if this model allows http authentication. By default true.
|
||||
|
@ -35,7 +35,7 @@ module Devise
|
|||
# == active_for_authentication?
|
||||
#
|
||||
# After authenticating a user and in each request, Devise checks if your model is active by
|
||||
# calling model.active_for_authentication?. This method is overwriten by other devise modules. For instance,
|
||||
# calling model.active_for_authentication?. This method is overwritten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
|
||||
#
|
||||
# You overwrite this method yourself, but if you do, don't forget to call super:
|
||||
|
@ -198,7 +198,7 @@ module Devise
|
|||
module ClassMethods
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys,
|
||||
:case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage,
|
||||
:http_auth_key)
|
||||
:http_authentication_key)
|
||||
|
||||
def serialize_into_session(record)
|
||||
[record.to_key, record.authenticatable_salt]
|
||||
|
|
|
@ -39,6 +39,13 @@ module Devise
|
|||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
end
|
||||
|
||||
def initialize(*args, &block)
|
||||
@bypass_postpone = false
|
||||
@reconfirmation_required = false
|
||||
@skip_confirmation_notification = false
|
||||
super
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
|
||||
required_methods << :unconfirmed_email if klass.reconfirmable
|
||||
|
@ -221,7 +228,7 @@ module Devise
|
|||
|
||||
def postpone_email_change?
|
||||
postpone = self.class.reconfirmable && email_changed? && !@bypass_postpone
|
||||
@bypass_postpone = nil
|
||||
@bypass_postpone = false
|
||||
postpone
|
||||
end
|
||||
|
||||
|
|
|
@ -95,6 +95,21 @@ module Devise
|
|||
result
|
||||
end
|
||||
|
||||
# Destroy record when :current_password matches, otherwise returns
|
||||
# error on :current_password. It also automatically rejects
|
||||
# :current_password if it is blank.
|
||||
def destroy_with_password(current_password)
|
||||
result = if valid_password?(current_password)
|
||||
destroy
|
||||
else
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def after_database_authentication
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ module Devise
|
|||
#
|
||||
# Oauthable adds the following options to devise_for:
|
||||
#
|
||||
# * +omniauth_providers+: Which providers are avaialble to this model. It expects an array:
|
||||
# * +omniauth_providers+: Which providers are available to this model. It expects an array:
|
||||
#
|
||||
# devise_for :database_authenticatable, :omniauthable, :omniauth_providers => [:twitter]
|
||||
#
|
||||
|
@ -24,4 +24,4 @@ module Devise
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'devise/hooks/timeoutable'
|
|||
|
||||
module Devise
|
||||
module Models
|
||||
# Timeoutable takes care of veryfing whether a user session has already
|
||||
# Timeoutable takes care of verifyng whether a user session has already
|
||||
# expired or not. When a session expires after the configured time, the user
|
||||
# will be asked for credentials again, it means, he/she will be redirected
|
||||
# to the sign in page.
|
||||
|
|
|
@ -8,16 +8,16 @@ module Devise
|
|||
def filter(conditions)
|
||||
conditions = stringify_params(conditions.dup)
|
||||
|
||||
@case_insensitive_keys.each do |k|
|
||||
value = conditions[k]
|
||||
next unless value.respond_to?(:downcase)
|
||||
conditions[k] = value.downcase
|
||||
end
|
||||
conditions.merge!(filtered_hash_by_method_for_given_keys(conditions.dup, :downcase, @case_insensitive_keys))
|
||||
conditions.merge!(filtered_hash_by_method_for_given_keys(conditions.dup, :strip, @strip_whitespace_keys))
|
||||
|
||||
@strip_whitespace_keys.each do |k|
|
||||
conditions
|
||||
end
|
||||
|
||||
def filtered_hash_by_method_for_given_keys(conditions, method, condition_keys)
|
||||
condition_keys.each do |k|
|
||||
value = conditions[k]
|
||||
next unless value.respond_to?(:strip)
|
||||
conditions[k] = value.strip
|
||||
conditions[k] = value.send(method) if value.respond_to?(method)
|
||||
end
|
||||
|
||||
conditions
|
||||
|
|
|
@ -250,15 +250,11 @@ module ActionDispatch::Routing
|
|||
# end
|
||||
#
|
||||
# authenticate :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show"
|
||||
# root :to => "admin/dashboard#show", :as => :user_root
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate!(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
constraints_for(:authenticate!, scope, block) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
@ -268,25 +264,21 @@ module ActionDispatch::Routing
|
|||
# a model and allows extra constraints to be done on the instance.
|
||||
#
|
||||
# authenticated :admin do
|
||||
# root :to => 'admin/dashboard#show'
|
||||
# root :to => 'admin/dashboard#show', :as => :admin_root
|
||||
# end
|
||||
#
|
||||
# authenticated do
|
||||
# root :to => 'dashboard#show'
|
||||
# root :to => 'dashboard#show', :as => :authenticated_root
|
||||
# end
|
||||
#
|
||||
# authenticated :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show"
|
||||
# root :to => "admin/dashboard#show", :as => :user_root
|
||||
# end
|
||||
#
|
||||
# root :to => 'landing#show'
|
||||
#
|
||||
def authenticated(scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate?(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
constraints_for(:authenticate?, scope, block) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
@ -428,6 +420,17 @@ module ActionDispatch::Routing
|
|||
@scope.merge!(old)
|
||||
end
|
||||
|
||||
def constraints_for(method_to_apply, scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env['warden'].send(method_to_apply, :scope => scope) &&
|
||||
(block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def set_omniauth_path_prefix!(path_prefix) #:nodoc:
|
||||
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
|
||||
raise "Wrong OmniAuth configuration. If you are getting this exception, it means that either:\n\n" \
|
||||
|
|
|
@ -100,7 +100,7 @@ module Devise
|
|||
|
||||
# Extract a hash with attributes:values from the http params.
|
||||
def http_auth_hash
|
||||
keys = [http_auth_key, :password]
|
||||
keys = [http_authentication_key, :password]
|
||||
Hash[*keys.zip(decode_credentials).flatten]
|
||||
end
|
||||
|
||||
|
@ -134,32 +134,27 @@ module Devise
|
|||
parse_authentication_key_values(request_values, request_keys)
|
||||
end
|
||||
|
||||
# Holds the authentication keys.
|
||||
def authentication_keys
|
||||
@authentication_keys ||= mapping.to.authentication_keys
|
||||
end
|
||||
|
||||
def http_auth_key
|
||||
@http_auth_key ||= mapping.to.http_auth_key
|
||||
@http_auth_key ||= case authentication_keys
|
||||
def http_authentication_key
|
||||
@http_authentication_key ||= mapping.to.http_authentication_key || case authentication_keys
|
||||
when Array then authentication_keys.first
|
||||
when Hash then authentication_keys.keys.first
|
||||
end
|
||||
end
|
||||
|
||||
# Holds request keys.
|
||||
def request_keys
|
||||
@request_keys ||= mapping.to.request_keys
|
||||
end
|
||||
|
||||
# Returns values from the request object.
|
||||
def request_values
|
||||
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
|
||||
values = keys.map { |k| self.request.send(k) }
|
||||
Hash[keys.zip(values)]
|
||||
end
|
||||
|
||||
# Parse authentication keys considering if they should be enforced or not.
|
||||
def parse_authentication_key_values(hash, keys)
|
||||
keys.each do |key, enforce|
|
||||
value = hash[key].presence
|
||||
|
|
|
@ -7,13 +7,22 @@ module Devise
|
|||
#
|
||||
# http://myapp.example.com/?user_token=SECRET
|
||||
#
|
||||
# For HTTP, you can pass the token as username and blank password. Since some clients may require
|
||||
# a password, you can pass "X" as password and it will simply be ignored.
|
||||
# For headers, you can use basic authentication passing the token as username and
|
||||
# blank password. Since some clients may require a password, you can pass "X" as
|
||||
# password and it will simply be ignored.
|
||||
#
|
||||
# You may also pass the token using the Token authentication mechanism provided
|
||||
# by Rails: http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
|
||||
# The token options are stored in request.env['devise.token_options']
|
||||
class TokenAuthenticatable < Authenticatable
|
||||
def store?
|
||||
super && !mapping.to.skip_session_storage.include?(:token_auth)
|
||||
end
|
||||
|
||||
def valid?
|
||||
super || valid_for_token_auth?
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
resource = mapping.to.find_for_token_authentication(authentication_hash)
|
||||
return fail(:invalid_token) unless resource
|
||||
|
@ -36,7 +45,33 @@ module Devise
|
|||
false
|
||||
end
|
||||
|
||||
# Try both scoped and non scoped keys.
|
||||
# Check if the model accepts this strategy as token authenticatable.
|
||||
def token_authenticatable?
|
||||
mapping.to.http_authenticatable?(:token_options)
|
||||
end
|
||||
|
||||
# Check if this is strategy is valid for token authentication by:
|
||||
#
|
||||
# * Validating if the model allows http token authentication;
|
||||
# * If the http auth token exists;
|
||||
# * If all authentication keys are present;
|
||||
#
|
||||
def valid_for_token_auth?
|
||||
token_authenticatable? && auth_token.present? && with_authentication_hash(:token_auth, token_auth_hash)
|
||||
end
|
||||
|
||||
# Extract the auth token from the request
|
||||
def auth_token
|
||||
@auth_token ||= ActionController::HttpAuthentication::Token.token_and_options(request)
|
||||
end
|
||||
|
||||
# Extract a hash with attributes:values from the auth_token
|
||||
def token_auth_hash
|
||||
request.env['devise.token_options'] = auth_token.last
|
||||
{ authentication_keys.first => auth_token.first }
|
||||
end
|
||||
|
||||
# Try both scoped and non scoped keys
|
||||
def params_auth_hash
|
||||
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
|
||||
params[scope]
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module Devise
|
||||
VERSION = "2.2.3".freeze
|
||||
VERSION = "2.2.4".freeze
|
||||
end
|
||||
|
|
|
@ -48,10 +48,14 @@ Devise.setup do |config|
|
|||
# enable it only for database (email + password) authentication.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
# Tell if authentication through HTTP Basic Auth is enabled. False by default.
|
||||
# Tell if authentication through HTTP Auth is enabled. False by default.
|
||||
# It can be set to an array that will enable http authentication only for the
|
||||
# given strategies, for example, `config.http_authenticatable = [:token]` will
|
||||
# enable it only for token authentication.
|
||||
# enable it only for token authentication. The supported strategies are:
|
||||
# :database = Support basic authentication with authentication key + password
|
||||
# :token = Support basic authentication with token authentication key
|
||||
# :token_options = Support token authentication with options as defined in
|
||||
# http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
|
||||
# config.http_authenticatable = false
|
||||
|
||||
# If http headers should be returned for AJAX requests. True by default.
|
||||
|
|
32
test/controllers/passwords_controller_test.rb
Normal file
32
test/controllers/passwords_controller_test.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
require 'test_helper'
|
||||
|
||||
class PasswordsControllerTest < ActionController::TestCase
|
||||
tests Devise::PasswordsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
def setup
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
@user = create_user
|
||||
@user.send_reset_password_instructions
|
||||
end
|
||||
|
||||
def put_update_with_params
|
||||
put :update, "user" => {
|
||||
"reset_password_token" => @user.reset_password_token, "password" => "123456", "password_confirmation" => "123456"
|
||||
}
|
||||
end
|
||||
|
||||
test 'redirect to after_sign_in_path_for if after_resetting_password_path_for is not overridden' do
|
||||
put_update_with_params
|
||||
assert_redirected_to "http://test.host/"
|
||||
end
|
||||
|
||||
test 'redirect accordingly if after_resetting_password_path_for is overridden' do
|
||||
custom_path = "http://custom.path/"
|
||||
Devise::PasswordsController.any_instance.stubs(:after_resetting_password_path_for).with(@user).returns(custom_path)
|
||||
|
||||
put_update_with_params
|
||||
assert_redirected_to custom_path
|
||||
end
|
||||
end
|
|
@ -80,9 +80,9 @@ class FailureTest < ActiveSupport::TestCase
|
|||
|
||||
test 'setup a default message' do
|
||||
call_failure
|
||||
assert_match /You are being/, @response.last.body
|
||||
assert_match /redirected/, @response.last.body
|
||||
assert_match /users\/sign_in/, @response.last.body
|
||||
assert_match(/You are being/, @response.last.body)
|
||||
assert_match(/redirected/, @response.last.body)
|
||||
assert_match(/users\/sign_in/, @response.last.body)
|
||||
end
|
||||
|
||||
test 'works for any navigational format' do
|
||||
|
|
|
@ -167,7 +167,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'resent confirmation token with invalid E-Mail in XML format should return invalid response' do
|
||||
user = create_user(:confirm => false)
|
||||
create_user(:confirm => false)
|
||||
post user_confirmation_path(:format => 'xml'), :user => { :email => 'invalid.test@test.com' }
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
|
@ -181,7 +181,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'confirm account with invalid confirmation token in XML format should return invalid response' do
|
||||
user = create_user(:confirm => false)
|
||||
create_user(:confirm => false)
|
||||
get user_confirmation_path(:confirmation_token => 'invalid_confirmation', :format => 'xml')
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
|
@ -275,7 +275,7 @@ class ConfirmationOnChangeTest < ActionDispatch::IntegrationTest
|
|||
|
||||
visit_admin_confirmation_with_token(confirmation_token)
|
||||
assert_have_selector '#error_explanation'
|
||||
assert_contain /Confirmation token(.*)invalid/
|
||||
assert_contain(/Confirmation token(.*)invalid/)
|
||||
|
||||
visit_admin_confirmation_with_token(admin.confirmation_token)
|
||||
assert_contain 'Your account was successfully confirmed.'
|
||||
|
@ -293,7 +293,7 @@ class ConfirmationOnChangeTest < ActionDispatch::IntegrationTest
|
|||
|
||||
visit_admin_confirmation_with_token(admin.confirmation_token)
|
||||
assert_have_selector '#error_explanation'
|
||||
assert_contain /Email.*already.*taken/
|
||||
assert_contain(/Email.*already.*taken/)
|
||||
assert admin.reload.pending_reconfirmation?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -63,7 +63,7 @@ class HttpAuthenticationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'it uses appropriate authentication_keys when configured with hash' do
|
||||
swap Devise, :authentication_keys => { :username => false, :email => false } do
|
||||
swap Devise, :authentication_keys => ActiveSupport::OrderedHash[:username, false, :email, false] do
|
||||
sign_in_as_new_user_with_http("usertest")
|
||||
assert_response :success
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
|
@ -72,7 +72,7 @@ class HttpAuthenticationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'it uses the appropriate key when configured explicitly' do
|
||||
swap Devise, :authentication_keys => { :email => false, :username => false }, :http_auth_key => :username do
|
||||
swap Devise, :authentication_keys => ActiveSupport::OrderedHash[:email, false, :username, false], :http_authentication_key => :username do
|
||||
sign_in_as_new_user_with_http("usertest")
|
||||
assert_response :success
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
|
|
|
@ -90,7 +90,7 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
assert session["devise.facebook_data"]
|
||||
user = sign_in_as_user
|
||||
sign_in_as_user
|
||||
assert !session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'change password with invalid token in XML format should return invalid response' do
|
||||
user = create_user
|
||||
create_user
|
||||
request_forgot_password
|
||||
put user_password_path(:format => 'xml'), :user => {:reset_password_token => 'invalid.token', :password => '987654321', :password_confirmation => '987654321'}
|
||||
assert_response :unprocessable_entity
|
||||
|
|
|
@ -113,7 +113,7 @@ class RegistrationTest < ActionDispatch::IntegrationTest
|
|||
# https://github.com/mongoid/mongoid/issues/756
|
||||
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
|
||||
|
||||
user = create_user
|
||||
create_user
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'user@test.com'
|
||||
|
@ -287,7 +287,7 @@ class RegistrationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'a user cancel his account in XML format should return valid response' do
|
||||
user = sign_in_as_user
|
||||
sign_in_as_user
|
||||
delete user_registration_path(:format => 'xml')
|
||||
assert_response :success
|
||||
assert_equal User.count, 0
|
||||
|
|
|
@ -26,7 +26,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'do not remember the user if he has not checked remember me option' do
|
||||
user = sign_in_as_user
|
||||
sign_in_as_user
|
||||
assert_nil request.cookies["remember_user_cookie"]
|
||||
end
|
||||
|
||||
|
@ -43,7 +43,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'generate remember token after sign in' do
|
||||
user = sign_in_as_user :remember_me => true
|
||||
sign_in_as_user :remember_me => true
|
||||
assert request.cookies["remember_user_token"]
|
||||
end
|
||||
|
||||
|
@ -84,7 +84,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'remember the user before sign up and redirect him to his home' do
|
||||
user = create_user_and_remember
|
||||
create_user_and_remember
|
||||
get new_user_registration_path
|
||||
assert warden.authenticated?(:user)
|
||||
assert_redirected_to root_path
|
||||
|
@ -92,7 +92,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
|
||||
test 'cookies are destroyed on unverified requests' do
|
||||
swap ApplicationController, :allow_forgery_protection => true do
|
||||
user = create_user_and_remember
|
||||
create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
post root_path, :authenticity_token => 'INVALID'
|
||||
|
@ -117,7 +117,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'do not remember other scopes' do
|
||||
user = create_user_and_remember
|
||||
create_user_and_remember
|
||||
get root_path
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
|
@ -125,14 +125,14 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'do not remember with invalid token' do
|
||||
user = create_user_and_remember('add')
|
||||
create_user_and_remember('add')
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
assert_redirected_to new_user_session_path
|
||||
end
|
||||
|
||||
test 'do not remember with expired token' do
|
||||
user = create_user_and_remember
|
||||
create_user_and_remember
|
||||
swap Devise, :remember_for => 0 do
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
@ -141,7 +141,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test 'do not remember the user anymore after forget' do
|
||||
user = create_user_and_remember
|
||||
create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
|
||||
|
|
|
@ -129,6 +129,46 @@ class TokenAuthenticationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and value through http header' do
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
sign_in_as_new_user_with_token(:token_auth => true)
|
||||
|
||||
assert_response :success
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
assert_equal request.env['devise.token_options'], {}
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and value through http header, with options' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :http_authenticatable => [:token_options] do
|
||||
signature = "**TESTSIGNATURE**"
|
||||
sign_in_as_new_user_with_token(:token_auth => true, :token_options => {:signature => signature, :nonce => 'def'})
|
||||
|
||||
assert_response :success
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
assert_equal request.env['devise.token_options'][:signature], signature
|
||||
assert_equal request.env['devise.token_options'][:nonce], 'def'
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and value through http header without allowing token authorization setting is denied' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :http_authenticatable => false do
|
||||
sign_in_as_new_user_with_token(:token_auth => true)
|
||||
|
||||
assert_response :unauthorized
|
||||
assert_nil warden.user(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'does not authenticate with improper authentication token value in header' do
|
||||
sign_in_as_new_user_with_token(:token_auth => true, :auth_token => '*** INVALID TOKEN ***')
|
||||
|
||||
assert_response :unauthorized
|
||||
assert_nil warden.user(:user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_as_new_user_with_token(options = {})
|
||||
|
@ -140,6 +180,10 @@ class TokenAuthenticationTest < ActionDispatch::IntegrationTest
|
|||
if options[:http_auth]
|
||||
header = "Basic #{Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
|
||||
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
|
||||
elsif options[:token_auth]
|
||||
token_options = options[:token_options] || {}
|
||||
header = ActionController::HttpAuthentication::Token.encode_credentials(options[:auth_token], token_options)
|
||||
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
|
||||
else
|
||||
visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
|
||||
end
|
||||
|
|
|
@ -52,6 +52,18 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
|||
assert_equal( { "login" => "foo@bar.com", "bool1" => "true", "bool2" => "false", "fixnum" => "123", "will_be_converted" => "1..10" }, conditions)
|
||||
end
|
||||
|
||||
test 'param filter should filter case_insensitive_keys as insensitive' do
|
||||
conditions = {'insensitive' => 'insensitive_VAL', 'sensitive' => 'sensitive_VAL'}
|
||||
conditions = Devise::ParamFilter.new(['insensitive'], []).filter(conditions)
|
||||
assert_equal( {'insensitive' => 'insensitive_val', 'sensitive' => 'sensitive_VAL'}, conditions )
|
||||
end
|
||||
|
||||
test 'param filter should filter strip_whitespace_keys stripping whitespaces' do
|
||||
conditions = {'strip_whitespace' => ' strip_whitespace_val ', 'do_not_strip_whitespace' => ' do_not_strip_whitespace_val '}
|
||||
conditions = Devise::ParamFilter.new([], ['strip_whitespace']).filter(conditions)
|
||||
assert_equal( {'strip_whitespace' => 'strip_whitespace_val', 'do_not_strip_whitespace' => ' do_not_strip_whitespace_val '}, conditions )
|
||||
end
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
user = new_user
|
||||
assert user.respond_to?(:password)
|
||||
|
@ -170,6 +182,26 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
|||
assert user.valid_password?('12345678')
|
||||
end
|
||||
|
||||
test 'should destroy user if current password is valid' do
|
||||
user = create_user
|
||||
assert user.destroy_with_password('12345678')
|
||||
assert !user.persisted?
|
||||
end
|
||||
|
||||
test 'should not destroy user with invalid password' do
|
||||
user = create_user
|
||||
assert_not user.destroy_with_password('other')
|
||||
assert user.persisted?
|
||||
assert_match "is invalid", user.errors[:current_password].join
|
||||
end
|
||||
|
||||
test 'should not destroy user with blank password' do
|
||||
user = create_user
|
||||
assert_not user.destroy_with_password(nil)
|
||||
assert user.persisted?
|
||||
assert_match "can't be blank", user.errors[:current_password].join
|
||||
end
|
||||
|
||||
test 'downcase_keys with validation' do
|
||||
user = User.create(:email => "HEllO@example.com", :password => "123456")
|
||||
user = User.create(:email => "HEllO@example.com", :password => "123456")
|
||||
|
|
|
@ -59,7 +59,7 @@ class LockableTest < ActiveSupport::TestCase
|
|||
assert_not user.active_for_authentication?
|
||||
end
|
||||
|
||||
test "should unlock a user by cleaning locked_at, falied_attempts and unlock_token" do
|
||||
test "should unlock a user by cleaning locked_at, failed_attempts and unlock_token" do
|
||||
user = create_user
|
||||
user.lock_access!
|
||||
assert_not_nil user.reload.locked_at
|
||||
|
|
|
@ -115,7 +115,7 @@ class RememberableTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
test 'remember should not be expired if it was created whitin the limit time' do
|
||||
test 'remember should not be expired if it was created within the limit time' do
|
||||
swap Devise, :remember_for => 30.days do
|
||||
resource = create_resource
|
||||
resource.remember_me!
|
||||
|
@ -167,7 +167,7 @@ class RememberableTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
test 'should have the required_fiels array' do
|
||||
test 'should have the required_fields array' do
|
||||
assert_same_content Devise::Models::Rememberable.required_fields(User), [
|
||||
:remember_created_at
|
||||
]
|
||||
|
|
|
@ -6,18 +6,18 @@ class SerializableTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test 'should not include unsafe keys on XML' do
|
||||
assert_match /email/, @user.to_xml
|
||||
assert_no_match /confirmation-token/, @user.to_xml
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
|
|
@ -64,7 +64,7 @@ class ValidatableTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
test 'should require password when updating/reseting password' do
|
||||
test 'should require password when updating/resetting password' do
|
||||
user = create_user
|
||||
|
||||
user.password = ''
|
||||
|
@ -74,7 +74,7 @@ class ValidatableTest < ActiveSupport::TestCase
|
|||
assert_equal 'can\'t be blank', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should require confirmation when updating/reseting password' do
|
||||
test 'should require confirmation when updating/resetting password' do
|
||||
user = create_user
|
||||
user.password_confirmation = 'another_password'
|
||||
assert user.invalid?
|
||||
|
@ -108,7 +108,7 @@ class ValidatableTest < ActiveSupport::TestCase
|
|||
assert_not (user.errors[:password].join =~ /is too long/)
|
||||
end
|
||||
|
||||
test 'should complain about length even if possword is not required' do
|
||||
test 'should complain about length even if password is not required' do
|
||||
user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129)
|
||||
user.stubs(:password_required?).returns(false)
|
||||
assert user.invalid?
|
||||
|
|
Loading…
Reference in a new issue