mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dba8f91f99 | ||
|
|
8e70e71143 | ||
|
|
f43a7c4f24 | ||
|
|
4e56d92ed8 | ||
|
|
5645d733ba | ||
|
|
42b07f1f47 | ||
|
|
e75354b3b0 | ||
|
|
80122856c4 | ||
|
|
308238ab42 | ||
|
|
e937cf78cf | ||
|
|
2ae2fdc9f8 | ||
|
|
3184834d72 | ||
|
|
8ef5534d92 | ||
|
|
41bb96be5d | ||
|
|
b37055fa47 | ||
|
|
515b727f52 | ||
|
|
77d6d1e8c2 | ||
|
|
04b614ce10 | ||
|
|
62e11ddbe4 | ||
|
|
8e3ab5921f | ||
|
|
1d87997647 | ||
|
|
b58e0ef991 | ||
|
|
db959da247 | ||
|
|
6199252011 | ||
|
|
40c0a7b50b | ||
|
|
422bc4aaa6 | ||
|
|
225c89fbf1 | ||
|
|
76281ff15c | ||
|
|
8b54ff699f | ||
|
|
7d160650b8 | ||
|
|
803e46cda7 | ||
|
|
004fe2ad12 | ||
|
|
09baf2091e | ||
|
|
135a94b4f7 | ||
|
|
a41d185768 | ||
|
|
c3432e57b1 | ||
|
|
a8d88d193e | ||
|
|
471e4d6e72 | ||
|
|
14fec4cfb3 | ||
|
|
4bcd1c6fcd | ||
|
|
84e1a89c44 | ||
|
|
e0162df465 | ||
|
|
7631456047 | ||
|
|
2bc51ab2bd | ||
|
|
d23ecef831 | ||
|
|
c0017ce76d | ||
|
|
30f9da9d71 | ||
|
|
e242ca0937 | ||
|
|
17596b0dc6 | ||
|
|
8e87a2d80d | ||
|
|
4964f53a42 | ||
|
|
6250fa8529 | ||
|
|
944e1c0378 | ||
|
|
4f446241a4 | ||
|
|
97659a1193 | ||
|
|
0bcf71f8df | ||
|
|
ab3bb9cf4d | ||
|
|
69126a31db | ||
|
|
03e3803cff | ||
|
|
58f8c7c613 | ||
|
|
acd1c76c3b | ||
|
|
4c8cc5e3f3 | ||
|
|
72bb33f962 | ||
|
|
2e61e52520 | ||
|
|
75490d0375 | ||
|
|
0fbe4cb6b9 | ||
|
|
d2b3f49384 | ||
|
|
136992b8df | ||
|
|
a130f848f2 | ||
|
|
e10bc9e3c0 | ||
|
|
d56741ca4f | ||
|
|
92c9ed2d6c | ||
|
|
50a5ad54ce | ||
|
|
9dcb44ba61 | ||
|
|
8bdc4b544f | ||
|
|
e763f843c4 | ||
|
|
b5732e31c6 | ||
|
|
ea24ffdd51 | ||
|
|
56f7fbf2d1 | ||
|
|
89b53ea39c | ||
|
|
9cc69277bc | ||
|
|
7e79ed6d4e | ||
|
|
b5190d8df2 | ||
|
|
b03c93c4fe | ||
|
|
8e12ddf7ed | ||
|
|
4fd866d113 | ||
|
|
a59410a254 | ||
|
|
b1a27ad633 | ||
|
|
4a3ad7f348 | ||
|
|
89e4ab8a45 | ||
|
|
fd8e34650e | ||
|
|
e26c8ce499 | ||
|
|
64cf8a4534 | ||
|
|
ae976f60ca | ||
|
|
f152860bc5 | ||
|
|
40153b7422 | ||
|
|
fdfe6a8340 | ||
|
|
79c100008a | ||
|
|
f132c7891b | ||
|
|
bdad984ace | ||
|
|
a229627a54 | ||
|
|
0b598cf132 | ||
|
|
0e657eece1 | ||
|
|
b6cf1df659 | ||
|
|
29afe2d21c | ||
|
|
a722c6236c | ||
|
|
14aedc416a | ||
|
|
9fe0cb4954 | ||
|
|
2a5669967f | ||
|
|
13376d22de | ||
|
|
6b21531916 | ||
|
|
4a4dcb30ef | ||
|
|
2cfa58b433 | ||
|
|
c6dd846718 | ||
|
|
7a2d76d002 | ||
|
|
e5a8febe3b | ||
|
|
60809719b8 | ||
|
|
ee6a8ab93a | ||
|
|
c3d92095f8 |
@@ -1,7 +1,7 @@
|
||||
script: "rake test"
|
||||
script: "bundle exec rake test"
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- ree
|
||||
- rbx
|
||||
- jruby
|
||||
- jruby
|
||||
- rubinius
|
||||
@@ -1,3 +1,45 @@
|
||||
== 1.4.0
|
||||
|
||||
* enhancements
|
||||
* Added authenticated and unauthenticated to the router to route the used based on his status (by github.com/sj26)
|
||||
* Improve e-mail regexp (by github.com/rodrigoflores)
|
||||
* Add strip_whitespace_keys and default to e-mail (by github.com/swrobel)
|
||||
* Do not run format and uniqueness validations on e-mail if it hasn't changed (by github.com/Thibaut)
|
||||
* Added update_without_password to update models but not allowing the password to change (by github.com/fschwahn)
|
||||
* Added config.paranoid, check the generator for more information (by github.com/rodrigoflores)
|
||||
|
||||
* bug fix
|
||||
* password_required? should not affect length validation
|
||||
* User cannot access sign up and similar pages if he is already signed in through a cookie or token
|
||||
* Do not convert booleans to strings on finders (by github.com/xavier)
|
||||
* Run validations even if current_password fails (by github.com/crx)
|
||||
* Devise now honors routes constraints (by github.com/macmartine)
|
||||
* Do not return the user resource when requesting instructions (by github.com/rodrigoflores)
|
||||
|
||||
== 1.3.4
|
||||
|
||||
* bug fix
|
||||
* Do not add formats if html or "*/*"
|
||||
|
||||
== 1.3.3
|
||||
|
||||
* bug fix
|
||||
* Explicitly mark the token as expired if so
|
||||
|
||||
== 1.3.2
|
||||
|
||||
* bug fix
|
||||
* Fix another regression related to reset_password_sent_at (by github.com/alexdreher)
|
||||
|
||||
== 1.3.1
|
||||
|
||||
* enhancements
|
||||
* Improve failure_app responses (by github.com/indirect)
|
||||
* sessions/new and registrations/new also respond to xml and json now
|
||||
|
||||
* bug fix
|
||||
* Fix a regression that occurred if reset_password_sent_at is not present (by github.com/stevehodgkiss)
|
||||
|
||||
== 1.3.0
|
||||
|
||||
* enhancements
|
||||
|
||||
23
Gemfile
23
Gemfile
@@ -2,7 +2,7 @@ source "http://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.0.4"
|
||||
gem "rails", "~> 3.0.7"
|
||||
gem "oa-oauth", '~> 0.2.0', :require => "omniauth/oauth"
|
||||
gem "oa-openid", '~> 0.2.0', :require => "omniauth/openid"
|
||||
|
||||
@@ -15,15 +15,18 @@ platforms :jruby do
|
||||
gem 'activerecord-jdbcsqlite3-adapter'
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
platforms :mri_18 do
|
||||
group :test do
|
||||
gem "sqlite3-ruby"
|
||||
gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9'
|
||||
end
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "1.1.2"
|
||||
gem "mongoid", "2.0.0.beta.20"
|
||||
gem "bson_ext", "1.2.1"
|
||||
gem "ruby-debug", ">= 0.10.3"
|
||||
end
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3-ruby"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
gem "mongoid", "2.0.1"
|
||||
gem "bson_ext", "~> 1.3.0"
|
||||
end
|
||||
end
|
||||
|
||||
91
Gemfile.lock
91
Gemfile.lock
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (1.3.0.dev)
|
||||
devise (1.4.0.dev)
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
orm_adapter (~> 0.0.3)
|
||||
warden (~> 1.0.3)
|
||||
@@ -10,41 +10,42 @@ GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
abstract (1.0.0)
|
||||
actionmailer (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
actionmailer (3.0.7)
|
||||
actionpack (= 3.0.7)
|
||||
mail (~> 2.2.15)
|
||||
actionpack (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
actionpack (3.0.7)
|
||||
activemodel (= 3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
builder (~> 2.1.2)
|
||||
erubis (~> 2.6.6)
|
||||
i18n (~> 0.4)
|
||||
i18n (~> 0.5.0)
|
||||
rack (~> 1.2.1)
|
||||
rack-mount (~> 0.6.13)
|
||||
rack-mount (~> 0.6.14)
|
||||
rack-test (~> 0.5.7)
|
||||
tzinfo (~> 0.3.23)
|
||||
activemodel (3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
activemodel (3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
builder (~> 2.1.2)
|
||||
i18n (~> 0.4)
|
||||
activerecord (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
i18n (~> 0.5.0)
|
||||
activerecord (3.0.7)
|
||||
activemodel (= 3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
arel (~> 2.0.2)
|
||||
tzinfo (~> 0.3.23)
|
||||
activerecord-jdbc-adapter (1.1.1)
|
||||
activerecord-jdbcsqlite3-adapter (1.1.1)
|
||||
activerecord-jdbc-adapter (= 1.1.1)
|
||||
jdbc-sqlite3 (~> 3.6.0)
|
||||
activeresource (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
activesupport (3.0.4)
|
||||
activeresource (3.0.7)
|
||||
activemodel (= 3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
activesupport (3.0.7)
|
||||
addressable (2.2.4)
|
||||
arel (2.0.8)
|
||||
arel (2.0.9)
|
||||
bcrypt-ruby (2.1.4)
|
||||
bson (1.2.1)
|
||||
bson_ext (1.2.1)
|
||||
bcrypt-ruby (2.1.4-java)
|
||||
bson (1.3.0)
|
||||
bson_ext (1.3.0)
|
||||
builder (2.1.2)
|
||||
columnize (0.3.2)
|
||||
erubis (2.6.6)
|
||||
@@ -56,24 +57,24 @@ GEM
|
||||
i18n (0.5.0)
|
||||
jdbc-sqlite3 (3.6.14.2.056-java)
|
||||
linecache (0.43)
|
||||
mail (2.2.15)
|
||||
mail (2.2.19)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.16)
|
||||
mocha (0.9.12)
|
||||
mongo (1.1.2)
|
||||
bson (>= 1.1.1)
|
||||
mongoid (2.0.0.beta.20)
|
||||
mongo (1.3.0)
|
||||
bson (>= 1.3.0)
|
||||
mongoid (2.0.1)
|
||||
activemodel (~> 3.0)
|
||||
mongo (~> 1.1)
|
||||
mongo (~> 1.3)
|
||||
tzinfo (~> 0.3.22)
|
||||
will_paginate (~> 3.0.pre)
|
||||
multi_json (0.0.5)
|
||||
multipart-post (1.1.0)
|
||||
nokogiri (1.4.4)
|
||||
nokogiri (1.4.4-java)
|
||||
nokogiri (1.4.3.1)
|
||||
nokogiri (1.4.3.1-java)
|
||||
weakling (>= 0.0.3)
|
||||
oa-core (0.2.0)
|
||||
rack (~> 1.1)
|
||||
@@ -93,25 +94,25 @@ GEM
|
||||
multi_json (~> 0.0.4)
|
||||
orm_adapter (0.0.4)
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.1)
|
||||
rack-mount (0.6.13)
|
||||
rack (1.2.2)
|
||||
rack-mount (0.6.14)
|
||||
rack (>= 1.0.0)
|
||||
rack-openid (1.2.0)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-test (0.5.7)
|
||||
rack (>= 1.0)
|
||||
rails (3.0.4)
|
||||
actionmailer (= 3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activerecord (= 3.0.4)
|
||||
activeresource (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
rails (3.0.7)
|
||||
actionmailer (= 3.0.7)
|
||||
actionpack (= 3.0.7)
|
||||
activerecord (= 3.0.7)
|
||||
activeresource (= 3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.0.4)
|
||||
railties (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
railties (= 3.0.7)
|
||||
railties (3.0.7)
|
||||
actionpack (= 3.0.7)
|
||||
activesupport (= 3.0.7)
|
||||
rake (>= 0.8.7)
|
||||
thor (~> 0.14.4)
|
||||
rake (0.8.7)
|
||||
@@ -129,7 +130,7 @@ GEM
|
||||
thor (0.14.6)
|
||||
treetop (1.4.9)
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.24)
|
||||
tzinfo (0.3.27)
|
||||
warden (1.0.3)
|
||||
rack (>= 1.0.0)
|
||||
weakling (0.0.4-java)
|
||||
@@ -145,14 +146,14 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bson_ext (= 1.2.1)
|
||||
bson_ext (~> 1.3.0)
|
||||
devise!
|
||||
mocha
|
||||
mongo (= 1.1.2)
|
||||
mongoid (= 2.0.0.beta.20)
|
||||
mongo (~> 1.3.0)
|
||||
mongoid (= 2.0.1)
|
||||
oa-oauth (~> 0.2.0)
|
||||
oa-openid (~> 0.2.0)
|
||||
rails (~> 3.0.4)
|
||||
rails (~> 3.0.7)
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3-ruby
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -86,7 +86,7 @@ The generator will install an initializer which describes ALL Devise's configura
|
||||
|
||||
rails generate devise MODEL
|
||||
|
||||
Replace MODEL by the class name you want to add devise, like User, Admin, etc. This will create a model (if one does not exist) and configure it with default Devise modules. The generator will also create a migration file (if your ORM support them) and configure your routes. Continue reading this file to understand exactly what the generator produces and how to use it.
|
||||
Replace MODEL by the class name used for the applications users, it's frequently 'User' but could also be 'Admin'. This will create a model (if one does not exist) and configure it with default Devise modules. Next, you'll usually run db:migrate as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file, continue reading this file to understand exactly what the generator produces and how to use it.
|
||||
|
||||
Support for Rails 2.3.x can be found by installing Devise 1.0.x from the v1.0 branch.
|
||||
|
||||
@@ -259,7 +259,7 @@ Feel free to choose the one you prefer!
|
||||
|
||||
=== I18n
|
||||
|
||||
Devise uses flash messages with I18n with the flash keys :success and :failure. To customize your app, you can set up your locale file:
|
||||
Devise uses flash messages with I18n with the flash keys :notice and :alert. To customize your app, you can set up your locale file:
|
||||
|
||||
en:
|
||||
devise:
|
||||
|
||||
2
Rakefile
2
Rakefile
@@ -4,7 +4,7 @@ require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
|
||||
desc 'Default: run tests for all ORMs.'
|
||||
task :default => :pre_commit
|
||||
task :default => :test
|
||||
|
||||
desc 'Run Devise tests for all ORMs.'
|
||||
task :pre_commit do
|
||||
|
||||
@@ -11,9 +11,9 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => after_resending_confirmation_instructions_path_for(resource_name)
|
||||
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
|
||||
@@ -12,9 +12,9 @@ class Devise::PasswordsController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
@@ -39,4 +39,12 @@ class Devise::PasswordsController < ApplicationController
|
||||
respond_with_navigational(resource){ render_with_scope :edit }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The path used after sending reset password instructions
|
||||
def after_sending_reset_password_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,8 +5,8 @@ class Devise::RegistrationsController < ApplicationController
|
||||
|
||||
# GET /resource/sign_up
|
||||
def new
|
||||
build_resource({})
|
||||
render_with_scope :new
|
||||
resource = build_resource({})
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
|
||||
# POST /resource
|
||||
@@ -35,7 +35,11 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
|
||||
# PUT /resource
|
||||
# We need to use a copy of the resource because we don't want to change
|
||||
# the current user in place.
|
||||
def update
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
|
||||
if resource.update_with_password(params[resource_name])
|
||||
set_flash_message :notice, :updated if is_navigational_format?
|
||||
sign_in resource_name, resource, :bypass => true
|
||||
@@ -102,11 +106,9 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# Authenticates the current scope and gets a copy of the current resource.
|
||||
# We need to use a copy because we don't want actions like update changing
|
||||
# the current user in place.
|
||||
# Authenticates the current scope and gets the current resource from the session.
|
||||
def authenticate_scope!
|
||||
send(:"authenticate_#{resource_name}!", true)
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
self.resource = send(:"current_#{resource_name}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,24 +4,14 @@ class Devise::SessionsController < ApplicationController
|
||||
|
||||
# GET /resource/sign_in
|
||||
def new
|
||||
clean_up_passwords(build_resource)
|
||||
render_with_scope :new
|
||||
resource = build_resource
|
||||
clean_up_passwords(resource)
|
||||
respond_with_navigational(resource, stub_options(resource)){ render_with_scope :new }
|
||||
end
|
||||
|
||||
# POST /resource/sign_in
|
||||
def create
|
||||
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
|
||||
|
||||
# In the running app, the previous line would actually cause this method to
|
||||
# exit by throwing `:warden` if the authentication failed. Unfortunately,
|
||||
# this doesn't happen in the Rails test environment if you have included the
|
||||
# Devise::TestHelpers (see `Devise::TestHelpers::TestWarden#authenticate!`),
|
||||
# which makes it difficult to unit test extensions to this controller. Since
|
||||
# the resource is nil if authentication fails, just short-circuit the method
|
||||
# in that case. This should not affect the running app.
|
||||
|
||||
return if resource.nil?
|
||||
|
||||
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
@@ -44,4 +34,12 @@ class Devise::SessionsController < ApplicationController
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def stub_options(resource)
|
||||
array = resource_class.authentication_keys.dup
|
||||
array << :password if resource.respond_to?(:password)
|
||||
{ :methods => array, :only => [:password] }
|
||||
end
|
||||
end
|
||||
@@ -12,9 +12,9 @@ class Devise::UnlocksController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message :notice, :send_instructions if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
respond_with({}, :location => new_session_path(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
en:
|
||||
errors:
|
||||
messages:
|
||||
expired: "has expired, please request a new one"
|
||||
not_found: "not found"
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
not_locked: "was not locked"
|
||||
@@ -26,8 +27,10 @@ en:
|
||||
passwords:
|
||||
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
updated: 'Your password was changed successfully. You are now signed in.'
|
||||
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
||||
registrations:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
@@ -37,6 +40,7 @@ en:
|
||||
unlocks:
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
unlocked: 'Your account was successfully unlocked. You are now signed in.'
|
||||
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
||||
omniauth_callbacks:
|
||||
success: 'Successfully authorized from %{kind} account.'
|
||||
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
||||
|
||||
@@ -3,6 +3,7 @@ require 'active_support/core_ext/numeric/time'
|
||||
require 'active_support/dependencies'
|
||||
require 'orm_adapter'
|
||||
require 'set'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
@@ -10,12 +11,14 @@ module Devise
|
||||
autoload :PathChecker, 'devise/path_checker'
|
||||
autoload :Schema, 'devise/schema'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
autoload :Email, 'devise/email'
|
||||
|
||||
module Controllers
|
||||
autoload :Helpers, 'devise/controllers/helpers'
|
||||
autoload :InternalHelpers, 'devise/controllers/internal_helpers'
|
||||
autoload :Rememberable, 'devise/controllers/rememberable'
|
||||
autoload :ScopedViews, 'devise/controllers/scoped_views'
|
||||
autoload :SharedHelpers, 'devise/controllers/shared_helpers'
|
||||
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
||||
end
|
||||
|
||||
@@ -41,6 +44,9 @@ module Devise
|
||||
STRATEGIES = ActiveSupport::OrderedHash.new
|
||||
URL_HELPERS = ActiveSupport::OrderedHash.new
|
||||
|
||||
# Strategies that do not require user input.
|
||||
NO_INPUT = []
|
||||
|
||||
# True values used to check params
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
@@ -73,6 +79,11 @@ module Devise
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :case_insensitive_keys
|
||||
@@case_insensitive_keys = false
|
||||
|
||||
# Keys that should have whitespace stripped.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :strip_whitespace_keys
|
||||
@@strip_whitespace_keys = false
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -90,9 +101,11 @@ module Devise
|
||||
mattr_accessor :http_authentication_realm
|
||||
@@http_authentication_realm = "Application"
|
||||
|
||||
# Email regex used to validate email formats. Adapted from authlogic.
|
||||
# Email regex used to validate email formats. Based on RFC 822 and
|
||||
# retrieved from Sixarm email validation gem
|
||||
# (https://github.com/SixArm/sixarm_ruby_email_address_validation).
|
||||
mattr_accessor :email_regexp
|
||||
@@email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
@@email_regexp = Devise::Email::EXACT_PATTERN
|
||||
|
||||
# Range validation for password length
|
||||
mattr_accessor :password_length
|
||||
@@ -171,7 +184,7 @@ module Devise
|
||||
mattr_accessor :reset_password_keys
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key
|
||||
# Time interval you can reset your password with a reset password key
|
||||
mattr_accessor :reset_password_within
|
||||
@@reset_password_within = nil
|
||||
|
||||
@@ -224,15 +237,30 @@ module Devise
|
||||
@@warden_config = nil
|
||||
@@warden_config_block = nil
|
||||
|
||||
# When true, enter in paranoid mode to avoid user enumeration.
|
||||
mattr_accessor :paranoid
|
||||
@@paranoid = false
|
||||
|
||||
# Default way to setup Devise. Run rails generate devise_install to create
|
||||
# a fresh initializer with all configuration values.
|
||||
def self.setup
|
||||
yield self
|
||||
end
|
||||
|
||||
class Getter
|
||||
def initialize name
|
||||
@name = name
|
||||
end
|
||||
|
||||
def get
|
||||
ActiveSupport::Dependencies.constantize(@name)
|
||||
end
|
||||
end
|
||||
|
||||
def self.ref(arg)
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
ActiveSupport::Dependencies::Reference.store(arg)
|
||||
ActiveSupport::Dependencies::reference(arg)
|
||||
Getter.new(arg)
|
||||
else
|
||||
ActiveSupport::Dependencies.ref(arg)
|
||||
end
|
||||
@@ -244,11 +272,7 @@ module Devise
|
||||
|
||||
# Get the mailer class from the mailer reference object.
|
||||
def self.mailer
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@@mailer_ref.get "Devise::Mailer"
|
||||
else
|
||||
@@mailer_ref.get
|
||||
end
|
||||
@@mailer_ref.get
|
||||
end
|
||||
|
||||
# Set the mailer reference object to access the mailer.
|
||||
@@ -289,13 +313,17 @@ module Devise
|
||||
options.assert_valid_keys(:strategy, :model, :controller, :route)
|
||||
|
||||
if strategy = options[:strategy]
|
||||
STRATEGIES[module_name] = (strategy == true ? module_name : strategy)
|
||||
strategy = (strategy == true ? module_name : strategy)
|
||||
STRATEGIES[module_name] = strategy
|
||||
end
|
||||
|
||||
if controller = options[:controller]
|
||||
CONTROLLERS[module_name] = (controller == true ? module_name : controller)
|
||||
controller = (controller == true ? module_name : controller)
|
||||
CONTROLLERS[module_name] = controller
|
||||
end
|
||||
|
||||
NO_INPUT << strategy if strategy && controller != :sessions
|
||||
|
||||
if route = options[:route]
|
||||
case route
|
||||
when TrueClass
|
||||
@@ -345,7 +373,8 @@ module Devise
|
||||
#
|
||||
def self.omniauth(provider, *args)
|
||||
@@helpers << Devise::OmniAuth::UrlHelpers
|
||||
@@omniauth_configs[provider] = Devise::OmniAuth::Config.new(provider, args)
|
||||
config = Devise::OmniAuth::Config.new(provider, args)
|
||||
@@omniauth_configs[config.strategy_name.to_sym] = config
|
||||
end
|
||||
|
||||
# Include helpers in the given scope to AC and AV.
|
||||
@@ -384,7 +413,7 @@ module Devise
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
def self.friendly_token
|
||||
ActiveSupport::SecureRandom.base64(15).tr('+/=', 'xyz')
|
||||
SecureRandom.base64(15).tr('+/=', 'xyz')
|
||||
end
|
||||
|
||||
# constant-time comparison algorithm to prevent timing attacks
|
||||
|
||||
@@ -5,7 +5,7 @@ module Devise
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
helper_method :warden, :signed_in?, :devise_controller?, :anybody_signed_in?
|
||||
helper_method :warden, :signed_in?, :devise_controller?
|
||||
end
|
||||
|
||||
# Define authentication filters and accessor helpers based on mappings.
|
||||
|
||||
@@ -6,19 +6,7 @@ module Devise
|
||||
module InternalHelpers #:nodoc:
|
||||
extend ActiveSupport::Concern
|
||||
include Devise::Controllers::ScopedViews
|
||||
|
||||
MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
|
||||
|
||||
# Helper used by FailureApp and Devise controllers to retrieve proper formats.
|
||||
def self.request_format(request)
|
||||
if request.format.respond_to?(:ref)
|
||||
request.format.ref
|
||||
elsif MIME_REFERENCES
|
||||
request.format
|
||||
elsif request.format # Rails < 3.0.4
|
||||
request.format.to_sym
|
||||
end
|
||||
end
|
||||
include Devise::Controllers::SharedHelpers
|
||||
|
||||
included do
|
||||
helper DeviseHelper
|
||||
@@ -65,10 +53,6 @@ module Devise
|
||||
|
||||
protected
|
||||
|
||||
def request_format
|
||||
@request_format ||= Devise::Controllers::InternalHelpers.request_format(request)
|
||||
end
|
||||
|
||||
# Checks whether it's a devise mapped resource or not.
|
||||
def is_devise_resource? #:nodoc:
|
||||
unknown_action! <<-MESSAGE unless devise_mapping
|
||||
@@ -81,11 +65,6 @@ Maybe you forgot to wrap your route inside the scope block? For example:
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
# Check whether it's navigational format, such as :html or :iphone, or not.
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request_format)
|
||||
end
|
||||
|
||||
# Returns real navigational formats which are supported by Rails
|
||||
def navigational_formats
|
||||
@navigational_formats ||= Devise.navigational_formats.select{ |format| Mime::EXTENSION_LOOKUP[format.to_s] }
|
||||
@@ -112,13 +91,27 @@ MESSAGE
|
||||
# Example:
|
||||
# before_filter :require_no_authentication, :only => :new
|
||||
def require_no_authentication
|
||||
if warden.authenticated?(resource_name)
|
||||
no_input = devise_mapping.no_input_strategies
|
||||
args = no_input.dup.push :scope => resource_name
|
||||
if no_input.present? && warden.authenticate?(*args)
|
||||
resource = warden.user(resource_name)
|
||||
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper for use to validate if an resource is errorless. If we are on paranoid mode, we always should assume it is
|
||||
# and return false.
|
||||
def successful_and_sane?(resource)
|
||||
if Devise.paranoid
|
||||
set_flash_message :notice, :send_paranoid_instructions if is_navigational_format?
|
||||
resource.errors.clear
|
||||
false
|
||||
else
|
||||
resource.errors.empty?
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the flash message with :key, using I18n. By default you are able
|
||||
# to setup your messages using specific resource scope, and if no one is
|
||||
# found we look to default scope.
|
||||
|
||||
@@ -29,7 +29,7 @@ module Devise
|
||||
# Forgets the given resource by deleting a cookie
|
||||
def forget_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.forget_me! unless resource.frozen?
|
||||
resource.forget_me!
|
||||
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
||||
end
|
||||
|
||||
|
||||
26
lib/devise/controllers/shared_helpers.rb
Normal file
26
lib/devise/controllers/shared_helpers.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
module Devise
|
||||
module Controllers
|
||||
# Helpers used in both FailureApp and Devise controllers.
|
||||
module SharedHelpers
|
||||
MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
|
||||
|
||||
protected
|
||||
|
||||
# Helper used by FailureApp and Devise controllers to retrieve proper formats.
|
||||
def request_format
|
||||
@request_format ||= if request.format.respond_to?(:ref)
|
||||
request.format.ref
|
||||
elsif MIME_REFERENCES
|
||||
request.format
|
||||
elsif request.format # Rails < 3.0.4
|
||||
request.format.to_sym
|
||||
end
|
||||
end
|
||||
|
||||
# Check whether it's navigational format, such as :html or :iphone, or not.
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request_format)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
23
lib/devise/email.rb
Normal file
23
lib/devise/email.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# This e-mail validation regexes were retrieved from SixArm Ruby
|
||||
# e-mail validation gem (https://github.com/SixArm/sixarm_ruby_email_address_validation)
|
||||
# As said on https://github.com/SixArm/sixarm_ruby_email_address_validation/blob/master/LICENSE.txt,
|
||||
# we added it using Ruby license terms.
|
||||
|
||||
module Devise
|
||||
module Email
|
||||
QTEXT = Regexp.new '[^\\x0d\\x22\\x5c\\x80-\\xff]', nil, 'n'
|
||||
DTEXT = Regexp.new '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', nil, 'n'
|
||||
ATOM = Regexp.new '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', nil, 'n'
|
||||
QUOTED_PAIR = Regexp.new '\\x5c[\\x00-\\x7f]', nil, 'n'
|
||||
DOMAIN_LITERAL = Regexp.new "\\x5b(?:#{DTEXT}|#{QUOTED_PAIR})*\\x5d", nil, 'n'
|
||||
QUOTED_STRING = Regexp.new "\\x22(?:#{QTEXT}|#{QUOTED_PAIR})*\\x22", nil, 'n'
|
||||
DOMAIN_REF = ATOM
|
||||
SUB_DOMAIN = "(?:#{DOMAIN_REF}|#{DOMAIN_LITERAL})"
|
||||
WORD = "(?:#{ATOM}|#{QUOTED_STRING})"
|
||||
DOMAIN = "#{SUB_DOMAIN}(?:\\x2e#{SUB_DOMAIN})*"
|
||||
LOCAL_PART = "#{WORD}(?:\\x2e#{WORD})*"
|
||||
SPEC = "#{LOCAL_PART}\\x40#{DOMAIN}"
|
||||
PATTERN = Regexp.new "#{SPEC}", nil, 'n'
|
||||
EXACT_PATTERN = Regexp.new "\\A#{SPEC}\\z", nil, 'n'
|
||||
end
|
||||
end
|
||||
@@ -10,6 +10,7 @@ module Devise
|
||||
include ActionController::UrlFor
|
||||
include ActionController::Redirecting
|
||||
include Rails.application.routes.url_helpers
|
||||
include Devise::Controllers::SharedHelpers
|
||||
|
||||
delegate :flash, :to => :request
|
||||
|
||||
@@ -64,13 +65,17 @@ module Devise
|
||||
end
|
||||
|
||||
def redirect_url
|
||||
if request_format == :html
|
||||
if skip_format?
|
||||
send(:"new_#{scope}_session_path")
|
||||
else
|
||||
send(:"new_#{scope}_session_path", :format => request_format)
|
||||
end
|
||||
end
|
||||
|
||||
def skip_format?
|
||||
%w(html */*).include? request_format.to_s
|
||||
end
|
||||
|
||||
# Choose whether we should respond in a http authentication fashion,
|
||||
# including 401 and optional headers.
|
||||
#
|
||||
@@ -83,7 +88,7 @@ module Devise
|
||||
if request.xhr?
|
||||
Devise.http_authenticatable_on_xhr
|
||||
else
|
||||
!(request_format && Devise.navigational_formats.include?(request_format))
|
||||
!(request_format && is_navigational_format?)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,7 +101,13 @@ module Devise
|
||||
def http_auth_body
|
||||
return i18n_message unless request_format
|
||||
method = "to_#{request_format}"
|
||||
{}.respond_to?(method) ? { :error => i18n_message }.send(method) : i18n_message
|
||||
if method == "to_xml"
|
||||
{ :error => i18n_message }.to_xml(:root => "errors")
|
||||
elsif {}.respond_to?(method)
|
||||
{ :error => i18n_message }.send(method)
|
||||
else
|
||||
i18n_message
|
||||
end
|
||||
end
|
||||
|
||||
def recall_app(app)
|
||||
@@ -129,9 +140,5 @@ module Devise
|
||||
def store_location!
|
||||
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
|
||||
end
|
||||
|
||||
def request_format
|
||||
@request_format ||= Devise::Controllers::InternalHelpers.request_format(request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Before logout hook to forget the user in the given scope, if it responds
|
||||
# to forget_me! Also clear remember token to ensure the user won't be
|
||||
# remembered again. Notice that we forget the user unless the record is frozen.
|
||||
# remembered again. Notice that we forget the user unless the record is not persisted.
|
||||
# This avoids forgetting deleted users.
|
||||
Warden::Manager.before_logout do |record, warden, options|
|
||||
if record.respond_to?(:forget_me!)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# and on authentication. Retrieving the user from session (:fetch) does
|
||||
# not trigger it.
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope])
|
||||
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
|
||||
record.update_tracked_fields!(warden.request)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,10 +58,14 @@ module Devise
|
||||
mod = options[:module] || "devise"
|
||||
@controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
|
||||
@controllers.merge!(options[:controllers] || {})
|
||||
@controllers.each { |k,v| @controllers[k] = v.to_s }
|
||||
|
||||
@path_names = Hash.new { |h,k| h[k] = k.to_s }
|
||||
@path_names.merge!(:registration => "")
|
||||
@path_names.merge!(options[:path_names] || {})
|
||||
|
||||
@constraints = Hash.new { |h,k| h[k] = k.to_s }
|
||||
@constraints.merge!(options[:constraints] || {})
|
||||
|
||||
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
|
||||
end
|
||||
@@ -73,17 +77,17 @@ module Devise
|
||||
|
||||
# Gives the class the mapping points to.
|
||||
def to
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@ref.get @class_name
|
||||
else
|
||||
@ref.get
|
||||
end
|
||||
@ref.get
|
||||
end
|
||||
|
||||
def strategies
|
||||
@strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
|
||||
end
|
||||
|
||||
def no_input_strategies
|
||||
self.strategies & Devise::NO_INPUT
|
||||
end
|
||||
|
||||
def routes
|
||||
@routes ||= ROUTES.values_at(*self.modules).compact.uniq
|
||||
end
|
||||
@@ -95,7 +99,11 @@ module Devise
|
||||
def fullpath
|
||||
"/#{@path_prefix}/#{@path}".squeeze("/")
|
||||
end
|
||||
|
||||
|
||||
def constraints
|
||||
@constraints
|
||||
end
|
||||
|
||||
# Create magic predicates for verifying what module is activated by this map.
|
||||
# Example:
|
||||
#
|
||||
|
||||
@@ -76,8 +76,17 @@ module Devise
|
||||
def authenticatable_salt
|
||||
end
|
||||
|
||||
def serializable_hash(options={})
|
||||
if self.class.respond_to?(:accessible_attributes)
|
||||
options = { :only => self.class.accessible_attributes.to_a }.merge(options || {})
|
||||
super(options)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
||||
|
||||
def params_authenticatable?(strategy)
|
||||
params_authenticatable.is_a?(Array) ?
|
||||
@@ -100,8 +109,9 @@ module Devise
|
||||
# end
|
||||
#
|
||||
def find_for_authentication(conditions)
|
||||
filter_auth_params(conditions)
|
||||
conditions = filter_auth_params(conditions.dup)
|
||||
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
||||
(strip_whitespace_keys || []).each { |k| conditions[k].try(:strip!) }
|
||||
to_adapter.find_first(conditions)
|
||||
end
|
||||
|
||||
@@ -113,14 +123,15 @@ module Devise
|
||||
# Find an initialize a group of attributes based on a list of required attributes.
|
||||
def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
|
||||
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
||||
|
||||
(strip_whitespace_keys || []).each { |k| attributes[k].try(:strip!) }
|
||||
|
||||
attributes = attributes.slice(*required_attributes)
|
||||
attributes.delete_if { |key, value| value.blank? }
|
||||
|
||||
if attributes.size == required_attributes.size
|
||||
record = to_adapter.find_first(filter_auth_params(attributes))
|
||||
end
|
||||
|
||||
|
||||
unless record
|
||||
record = new
|
||||
|
||||
@@ -139,9 +150,14 @@ module Devise
|
||||
# Force keys to be string to avoid injection on mongoid related database.
|
||||
def filter_auth_params(conditions)
|
||||
conditions.each do |k, v|
|
||||
conditions[k] = v.to_s
|
||||
conditions[k] = v.to_s if auth_param_requires_string_conversion?(v)
|
||||
end if conditions.is_a?(Hash)
|
||||
end
|
||||
|
||||
# Determine which values should be transformed to string or passed as-is to the query builder underneath
|
||||
def auth_param_requires_string_conversion?(value)
|
||||
true unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Fixnum)
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def generate_token(column)
|
||||
|
||||
@@ -23,6 +23,7 @@ module Devise
|
||||
attr_reader :password, :current_password
|
||||
attr_accessor :password_confirmation
|
||||
before_validation :downcase_keys
|
||||
before_validation :strip_whitespace
|
||||
end
|
||||
|
||||
# Generates password encryption based on the given value.
|
||||
@@ -41,7 +42,7 @@ module Devise
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
def clean_up_passwords
|
||||
self.password = self.password_confirmation = nil
|
||||
self.password = self.password_confirmation = ""
|
||||
end
|
||||
|
||||
# Update record attributes when :current_password matches, otherwise returns
|
||||
@@ -58,8 +59,9 @@ module Devise
|
||||
result = if valid_password?(current_password)
|
||||
update_attributes(params)
|
||||
else
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
self.attributes = params
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
end
|
||||
|
||||
@@ -67,6 +69,17 @@ module Devise
|
||||
result
|
||||
end
|
||||
|
||||
# Updates record attributes without asking for the current password.
|
||||
# Never allows to change the current password
|
||||
def update_without_password(params={})
|
||||
params.delete(:password)
|
||||
params.delete(:password_confirmation)
|
||||
|
||||
result = update_attributes(params)
|
||||
clean_up_passwords
|
||||
result
|
||||
end
|
||||
|
||||
def after_database_authentication
|
||||
end
|
||||
|
||||
@@ -81,6 +94,10 @@ module Devise
|
||||
def downcase_keys
|
||||
(self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
(self.class.strip_whitespace_keys || []).each { |k| self[k].try(:strip!) }
|
||||
end
|
||||
|
||||
# Digests the password using bcrypt.
|
||||
def password_digest(password)
|
||||
|
||||
@@ -42,6 +42,7 @@ module Devise
|
||||
# Checks if the reset password token sent is within the limit time.
|
||||
# We do this by calculating if the difference between today and the
|
||||
# sending date does not exceed the confirm in time configured.
|
||||
# Returns true if the resource is not responding to reset_password_sent_at at all.
|
||||
# reset_password_within is a model configuration, must always be an integer value.
|
||||
#
|
||||
# Example:
|
||||
@@ -59,8 +60,8 @@ module Devise
|
||||
# reset_password_period_valid? # will always return false
|
||||
#
|
||||
def reset_password_period_valid?
|
||||
respond_to?(:reset_password_sent_at) && reset_password_sent_at &&
|
||||
reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
||||
return true unless respond_to?(:reset_password_sent_at)
|
||||
reset_password_sent_at && reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -73,6 +74,7 @@ module Devise
|
||||
def generate_reset_password_token
|
||||
self.reset_password_token = self.class.reset_password_token
|
||||
self.reset_password_sent_at = Time.now.utc if respond_to?(:reset_password_sent_at=)
|
||||
self.reset_password_token
|
||||
end
|
||||
|
||||
# Resets the reset password token with and save the record without
|
||||
@@ -114,7 +116,7 @@ module Devise
|
||||
if recoverable.reset_password_period_valid?
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
||||
else
|
||||
recoverable.errors.add(:reset_password_token, :invalid)
|
||||
recoverable.errors.add(:reset_password_token, :expired)
|
||||
end
|
||||
end
|
||||
recoverable
|
||||
|
||||
@@ -54,12 +54,14 @@ module Devise
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Removes the remember token only if it exists, and save the record
|
||||
# without validations.
|
||||
# If the record is persisted, remove the remember token (but only if
|
||||
# it exists), and save the record without validations.
|
||||
def forget_me!
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
if persisted?
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
# Remember token should be expired if expiration time not overpass now.
|
||||
|
||||
@@ -23,14 +23,12 @@ module Devise
|
||||
|
||||
base.class_eval do
|
||||
validates_presence_of :email, :if => :email_required?
|
||||
validates_uniqueness_of :email, :case_sensitive => (case_insensitive_keys != false), :allow_blank => true
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true
|
||||
validates_uniqueness_of :email, :case_sensitive => (case_insensitive_keys != false), :allow_blank => true, :if => :email_changed?
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true, :if => :email_changed?
|
||||
|
||||
with_options :if => :password_required? do |v|
|
||||
v.validates_presence_of :password
|
||||
v.validates_confirmation_of :password
|
||||
v.validates_length_of :password, :within => password_length, :allow_blank => true
|
||||
end
|
||||
validates_presence_of :password, :if => :password_required?
|
||||
validates_confirmation_of :password, :if => :password_required?
|
||||
validates_length_of :password, :within => password_length, :allow_blank => true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Devise.with_options :model => true do |d|
|
||||
d.with_options :strategy => true do |s|
|
||||
routes = [nil, :new, :destroy]
|
||||
s.add_module :database_authenticatable, :controller => :sessions, :route => { :session => routes }
|
||||
s.add_module :token_authenticatable, :controller => :sessions, :route => { :session => routes }
|
||||
s.add_module :token_authenticatable
|
||||
s.add_module :rememberable
|
||||
end
|
||||
|
||||
|
||||
@@ -23,10 +23,5 @@ module Devise
|
||||
module OmniAuth
|
||||
autoload :Config, "devise/omniauth/config"
|
||||
autoload :UrlHelpers, "devise/omniauth/url_helpers"
|
||||
|
||||
class << self
|
||||
delegate :short_circuit_authorizers!, :unshort_circuit_authorizers!,
|
||||
:test_mode!, :stub!, :reset_stubs!, :to => "Devise::OmniAuth::TestHelpers"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,12 @@ module Devise
|
||||
@strategy = nil
|
||||
end
|
||||
|
||||
# open_id strategy can have configurable name
|
||||
def strategy_name
|
||||
options = @args.last.is_a?(Hash) && @args.last
|
||||
options && options[:name] ? options[:name] : @provider
|
||||
end
|
||||
|
||||
def strategy_class
|
||||
::OmniAuth::Strategies.const_get("#{::OmniAuth::Utils.camelize(@provider.to_s)}")
|
||||
end
|
||||
|
||||
@@ -129,9 +129,9 @@ module ActionDispatch::Routing
|
||||
# end
|
||||
#
|
||||
# ==== Adding custom actions to override controllers
|
||||
#
|
||||
# You can pass a block to devise_for that will add any routes defined in the block to Devise's
|
||||
# list of known actions. This is important if you add a custom action to a controller that
|
||||
#
|
||||
# You can pass a block to devise_for that will add any routes defined in the block to Devise's
|
||||
# list of known actions. This is important if you add a custom action to a controller that
|
||||
# overrides an out of the box Devise controller.
|
||||
# For example:
|
||||
#
|
||||
@@ -159,6 +159,7 @@ module ActionDispatch::Routing
|
||||
options[:module] ||= @scope[:module] if @scope[:module].present?
|
||||
options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
|
||||
options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
|
||||
options[:constraints] = (@scope[:constraints] || {}).merge(options[:constraints] || {})
|
||||
|
||||
resources.map!(&:to_sym)
|
||||
|
||||
@@ -185,7 +186,7 @@ module ActionDispatch::Routing
|
||||
|
||||
devise_scope mapping.name do
|
||||
yield if block_given?
|
||||
with_devise_exclusive_scope mapping.fullpath, mapping.name do
|
||||
with_devise_exclusive_scope mapping.fullpath, mapping.name, mapping.constraints do
|
||||
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
|
||||
end
|
||||
end
|
||||
@@ -208,6 +209,50 @@ module ActionDispatch::Routing
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is authenticated. You
|
||||
# can optionally specify which scope.
|
||||
#
|
||||
# authenticated :admin do
|
||||
# root :to => 'admin/dashboard#show'
|
||||
# end
|
||||
#
|
||||
# authenticated do
|
||||
# root :to => 'dashboard#show'
|
||||
# end
|
||||
#
|
||||
# root :to => 'landing#show'
|
||||
#
|
||||
def authenticated(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate? :scope => scope
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is *not* authenticated.
|
||||
# You can optionally specify which scope.
|
||||
#
|
||||
# unauthenticated do
|
||||
# as :user do
|
||||
# root :to => 'devise/registrations#new'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# root :to => 'dashboard#show'
|
||||
#
|
||||
def unauthenticated(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
not request.env["warden"].authenticate? :scope => scope
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the devise scope to be used in the controller. If you have custom routes,
|
||||
# you are required to call this method (also aliased as :as) in order to specify
|
||||
# to which controller it is targetted.
|
||||
@@ -286,12 +331,12 @@ module ActionDispatch::Routing
|
||||
@scope[:path] = path
|
||||
end
|
||||
|
||||
def with_devise_exclusive_scope(new_path, new_as) #:nodoc:
|
||||
old_as, old_path, old_module = @scope[:as], @scope[:path], @scope[:module]
|
||||
@scope[:as], @scope[:path], @scope[:module] = new_as, new_path, nil
|
||||
def with_devise_exclusive_scope(new_path, new_as, new_constraints) #:nodoc:
|
||||
old_as, old_path, old_module, old_constraints = @scope[:as], @scope[:path], @scope[:module], @scope[:constraints]
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints] = new_as, new_path, nil, new_constraints
|
||||
yield
|
||||
ensure
|
||||
@scope[:as], @scope[:path], @scope[:module] = old_as, old_path, old_module
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints] = old_as, old_path, old_module, old_constraints
|
||||
end
|
||||
|
||||
def raise_no_devise_method_error!(klass) #:nodoc:
|
||||
|
||||
@@ -13,48 +13,11 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
# This is a Warden::Proxy customized for functional tests. It's meant to
|
||||
# some of Warden::Manager responsibilities, as retrieving configuration
|
||||
# options and calling the FailureApp.
|
||||
class TestWarden < Warden::Proxy #:nodoc:
|
||||
attr_reader :controller
|
||||
|
||||
def initialize(controller)
|
||||
@controller = controller
|
||||
manager = Warden::Manager.new(nil) do |config|
|
||||
config.merge! Devise.warden_config
|
||||
end
|
||||
super(controller.request.env, manager)
|
||||
end
|
||||
|
||||
def authenticate!(*args)
|
||||
catch_with_redirect { super }
|
||||
end
|
||||
|
||||
def user(*args)
|
||||
catch_with_redirect { super }
|
||||
end
|
||||
|
||||
def catch_with_redirect(&block)
|
||||
result = catch(:warden, &block)
|
||||
|
||||
if result.is_a?(Hash) && !custom_failure? && !@controller.send(:performed?)
|
||||
result[:action] ||= :unauthenticated
|
||||
|
||||
env = @controller.request.env
|
||||
env["PATH_INFO"] = "/#{result[:action]}"
|
||||
env["warden.options"] = result
|
||||
Warden::Manager._run_callbacks(:before_failure, env, result)
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
|
||||
nil
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
# Override process to consider warden.
|
||||
def process(*)
|
||||
result = nil
|
||||
_catch_warden { result = super }
|
||||
result
|
||||
end
|
||||
|
||||
# We need to setup the environment variables and the response in the controller.
|
||||
@@ -64,7 +27,12 @@ module Devise
|
||||
|
||||
# Quick access to Warden::Proxy.
|
||||
def warden #:nodoc:
|
||||
@warden ||= (@request.env['warden'] = TestWarden.new(@controller))
|
||||
@warden ||= begin
|
||||
manager = Warden::Manager.new(nil) do |config|
|
||||
config.merge! Devise.warden_config
|
||||
end
|
||||
@request.env['warden'] = Warden::Proxy.new(@request.env, manager)
|
||||
end
|
||||
end
|
||||
|
||||
# sign_in a given resource by storing its keys in the session.
|
||||
@@ -96,5 +64,27 @@ module Devise
|
||||
warden.session_serializer.delete(scope, user)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def _catch_warden(&block)
|
||||
result = catch(:warden, &block)
|
||||
|
||||
if result.is_a?(Hash) && !warden.custom_failure? && !@controller.send(:performed?)
|
||||
result[:action] ||= :unauthenticated
|
||||
|
||||
env = @controller.request.env
|
||||
env["PATH_INFO"] = "/#{result[:action]}"
|
||||
env["warden.options"] = result
|
||||
Warden::Manager._run_callbacks(:before_failure, env, result)
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
|
||||
nil
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "1.3.0".freeze
|
||||
VERSION = "1.4.0".freeze
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'active_support/secure_random'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
module Generators
|
||||
@@ -21,4 +21,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Devise.setup do |config|
|
||||
# ==> Mailer Configuration
|
||||
# Configure the e-mail address which will be shown in DeviseMailer.
|
||||
config.mailer_sender = "please-change-me@config-initializers-devise.com"
|
||||
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
|
||||
|
||||
# Configure the class responsible to send e-mails.
|
||||
# config.mailer = "Devise::Mailer"
|
||||
@@ -35,6 +35,11 @@ Devise.setup do |config|
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Configure which authentication keys should have whitespace stripped.
|
||||
# These keys will have whitespace before and after removed upon creating or
|
||||
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||
config.strip_whitespace_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
@@ -48,13 +53,18 @@ Devise.setup do |config|
|
||||
# The realm used in Http Basic Authentication. "Application" by default.
|
||||
# config.http_authentication_realm = "Application"
|
||||
|
||||
# It will change confirmation, password recovery and other workflows
|
||||
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||
# Does not affect registerable.
|
||||
# config.paranoid = true
|
||||
|
||||
# ==> Configuration for :database_authenticatable
|
||||
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
||||
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||
config.stretches = 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
# config.pepper = <%= SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
|
||||
@@ -39,14 +39,21 @@ class HelpersTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
test 'require no authentication tests current mapping' do
|
||||
@mock_warden.expects(:authenticated?).with(:user).returns(true)
|
||||
@mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
|
||||
@mock_warden.expects(:user).with(:user).returns(User.new)
|
||||
@controller.expects(:redirect_to).with(root_path)
|
||||
@controller.send :require_no_authentication
|
||||
end
|
||||
|
||||
test 'require no authentication skips if no inputs are available' do
|
||||
Devise.mappings[:user].expects(:no_input_strategies).returns([])
|
||||
@mock_warden.expects(:authenticate?).never
|
||||
@controller.expects(:redirect_to).never
|
||||
@controller.send :require_no_authentication
|
||||
end
|
||||
|
||||
test 'require no authentication sets a flash message' do
|
||||
@mock_warden.expects(:authenticated?).with(:user).returns(true)
|
||||
@mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
|
||||
@mock_warden.expects(:user).with(:user).returns(User.new)
|
||||
@controller.expects(:redirect_to).with(root_path)
|
||||
@controller.send :require_no_authentication
|
||||
|
||||
@@ -4,14 +4,13 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
tests Devise::SessionsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
test "#create doesn't raise exception after Warden authentication fails " \
|
||||
+ "when TestHelpers included" do
|
||||
test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
assert_nothing_raised(NoMethodError) do
|
||||
post :create, :user => {
|
||||
:email => "nosuchuser@example.com",
|
||||
:password => "wevdude"
|
||||
}
|
||||
end
|
||||
post :create, :user => {
|
||||
:email => "nosuchuser@example.com",
|
||||
:password => "wevdude"
|
||||
}
|
||||
assert_equal 200, @response.status
|
||||
assert_template "devise/sessions/new"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,6 +39,11 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'return to the default redirect location for wildcard requests' do
|
||||
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'uses the proxy failure message as symbol' do
|
||||
call_failure('warden' => OpenStruct.new(:message => :test))
|
||||
assert_equal 'test', @request.flash[:alert]
|
||||
@@ -84,6 +89,18 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert_equal 401, @response.first
|
||||
end
|
||||
|
||||
test 'return appropriate body for xml' do
|
||||
call_failure('formats' => :xml)
|
||||
result = %(<?xml version="1.0" encoding="UTF-8"?>\n<errors>\n <error>You need to sign in or sign up before continuing.</error>\n</errors>\n)
|
||||
assert_equal result, @response.last.body
|
||||
end
|
||||
|
||||
test 'return appropriate body for json' do
|
||||
call_failure('formats' => :json)
|
||||
result = %({"error":"You need to sign in or sign up before continuing."})
|
||||
assert_equal result, @response.last.body
|
||||
end
|
||||
|
||||
test 'return 401 status for unknown formats' do
|
||||
call_failure 'formats' => []
|
||||
assert_equal 401, @response.first
|
||||
|
||||
@@ -101,6 +101,54 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
|
||||
assert_contain 'Private!'
|
||||
end
|
||||
|
||||
test 'signed in as admin should get admin dashboard' do
|
||||
sign_in_as_admin
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get dashboard_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/admin'
|
||||
assert_contain 'Admin dashboard'
|
||||
end
|
||||
|
||||
test 'signed in as user should get user dashboard' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
|
||||
get dashboard_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/user'
|
||||
assert_contain 'User dashboard'
|
||||
end
|
||||
|
||||
test 'not signed in should get no dashboard' do
|
||||
assert_raises ActionController::RoutingError do
|
||||
get dashboard_path
|
||||
end
|
||||
end
|
||||
|
||||
test 'signed in user should not see join page' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
|
||||
assert_raises ActionController::RoutingError do
|
||||
get join_path
|
||||
end
|
||||
end
|
||||
|
||||
test 'not signed in should see join page' do
|
||||
get join_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/join'
|
||||
assert_contain 'Join'
|
||||
end
|
||||
|
||||
test 'signed in as user should not be able to access admins actions' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -314,8 +362,9 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'render 404 on roles without routes' do
|
||||
get '/admin_area/password/new'
|
||||
assert_equal 404, response.status
|
||||
assert_raise ActionController::RoutingError do
|
||||
get '/admin_area/password/new'
|
||||
end
|
||||
end
|
||||
|
||||
test 'does not intercept Rails 401 responses' do
|
||||
@@ -336,9 +385,24 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'registration in xml format works when recognizing path' do
|
||||
assert_nothing_raised do
|
||||
post user_registration_path(:format => 'xml', :user => {:email => "test@example.com", :password => "invalid"} )
|
||||
test 'sign in stub in xml format' do
|
||||
get new_user_session_path(:format => 'xml')
|
||||
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>\n <email></email>\n <password></password>\n</user>\n", response.body
|
||||
end
|
||||
|
||||
test 'sign in stub in json format' do
|
||||
get new_user_session_path(:format => 'json')
|
||||
assert_match '{"user":{', response.body
|
||||
assert_match '"email":""', response.body
|
||||
assert_match '"password":""', response.body
|
||||
end
|
||||
|
||||
test 'sign in stub in json with non attribute key' do
|
||||
swap Devise, :authentication_keys => [:other_key] do
|
||||
get new_user_session_path(:format => 'json')
|
||||
assert_match '{"user":{', response.body
|
||||
assert_match '"other_key":null', response.body
|
||||
assert_match '"password":""', response.body
|
||||
end
|
||||
end
|
||||
|
||||
@@ -431,7 +495,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides only delete' do
|
||||
sign_in!(:sign_out_via_delete)
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_delete)
|
||||
end
|
||||
|
||||
@@ -443,7 +509,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides only post' do
|
||||
sign_in!(:sign_out_via_post)
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_post)
|
||||
end
|
||||
|
||||
@@ -461,7 +529,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides delete and post' do
|
||||
sign_in!(:sign_out_via_delete_or_post)
|
||||
get destroy_sign_out_via_delete_or_post_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_or_post_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_delete_or_post)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,7 +106,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
user = create_user(:confirm => false)
|
||||
post user_confirmation_path(:format => 'xml'), :user => { :email => user.email }
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
assert_equal response.body, {}.to_xml
|
||||
end
|
||||
|
||||
test 'resent confirmation token with invalid E-Mail in XML format should return invalid response' do
|
||||
@@ -129,4 +129,42 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'request an account confirmation account with JSON, should return an empty JSON' do
|
||||
user = create_user(:confirm => false)
|
||||
|
||||
post user_confirmation_path, :user => { :email => user.email }, :format => :json
|
||||
assert_response :success
|
||||
assert_equal response.body, {}.to_json
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a valid e-mail, should not say that the e-mail is valid" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:confirm => false)
|
||||
visit new_user_session_path
|
||||
|
||||
click_link "Didn't receive confirmation instructions?"
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend confirmation instructions'
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/confirmation"
|
||||
end
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a invalid e-mail, should not say that the e-mail is invalid" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit new_user_session_path
|
||||
|
||||
click_link "Didn't receive confirmation instructions?"
|
||||
fill_in 'email', :with => "idonthavethisemail@gmail.com"
|
||||
click_button 'Resend confirmation instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/confirmation"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,6 +22,28 @@ class DatabaseAuthenticationTest < ActionController::IntegrationTest
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'sign in with email including extra spaces should succeed when email is in the list of strip whitespace keys' do
|
||||
create_user(:email => ' foo@bar.com ')
|
||||
|
||||
sign_in_as_user do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign in with email including extra spaces should fail when email is NOT the list of strip whitespace keys' do
|
||||
swap Devise, :strip_whitespace_keys => [] do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
sign_in_as_user do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'sign in should not authenticate if not using proper authentication keys' do
|
||||
swap Devise, :authentication_keys => [:username] do
|
||||
|
||||
@@ -37,7 +37,7 @@ class LockTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'unlocked pages should not be available if email strategy is disabled' do
|
||||
visit "/admins/sign_in"
|
||||
visit "/admin_area/sign_in"
|
||||
|
||||
assert_raise Webrat::NotFoundError do
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
@@ -47,8 +47,9 @@ class LockTest < ActionController::IntegrationTest
|
||||
visit new_admin_unlock_path
|
||||
end
|
||||
|
||||
visit "/admins/unlock/new"
|
||||
assert_response :not_found
|
||||
assert_raise ActionController::RoutingError do
|
||||
visit "/admin_area/unlock/new"
|
||||
end
|
||||
end
|
||||
|
||||
test 'user with invalid unlock token should not be able to unlock an account' do
|
||||
@@ -112,7 +113,7 @@ class LockTest < ActionController::IntegrationTest
|
||||
|
||||
post user_unlock_path(:format => 'xml'), :user => {:email => user.email}
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
assert_equal response.body, {}.to_xml
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
@@ -140,4 +141,61 @@ class LockTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test "when using json to ask a unlock request, should not return the user" do
|
||||
user = create_user(:locked => true)
|
||||
post user_unlock_path(:format => "json", :user => {:email => user.email})
|
||||
assert_response :success
|
||||
assert_equal response.body, {}.to_json
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that exists it should not say that it exists if it is locked" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:locked => true)
|
||||
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
end
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that exists it should not say that it exists if it is not locked" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:locked => false)
|
||||
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
end
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that does not exists it should not say that it does not exists" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => "arandomemail@hotmail.com"
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -114,9 +114,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
test "generates a proper link when SCRIPT_NAME is set" do
|
||||
header 'SCRIPT_NAME', '/q'
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
|
||||
assert_equal '/q/users/auth/facebook', current_url
|
||||
assert_select "a", :href => "/q/users/auth/facebook"
|
||||
end
|
||||
|
||||
test "handles callback error parameter according to the specification" do
|
||||
|
||||
@@ -17,7 +17,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
click_button 'Send me reset password instructions'
|
||||
end
|
||||
|
||||
def reset_password(options={}, &block)
|
||||
def reset_password(options={}, &block)
|
||||
visit edit_user_password_path(:reset_password_token => options[:reset_password_token]) unless options[:visit] == false
|
||||
assert_response :success
|
||||
|
||||
@@ -29,11 +29,11 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
|
||||
test 'reset password with email of different case should succeed when email is in the list of case insensitive keys' do
|
||||
create_user(:email => 'Foo@Bar.com')
|
||||
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
|
||||
assert_current_url '/users/sign_in'
|
||||
assert_contain 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
end
|
||||
@@ -41,11 +41,11 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
test 'reset password with email of different case should fail when email is NOT the list of case insensitive keys' do
|
||||
swap Devise, :case_insensitive_keys => [] do
|
||||
create_user(:email => 'Foo@Bar.com')
|
||||
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
|
||||
assert_response :success
|
||||
assert_current_url '/users/password'
|
||||
assert_have_selector "input[type=email][value='foo@bar.com']"
|
||||
@@ -53,6 +53,32 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'reset password with email with extra whitespace should succeed when email is in the list of strip whitespace keys' do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_current_url '/users/sign_in'
|
||||
assert_contain 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
end
|
||||
|
||||
test 'reset password with email with extra whitespace should fail when email is NOT the list of strip whitespace keys' do
|
||||
swap Devise, :strip_whitespace_keys => [] do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_current_url '/users/password'
|
||||
assert_have_selector "input[type=email][value=' foo@bar.com ']"
|
||||
assert_contain 'not found'
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticated user should not be able to visit forgot password page' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -161,7 +187,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
create_user
|
||||
post user_password_path(:format => 'xml'), :user => {:email => "user@test.com"}
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
assert_equal response.body, { }.to_xml
|
||||
end
|
||||
|
||||
test 'reset password request with invalid E-Mail in XML format should return valid response' do
|
||||
@@ -194,4 +220,38 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test "when using json requests to ask a confirmable request, should not return the object" do
|
||||
user = create_user(:confirm => false)
|
||||
|
||||
post user_password_path(:format => :json), :user => { :email => user.email }
|
||||
|
||||
assert_response :success
|
||||
assert_equal response.body, "{}"
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with an invalid e-mail, asking to reset a password should display a message that does not indicates that the e-mail does not exists in the database" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit_new_password_path
|
||||
fill_in "email", :with => "arandomemail@test.com"
|
||||
click_button 'Send me reset password instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/password"
|
||||
end
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a valid e-mail, asking to reset password should display a message that does not indicates that the email exists in the database and redirect to the failure route" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user
|
||||
visit_new_password_path
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Send me reset password instructions'
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/password"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,14 +118,14 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
sign_in_as_user
|
||||
get edit_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'user.new@email.com'
|
||||
fill_in 'email', :with => 'user.new@example.com'
|
||||
fill_in 'current password', :with => '123456'
|
||||
click_button 'Update'
|
||||
|
||||
assert_current_url '/'
|
||||
assert_contain 'You updated your account successfully.'
|
||||
|
||||
assert_equal "user.new@email.com", User.first.email
|
||||
assert_equal "user.new@example.com", User.first.email
|
||||
end
|
||||
|
||||
test 'a signed in user should still be able to use the website after changing his password' do
|
||||
@@ -146,13 +146,13 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
sign_in_as_user
|
||||
get edit_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'user.new@email.com'
|
||||
fill_in 'email', :with => 'user.new@example.com'
|
||||
fill_in 'current password', :with => 'invalid'
|
||||
click_button 'Update'
|
||||
|
||||
assert_template 'registrations/edit'
|
||||
assert_contain 'user@test.com'
|
||||
assert_have_selector 'form input[value="user.new@email.com"]'
|
||||
assert_have_selector 'form input[value="user.new@example.com"]'
|
||||
|
||||
assert_equal "user@test.com", User.first.email
|
||||
end
|
||||
@@ -207,6 +207,20 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
assert_redirected_to new_user_registration_path
|
||||
end
|
||||
|
||||
test 'a user with XML sign up stub' do
|
||||
get new_user_registration_path(:format => 'xml')
|
||||
assert_response :success
|
||||
assert_match %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>), response.body
|
||||
assert_no_match(/<confirmation_token>/, response.body) if DEVISE_ORM == :active_record
|
||||
end
|
||||
|
||||
test 'a user with JSON sign up stub' do
|
||||
get new_user_registration_path(:format => 'json')
|
||||
assert_response :success
|
||||
assert_match %({"user":), response.body
|
||||
assert_no_match(/"confirmation_token"/, response.body) if DEVISE_ORM == :active_record
|
||||
end
|
||||
|
||||
test 'an admin sign up with valid information in XML format should return valid response' do
|
||||
post admin_registration_path(:format => 'xml'), :admin => { :email => 'new_user@test.com', :password => 'new_user123', :password_confirmation => 'new_user123' }
|
||||
assert_response :success
|
||||
|
||||
@@ -69,7 +69,14 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.user(:user) == user
|
||||
assert_match /remember_user_token[^\n]*HttpOnly\n/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
|
||||
assert_match /remember_user_token[^\n]*HttpOnly/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
|
||||
end
|
||||
|
||||
test 'remember the user before sign up and redirect him to his home' do
|
||||
user = create_user_and_remember
|
||||
get new_user_registration_path
|
||||
assert warden.authenticated?(:user)
|
||||
assert_redirected_to root_path
|
||||
end
|
||||
|
||||
test 'cookies are destroyed on unverified requests' do
|
||||
|
||||
@@ -61,4 +61,21 @@ class TrackableHooksTest < ActionController::IntegrationTest
|
||||
assert_nil user.last_sign_in_at
|
||||
end
|
||||
end
|
||||
|
||||
test "do not track if devise.skip_trackable is set" do
|
||||
user = create_user
|
||||
sign_in_as_user do
|
||||
header 'devise.skip_trackable', '1'
|
||||
end
|
||||
user.reload
|
||||
assert_equal 0, user.sign_in_count
|
||||
visit destroy_user_session_path
|
||||
|
||||
sign_in_as_user do
|
||||
header 'devise.skip_trackable', false
|
||||
end
|
||||
user.reload
|
||||
assert_equal 1, user.sign_in_count
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -50,6 +50,11 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal [:rememberable, :database_authenticatable], Devise.mappings[:admin].strategies
|
||||
end
|
||||
|
||||
test 'has no input strategies depending on the model declaration' do
|
||||
assert_equal [:rememberable, :token_authenticatable], Devise.mappings[:user].no_input_strategies
|
||||
assert_equal [:rememberable], Devise.mappings[:admin].no_input_strategies
|
||||
end
|
||||
|
||||
test 'find scope for a given object' do
|
||||
assert_equal :user, Devise::Mapping.find_scope!(User)
|
||||
assert_equal :user, Devise::Mapping.find_scope!(:user)
|
||||
|
||||
@@ -111,12 +111,12 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'should return a new user if no email was found' do
|
||||
confirmation_user = User.send_confirmation_instructions(:email => "invalid@email.com")
|
||||
confirmation_user = User.send_confirmation_instructions(:email => "invalid@example.com")
|
||||
assert_not confirmation_user.persisted?
|
||||
end
|
||||
|
||||
test 'should add error to new user email if no email was found' do
|
||||
confirmation_user = User.send_confirmation_instructions(:email => "invalid@email.com")
|
||||
confirmation_user = User.send_confirmation_instructions(:email => "invalid@example.com")
|
||||
assert confirmation_user.errors[:email]
|
||||
assert_equal "not found", confirmation_user.errors[:email].join
|
||||
end
|
||||
|
||||
@@ -11,6 +11,39 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
user.save!
|
||||
assert_equal email.downcase, user.email
|
||||
end
|
||||
|
||||
test 'should remove whitespace from strip whitespace keys when saving' do
|
||||
# strip_whitespace_keys is set to :email by default.
|
||||
email = ' foo@bar.com '
|
||||
user = new_user(:email => email)
|
||||
|
||||
assert_equal email, user.email
|
||||
user.save!
|
||||
assert_equal email.strip, user.email
|
||||
end
|
||||
|
||||
test 'find_for_authentication and filter_auth_params should not modify the conditions hash' do
|
||||
FilterAuthUser = Class.new(User) do
|
||||
def self.filter_auth_params(conditions)
|
||||
if conditions.is_a?(Hash) && login = conditions.delete('login')
|
||||
key = login.include?('@') ? :email : :username
|
||||
conditions[key] = login
|
||||
end
|
||||
super(conditions)
|
||||
end
|
||||
end
|
||||
|
||||
conditions = { 'login' => 'foo@bar.com' }
|
||||
FilterAuthUser.find_for_authentication(conditions)
|
||||
|
||||
assert_equal({ 'login' => 'foo@bar.com' }, conditions)
|
||||
end
|
||||
|
||||
test "filter_auth_params should not convert booleans and integer to strings" do
|
||||
conditions = { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => (1..10) }
|
||||
conditions = User.__send__(:filter_auth_params, conditions)
|
||||
assert_equal( { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => "1..10" }, conditions)
|
||||
end
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
user = new_user
|
||||
@@ -70,7 +103,7 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
:password => 'pass321', :password_confirmation => 'pass321')
|
||||
assert user.reload.valid_password?('pass321')
|
||||
end
|
||||
|
||||
|
||||
test 'should add an error to current password when it is invalid' do
|
||||
user = create_user
|
||||
assert_not user.update_with_password(:current_password => 'other',
|
||||
@@ -87,10 +120,19 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert_match "can't be blank", user.errors[:current_password].join
|
||||
end
|
||||
|
||||
test 'should run validations even when current password is invalid or blank' do
|
||||
user = UserWithValidation.create!(valid_attributes)
|
||||
user.save
|
||||
assert user.persisted?
|
||||
assert_not user.update_with_password(:username => "")
|
||||
assert_match "usertest", user.reload.username
|
||||
assert_match "can't be blank", user.errors[:username].join
|
||||
end
|
||||
|
||||
test 'should ignore password and its confirmation if they are blank' do
|
||||
user = create_user
|
||||
assert user.update_with_password(:current_password => '123456', :email => "new@email.com")
|
||||
assert_equal "new@email.com", user.email
|
||||
assert user.update_with_password(:current_password => '123456', :email => "new@example.com")
|
||||
assert_equal "new@example.com", user.email
|
||||
end
|
||||
|
||||
test 'should not update password with invalid confirmation' do
|
||||
@@ -108,6 +150,19 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert user.password_confirmation.blank?
|
||||
end
|
||||
|
||||
test 'should update the user without password' do
|
||||
user = create_user
|
||||
user.update_without_password(:email => 'new@example.com')
|
||||
assert_equal 'new@example.com', user.email
|
||||
end
|
||||
|
||||
test 'should not update password without password' do
|
||||
user = create_user
|
||||
user.update_without_password(:password => 'pass321', :password_confirmation => 'pass321')
|
||||
assert !user.reload.valid_password?('pass321')
|
||||
assert user.valid_password?('123456')
|
||||
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")
|
||||
|
||||
@@ -31,7 +31,7 @@ class EncryptableTest < ActiveSupport::TestCase
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor Admin, :sha1 do
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
|
||||
SecureRandom.expects(:base64).with(15).returns('friendly_token')
|
||||
assert_equal 'friendly_token', create_admin.password_salt
|
||||
end
|
||||
end
|
||||
|
||||
@@ -163,12 +163,12 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'should return a new user if no email was found' do
|
||||
unlock_user = User.send_unlock_instructions(:email => "invalid@email.com")
|
||||
unlock_user = User.send_unlock_instructions(:email => "invalid@example.com")
|
||||
assert_not unlock_user.persisted?
|
||||
end
|
||||
|
||||
test 'should add error to new user email if no email was found' do
|
||||
unlock_user = User.send_unlock_instructions(:email => "invalid@email.com")
|
||||
unlock_user = User.send_unlock_instructions(:email => "invalid@example.com")
|
||||
assert_equal 'not found', unlock_user.errors[:email].join
|
||||
end
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'should return a new record with errors if user was not found by e-mail' do
|
||||
reset_password_user = User.send_reset_password_instructions(:email => "invalid@email.com")
|
||||
reset_password_user = User.send_reset_password_instructions(:email => "invalid@example.com")
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "not found", reset_password_user.errors[:email].join
|
||||
end
|
||||
@@ -192,8 +192,34 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
|
||||
assert user.valid_password?(old_password)
|
||||
assert_not user.valid_password?('new_password')
|
||||
assert_equal "is invalid", reset_password_user.errors[:reset_password_token].join
|
||||
assert_equal "has expired, please request a new one", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should save the model when the reset_password_sent_at doesnt exist' do
|
||||
user = create_user
|
||||
def user.respond_to?(meth, *)
|
||||
if meth == :reset_password_sent_at=
|
||||
false
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
user.send_reset_password_instructions
|
||||
user.reload
|
||||
assert_not_nil user.reset_password_token
|
||||
end
|
||||
|
||||
test 'should have valid period if does not respond to reset_password_sent_at' do
|
||||
user = create_user
|
||||
def user.respond_to?(meth, *)
|
||||
if meth == :reset_password_sent_at
|
||||
false
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
assert user.reset_password_period_valid?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,6 +15,14 @@ module SharedRememberableTest
|
||||
resource.forget_me!
|
||||
assert resource.remember_created_at.nil?
|
||||
end
|
||||
|
||||
test 'forget_me should not try to update resource if it has been destroyed' do
|
||||
resource = create_resource
|
||||
resource.destroy
|
||||
resource.expects(:remember_created_at).never
|
||||
resource.expects(:save).never
|
||||
resource.forget_me!
|
||||
end
|
||||
|
||||
test 'remember is expired if not created at timestamp is set' do
|
||||
assert create_resource.remember_expired?
|
||||
|
||||
@@ -8,7 +8,7 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
assert_equal 'can\'t be blank', user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should require uniqueness of email, allowing blank' do
|
||||
test 'should require uniqueness of email if email has changed, allowing blank' do
|
||||
existing_user = create_user
|
||||
|
||||
user = new_user(:email => '')
|
||||
@@ -18,18 +18,24 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
user.email = existing_user.email
|
||||
assert user.invalid?
|
||||
assert_match(/taken/, user.errors[:email].join)
|
||||
|
||||
user.save(:validate => false)
|
||||
assert user.valid?
|
||||
end
|
||||
|
||||
test 'should require correct email format, allowing blank' do
|
||||
test 'should require correct email format if email has changed, allowing blank' do
|
||||
user = new_user(:email => '')
|
||||
assert user.invalid?
|
||||
assert_not_equal 'is invalid', user.errors[:email].join
|
||||
|
||||
%w(invalid_email_format email@invalid invalid$character@mail.com other@not 123).each do |email|
|
||||
%w(invalid_email_format 123 $$$ \(\) ).each do |email|
|
||||
user.email = email
|
||||
assert user.invalid?, 'should be invalid with email ' << email
|
||||
assert_equal 'is invalid', user.errors[:email].join
|
||||
end
|
||||
|
||||
user.save(:validate => false)
|
||||
assert user.valid?
|
||||
end
|
||||
|
||||
test 'should accept valid emails' do
|
||||
@@ -85,12 +91,19 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
user = create_user.reload
|
||||
user.password = user.password_confirmation = nil
|
||||
assert user.valid?
|
||||
|
||||
|
||||
user.password_confirmation = 'confirmation'
|
||||
assert user.invalid?
|
||||
assert_not (user.errors[:password].join =~ /is too long/)
|
||||
end
|
||||
|
||||
test 'should complain about length even if possword is not required' do
|
||||
user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129)
|
||||
user.stubs(:password_required?).returns(false)
|
||||
assert user.invalid?
|
||||
assert_equal 'is too long (maximum is 128 characters)', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'shuold not be included in objects with invalid API' do
|
||||
assert_raise RuntimeError do
|
||||
Class.new.send :include, Devise::Models::Validatable
|
||||
|
||||
@@ -10,6 +10,10 @@ class WithValidation < Admin
|
||||
devise :database_authenticatable, :validatable, :password_length => 2..6
|
||||
end
|
||||
|
||||
class UserWithValidation < User
|
||||
validates_presence_of :username
|
||||
end
|
||||
|
||||
class Several < Admin
|
||||
devise :validatable
|
||||
devise :lockable
|
||||
|
||||
@@ -35,6 +35,10 @@ class OmniAuthRoutesTest < ActionController::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'should generate authorization path for named open_id omniauth' do
|
||||
assert_match "/users/auth/google", @controller.omniauth_authorize_path(:user, :google)
|
||||
end
|
||||
|
||||
test 'should generate authorization path with params' do
|
||||
assert_match "/users/auth/open_id?openid_url=http%3A%2F%2Fyahoo.com",
|
||||
@controller.omniauth_authorize_path(:user, :open_id, :openid_url => "http://yahoo.com")
|
||||
|
||||
@@ -5,6 +5,15 @@ class HomeController < ApplicationController
|
||||
def private
|
||||
end
|
||||
|
||||
def user_dashboard
|
||||
end
|
||||
|
||||
def admin_dashboard
|
||||
end
|
||||
|
||||
def join
|
||||
end
|
||||
|
||||
def set
|
||||
session["devise.foo_bar"] = "something"
|
||||
head :ok
|
||||
|
||||
1
test/rails_app/app/views/home/admin_dashboard.html.erb
Normal file
1
test/rails_app/app/views/home/admin_dashboard.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
Admin dashboard
|
||||
1
test/rails_app/app/views/home/join.html.erb
Normal file
1
test/rails_app/app/views/home/join.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
Join
|
||||
1
test/rails_app/app/views/home/user_dashboard.html.erb
Normal file
1
test/rails_app/app/views/home/user_dashboard.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
User dashboard
|
||||
@@ -35,6 +35,11 @@ Devise.setup do |config|
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Configure which authentication keys should have whitespace stripped.
|
||||
# These keys will have whitespace before and after removed upon creating or
|
||||
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||
config.strip_whitespace_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
@@ -172,6 +177,7 @@ Devise.setup do |config|
|
||||
# ==> OmniAuth
|
||||
config.omniauth :facebook, 'APP_ID', 'APP_SECRET', :scope => 'email,offline_access'
|
||||
config.omniauth :open_id
|
||||
config.omniauth :open_id, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not supported by Devise, or
|
||||
|
||||
@@ -19,7 +19,7 @@ Rails.application.routes.draw do
|
||||
match "/sign_in", :to => "devise/sessions#new"
|
||||
|
||||
# Admin scope
|
||||
devise_for :admin, :path => "admin_area", :controllers => { :sessions => "admins/sessions" }, :skip => :passwords
|
||||
devise_for :admin, :path => "admin_area", :controllers => { :sessions => :"admins/sessions" }, :skip => :passwords
|
||||
|
||||
match "/admin_area/home", :to => "admins#index", :as => :admin_root
|
||||
match "/anywhere", :to => "foo#bar", :as => :new_admin_password
|
||||
@@ -28,6 +28,25 @@ Rails.application.routes.draw do
|
||||
match "/private", :to => "home#private", :as => :private
|
||||
end
|
||||
|
||||
authenticated :admin do
|
||||
match "/dashboard", :to => "home#admin_dashboard"
|
||||
end
|
||||
|
||||
authenticated do
|
||||
match "/dashboard", :to => "home#user_dashboard"
|
||||
end
|
||||
|
||||
unauthenticated do
|
||||
match "/join", :to => "home#join"
|
||||
end
|
||||
|
||||
# Routes for constraints testing
|
||||
devise_for :headquarters_admin, :class_name => "Admin", :path => "headquarters", :constraints => {:host => /192\.168\.1\.\d\d\d/}
|
||||
|
||||
constraints(:host => /192\.168\.1\.\d\d\d/) do
|
||||
devise_for :homebase_admin, :class_name => "Admin", :path => "homebase"
|
||||
end
|
||||
|
||||
# Other routes for routing_test.rb
|
||||
devise_for :reader, :class_name => "User", :only => :passwords
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ module SharedUser
|
||||
:registerable, :rememberable, :timeoutable, :token_authenticatable,
|
||||
:trackable, :validatable, :omniauthable
|
||||
|
||||
attr_accessor :other_key
|
||||
|
||||
# They need to be included after Devise is called.
|
||||
extend ExtendMethods
|
||||
end
|
||||
|
||||
@@ -96,6 +96,11 @@ class DefaultRoutingTest < ActionController::TestCase
|
||||
assert_recognizes({:controller => 'users/omniauth_callbacks', :action => 'facebook'}, {:path => 'users/auth/facebook/callback', :method => :post})
|
||||
assert_named_route "/users/auth/facebook/callback", :user_omniauth_callback_path, :facebook
|
||||
|
||||
# named open_id
|
||||
assert_recognizes({:controller => 'users/omniauth_callbacks', :action => 'google'}, {:path => 'users/auth/google/callback', :method => :get})
|
||||
assert_recognizes({:controller => 'users/omniauth_callbacks', :action => 'google'}, {:path => 'users/auth/google/callback', :method => :post})
|
||||
assert_named_route "/users/auth/google/callback", :user_omniauth_callback_path, :google
|
||||
|
||||
assert_raise ActionController::RoutingError do
|
||||
assert_recognizes({:controller => 'ysers/omniauth_callbacks', :action => 'twitter'}, {:path => 'users/auth/twitter/callback', :method => :get})
|
||||
end
|
||||
@@ -171,6 +176,20 @@ class CustomizedRoutingTest < ActionController::TestCase
|
||||
assert_recognizes({:controller => 'devise/sessions', :action => 'destroy'}, {:path => '/sign_out_via/delete_or_posts/sign_out', :method => :get})
|
||||
end
|
||||
end
|
||||
|
||||
test 'map with constraints defined in hash' do
|
||||
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => 'http://192.168.1.100/headquarters/sign_up', :method => :get})
|
||||
assert_raise ActionController::RoutingError do
|
||||
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => 'http://10.0.0.100/headquarters/sign_up', :method => :get})
|
||||
end
|
||||
end
|
||||
|
||||
test 'map with constraints defined in block' do
|
||||
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => 'http://192.168.1.100/homebase/sign_up', :method => :get})
|
||||
assert_raise ActionController::RoutingError do
|
||||
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => 'http://10.0.0.100//homebase/sign_up', :method => :get})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ScopedRoutingTest < ActionController::TestCase
|
||||
|
||||
@@ -19,7 +19,7 @@ class ActiveSupport::TestCase
|
||||
def generate_unique_email
|
||||
@@email_count ||= 0
|
||||
@@email_count += 1
|
||||
"test#{@@email_count}@email.com"
|
||||
"test#{@@email_count}@example.com"
|
||||
end
|
||||
|
||||
def valid_attributes(attributes={})
|
||||
@@ -57,4 +57,4 @@ class ActiveSupport::TestCase
|
||||
object.send :"#{key}=", value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user