mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
197 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39b59142ea | ||
|
|
624fb566fb | ||
|
|
76edb49c9d | ||
|
|
b7d86ac014 | ||
|
|
7097189de1 | ||
|
|
c4e451b896 | ||
|
|
b6cf1df659 | ||
|
|
29afe2d21c | ||
|
|
a722c6236c | ||
|
|
fd6ba32812 | ||
|
|
14aedc416a | ||
|
|
9fe0cb4954 | ||
|
|
2a5669967f | ||
|
|
13376d22de | ||
|
|
6b21531916 | ||
|
|
4a4dcb30ef | ||
|
|
2cfa58b433 | ||
|
|
c6dd846718 | ||
|
|
7a2d76d002 | ||
|
|
e5a8febe3b | ||
|
|
60809719b8 | ||
|
|
ee6a8ab93a | ||
|
|
c3d92095f8 | ||
|
|
460beae671 | ||
|
|
fa6c8ab321 | ||
|
|
d02f86bef5 | ||
|
|
0d74c1b4f0 | ||
|
|
8f3539c14f | ||
|
|
3d5e692c2c | ||
|
|
cb622e99d8 | ||
|
|
567d59e48a | ||
|
|
f89f71262d | ||
|
|
5e2ee5eb6a | ||
|
|
34a54dac2d | ||
|
|
e329930a82 | ||
|
|
3940846d79 | ||
|
|
c608fbe89e | ||
|
|
8db00eedea | ||
|
|
0e904dda79 | ||
|
|
e4af6adaf7 | ||
|
|
e1c7c49a0c | ||
|
|
bd9f148d24 | ||
|
|
f009011179 | ||
|
|
5adb854aa5 | ||
|
|
1f51524bae | ||
|
|
23f8dbed80 | ||
|
|
140acfe4cc | ||
|
|
cb2cb2cff7 | ||
|
|
30300fc6b9 | ||
|
|
de8982563a | ||
|
|
e7154b3af9 | ||
|
|
39360dc419 | ||
|
|
eeb61929ac | ||
|
|
56fd7031e5 | ||
|
|
425fe7f22d | ||
|
|
ed51fc7636 | ||
|
|
d23a7ca8d5 | ||
|
|
1b1dc2a429 | ||
|
|
be2aeee70f | ||
|
|
8a3deb98cd | ||
|
|
e4902143f8 | ||
|
|
d3a374777b | ||
|
|
5b94d9b803 | ||
|
|
b6652abc7c | ||
|
|
97f0bacfa0 | ||
|
|
210bc6aa66 | ||
|
|
8170d5e340 | ||
|
|
6225902034 | ||
|
|
0487e9eafe | ||
|
|
73669e09c8 | ||
|
|
da510508bb | ||
|
|
02ae0c22ef | ||
|
|
edee511cd1 | ||
|
|
fbd35ec332 | ||
|
|
30b35e3727 | ||
|
|
330cafd3d2 | ||
|
|
fe9024218c | ||
|
|
0c9bd3259e | ||
|
|
b23e2e807a | ||
|
|
7876acf960 | ||
|
|
74166e224b | ||
|
|
cb778d033f | ||
|
|
1bf7da148a | ||
|
|
d58a72ee32 | ||
|
|
15d195d2f0 | ||
|
|
4f093574da | ||
|
|
64457e2c1f | ||
|
|
3f4fb1a769 | ||
|
|
1982ad9f57 | ||
|
|
569d205ca7 | ||
|
|
63b72cd512 | ||
|
|
bb89ca4865 | ||
|
|
307fe6cb60 | ||
|
|
fe2d7b5ffe | ||
|
|
d445db9e5e | ||
|
|
e4cae200f4 | ||
|
|
a535b047ff | ||
|
|
aa81df261c | ||
|
|
0cc900e7cf | ||
|
|
9bff1cf658 | ||
|
|
305059f573 | ||
|
|
392e664036 | ||
|
|
43a3431c3e | ||
|
|
930d5874ca | ||
|
|
3375985ab8 | ||
|
|
2e43944567 | ||
|
|
352edc024b | ||
|
|
b5e289c9a8 | ||
|
|
42d002702c | ||
|
|
6bd65209d5 | ||
|
|
970457f2c2 | ||
|
|
bbaaefa995 | ||
|
|
fdf6a48a7e | ||
|
|
7113beac81 | ||
|
|
0c5acc6f38 | ||
|
|
dd721f1857 | ||
|
|
ae75186c52 | ||
|
|
ca293d17ba | ||
|
|
add8f8a203 | ||
|
|
6a6ed6702e | ||
|
|
2d0f887ba7 | ||
|
|
3109b0924b | ||
|
|
bbafb70655 | ||
|
|
aac9c40cba | ||
|
|
f964ea526b | ||
|
|
bca43a7576 | ||
|
|
8440ed0101 | ||
|
|
cb5e0c4a7b | ||
|
|
0287d8cc80 | ||
|
|
a48c815dc8 | ||
|
|
f332d7e932 | ||
|
|
a14b833581 | ||
|
|
c9fe8885f9 | ||
|
|
e1c3b915e7 | ||
|
|
f06bed279a | ||
|
|
3fd206c591 | ||
|
|
7a1852e9f5 | ||
|
|
76a4800446 | ||
|
|
5f93d8355c | ||
|
|
1f8909458f | ||
|
|
68f699bfd4 | ||
|
|
0615c0a0a4 | ||
|
|
c78bb68c66 | ||
|
|
d018970c4b | ||
|
|
971f68f97d | ||
|
|
4207c2321f | ||
|
|
54dc82ad25 | ||
|
|
fa239b984a | ||
|
|
692f7b27ff | ||
|
|
258eb1c7e6 | ||
|
|
aa61034d40 | ||
|
|
42f2196d01 | ||
|
|
d87521723d | ||
|
|
6e91edd5e3 | ||
|
|
fb4ec6e9da | ||
|
|
7ff0231ab7 | ||
|
|
3f086656aa | ||
|
|
55cb7195b8 | ||
|
|
555435e6fe | ||
|
|
88d4aca2c4 | ||
|
|
038eb321d4 | ||
|
|
c8c84c77c6 | ||
|
|
8f20b13f84 | ||
|
|
af1295284c | ||
|
|
1b43cb5203 | ||
|
|
b34f456096 | ||
|
|
e95eb93eb7 | ||
|
|
1a2590dc08 | ||
|
|
1cdb02bd54 | ||
|
|
7759c8b3f3 | ||
|
|
b32883a7c5 | ||
|
|
27051cb2fe | ||
|
|
e8e3df3891 | ||
|
|
2561cd4eac | ||
|
|
146090f86e | ||
|
|
4519364eaf | ||
|
|
f56c588a6a | ||
|
|
379d8c69a5 | ||
|
|
13e8bc22e3 | ||
|
|
c27bc21af9 | ||
|
|
a156576ce9 | ||
|
|
b942520dc4 | ||
|
|
a2e92a2ef2 | ||
|
|
60be68436b | ||
|
|
fe4eaf2d12 | ||
|
|
845c186f48 | ||
|
|
9f832d2cb2 | ||
|
|
a23a52b2f7 | ||
|
|
7ed1fb116f | ||
|
|
b50fd1a72e | ||
|
|
2305e8f8cf | ||
|
|
f2f9232b89 | ||
|
|
cb62597afa | ||
|
|
089c316f37 | ||
|
|
ec5bfe9119 | ||
|
|
912969b5a0 | ||
|
|
fe5ef25614 |
6
.travis.yml
Normal file
6
.travis.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
script: "rake test"
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- ree
|
||||
- jruby
|
||||
@@ -1,3 +1,84 @@
|
||||
== 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
|
||||
* All controllers can now handle different mime types than html using Responders (by github.com/sikachu)
|
||||
* Added reset_password_within as configuration option to send the token for recovery (by github.com/jdguyot)
|
||||
* Bump password length to 128 characters (by github.com/k33l0r)
|
||||
* Add :only as option to devise_for (by github.com/timoschilling)
|
||||
* Allow to override path after sending password instructions (by github.com/irohiroki)
|
||||
* require_no_authentication has its own flash message (by github.com/jackdempsey)
|
||||
|
||||
* bug fix
|
||||
* Fix a bug where configuration options were being included too late
|
||||
* Ensure Devise::TestHelpers can be used to tests Devise internal controllers (by github.com/jwilger)
|
||||
* valid_password? should not choke on empty passwords (by github.com/mikel)
|
||||
* Calling devise more than once does not include previously added modules anymore
|
||||
* downcase_keys before validation
|
||||
|
||||
* backward incompatible changes
|
||||
* authentication_keys are no longer considered when creating the e-mail validations, the previous behavior was buggy. You must double check if you were relying on such behavior.
|
||||
|
||||
== 1.2.1
|
||||
|
||||
* enhancements
|
||||
* Improve update path messages
|
||||
|
||||
== 1.2.0
|
||||
|
||||
* bug fix
|
||||
* Properly ignore path prefix on omniauthable
|
||||
* Faster uniqueness queries
|
||||
* Rename active? to active_for_authentication? to avoid conflicts
|
||||
|
||||
== 1.2.rc2
|
||||
|
||||
* enhancements
|
||||
* Make friendly_token 20 chars long
|
||||
* Use secure_compare
|
||||
|
||||
* bug fix
|
||||
* Fix an issue causing infinite redirects in production
|
||||
* rails g destroy works properly with devise generators (by github.com/andmej)
|
||||
* before_failure callbacks should work on test helpers (by github.com/twinge)
|
||||
* rememberable cookie now is httponly by default (by github.com/JamesFerguson)
|
||||
* Add missing confirmation_keys (by github.com/JohnPlummer)
|
||||
* Ensure after_* hooks are called on RegistrationsController
|
||||
* When using database_authenticatable Devise will now only create an email field when appropriate (if using default authentication_keys or custom authentication_keys with email included)
|
||||
* Ensure stateless token does not trigger timeout (by github.com/pixelauthority)
|
||||
* Implement handle_unverified_request for Rails 3.0.4 compatibility and improve FailureApp reliance on symbols
|
||||
* Consider namespaces while generating routes
|
||||
* Custom failure apps no longer ignored in test mode (by github.com/jaghion)
|
||||
* Do not depend on ActiveModel::Dirty
|
||||
* Manual sign_in now triggers remember token
|
||||
* Be sure to halt strategies on failures
|
||||
* Consider SCRIPT_NAME on Omniauth paths
|
||||
* Reset failed attempts when lock is expired
|
||||
* Ensure there is no Mongoid injection
|
||||
|
||||
* deprecations
|
||||
* Deprecated anybody_signed_in? in favor of signed_in? (by github.com/gavinhughes)
|
||||
* Removed --haml and --slim view templates
|
||||
* Devise::OmniAuth helpers were deprecated and removed in favor of Omniauth.config.test_mode
|
||||
|
||||
== 1.2.rc
|
||||
|
||||
* deprecations
|
||||
@@ -30,12 +111,26 @@
|
||||
* bugfix
|
||||
* after_sign_in_path_for always receives a resource
|
||||
* Do not execute Warden::Callbacks on Devise::TestHelpers (by github.com/sgronblo)
|
||||
* Password recovery and account unlocking takes into account authentication keys (by github.com/RStankov)
|
||||
* Allow password recovery and account unlocking to change used keys (by github.com/RStankov)
|
||||
* FailureApp now properly handles nil request.format
|
||||
* Fix a bug causing FailureApp to return with HTTP Auth Headers for IE7
|
||||
* Ensure namespaces has proper scoped views
|
||||
* Ensure Devise does not set empty flash messages (by github.com/sxross)
|
||||
|
||||
== 1.1.6
|
||||
|
||||
* Use a more secure e-mail regexp
|
||||
* Implement Rails 3.0.4 handle unverified request
|
||||
* Use secure_compare to compare passwords
|
||||
|
||||
== 1.1.5
|
||||
|
||||
* bugfix
|
||||
* Ensure to convert keys on indifferent hash
|
||||
|
||||
* defaults
|
||||
* Set config.http_authenticatable to false to avoid confusion
|
||||
|
||||
== 1.1.4
|
||||
|
||||
* bugfix
|
||||
|
||||
8
Gemfile
8
Gemfile
@@ -2,9 +2,9 @@ source "http://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.0.0"
|
||||
gem "oa-oauth", :require => "omniauth/oauth"
|
||||
gem "oa-openid", :require => "omniauth/openid"
|
||||
gem "rails", "~> 3.0.4"
|
||||
gem "oa-oauth", '~> 0.2.0', :require => "omniauth/oauth"
|
||||
gem "oa-openid", '~> 0.2.0', :require => "omniauth/openid"
|
||||
|
||||
group :test do
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
@@ -24,6 +24,6 @@ platforms :ruby do
|
||||
group :mongoid do
|
||||
gem "mongo", "1.1.2"
|
||||
gem "mongoid", "2.0.0.beta.20"
|
||||
gem "bson_ext", "1.1.2"
|
||||
gem "bson_ext", "1.2.1"
|
||||
end
|
||||
end
|
||||
|
||||
132
Gemfile.lock
132
Gemfile.lock
@@ -1,69 +1,68 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (1.2.rc)
|
||||
devise (1.3.1)
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
orm_adapter (~> 0.0.2)
|
||||
warden (~> 1.0.2)
|
||||
orm_adapter (~> 0.0.3)
|
||||
warden (~> 1.0.3)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
abstract (1.0.0)
|
||||
actionmailer (3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
mail (~> 2.2.9)
|
||||
actionpack (3.0.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
actionmailer (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
mail (~> 2.2.15)
|
||||
actionpack (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
builder (~> 2.1.2)
|
||||
erubis (~> 2.6.6)
|
||||
i18n (~> 0.4)
|
||||
rack (~> 1.2.1)
|
||||
rack-mount (~> 0.6.13)
|
||||
rack-test (~> 0.5.6)
|
||||
rack-test (~> 0.5.7)
|
||||
tzinfo (~> 0.3.23)
|
||||
activemodel (3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activemodel (3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
builder (~> 2.1.2)
|
||||
i18n (~> 0.4)
|
||||
activerecord (3.0.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activerecord (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
arel (~> 2.0.2)
|
||||
tzinfo (~> 0.3.23)
|
||||
activerecord-jdbc-adapter (1.0.2-java)
|
||||
activerecord-jdbcsqlite3-adapter (1.0.2-java)
|
||||
activerecord-jdbc-adapter (= 1.0.2)
|
||||
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.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activesupport (3.0.3)
|
||||
addressable (2.2.2)
|
||||
arel (2.0.4)
|
||||
bcrypt-ruby (2.1.2)
|
||||
bson (1.1.2)
|
||||
bson_ext (1.1.2)
|
||||
activeresource (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
activesupport (3.0.4)
|
||||
addressable (2.2.4)
|
||||
arel (2.0.8)
|
||||
bcrypt-ruby (2.1.4)
|
||||
bson (1.2.1)
|
||||
bson_ext (1.2.1)
|
||||
builder (2.1.2)
|
||||
columnize (0.3.2)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
faraday (0.5.2)
|
||||
addressable (~> 2.2.2)
|
||||
multipart-post (~> 1.0.1)
|
||||
faraday (0.5.7)
|
||||
addressable (~> 2.2.4)
|
||||
multipart-post (~> 1.1.0)
|
||||
rack (>= 1.1.0, < 2)
|
||||
i18n (0.4.2)
|
||||
i18n (0.5.0)
|
||||
jdbc-sqlite3 (3.6.14.2.056-java)
|
||||
linecache (0.43)
|
||||
mail (2.2.10)
|
||||
mail (2.2.15)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (~> 0.4.1)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.16)
|
||||
mocha (0.9.9)
|
||||
rake
|
||||
mocha (0.9.12)
|
||||
mongo (1.1.2)
|
||||
bson (>= 1.1.1)
|
||||
mongoid (2.0.0.beta.20)
|
||||
@@ -72,27 +71,27 @@ GEM
|
||||
tzinfo (~> 0.3.22)
|
||||
will_paginate (~> 3.0.pre)
|
||||
multi_json (0.0.5)
|
||||
multipart-post (1.0.1)
|
||||
nokogiri (1.4.3.1)
|
||||
nokogiri (1.4.3.1-java)
|
||||
multipart-post (1.1.0)
|
||||
nokogiri (1.4.4)
|
||||
nokogiri (1.4.4-java)
|
||||
weakling (>= 0.0.3)
|
||||
oa-core (0.1.6)
|
||||
oa-core (0.2.0)
|
||||
rack (~> 1.1)
|
||||
oa-oauth (0.1.6)
|
||||
oa-oauth (0.2.0)
|
||||
multi_json (~> 0.0.2)
|
||||
nokogiri (~> 1.4.2)
|
||||
oa-core (= 0.1.6)
|
||||
oa-core (= 0.2.0)
|
||||
oauth (~> 0.4.0)
|
||||
oauth2 (~> 0.1.0)
|
||||
oa-openid (0.1.6)
|
||||
oa-core (= 0.1.6)
|
||||
oauth2 (~> 0.1.1)
|
||||
oa-openid (0.2.0)
|
||||
oa-core (= 0.2.0)
|
||||
rack-openid (~> 1.2.0)
|
||||
ruby-openid-apps-discovery
|
||||
oauth (0.4.4)
|
||||
oauth2 (0.1.0)
|
||||
oauth2 (0.1.1)
|
||||
faraday (~> 0.5.0)
|
||||
multi_json (~> 0.0.4)
|
||||
orm_adapter (0.0.3)
|
||||
orm_adapter (0.0.4)
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.1)
|
||||
rack-mount (0.6.13)
|
||||
@@ -100,19 +99,19 @@ GEM
|
||||
rack-openid (1.2.0)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-test (0.5.6)
|
||||
rack-test (0.5.7)
|
||||
rack (>= 1.0)
|
||||
rails (3.0.3)
|
||||
actionmailer (= 3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
activerecord (= 3.0.3)
|
||||
activeresource (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
rails (3.0.4)
|
||||
actionmailer (= 3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activerecord (= 3.0.4)
|
||||
activeresource (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.0.3)
|
||||
railties (3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
railties (= 3.0.4)
|
||||
railties (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
rake (>= 0.8.7)
|
||||
thor (~> 0.14.4)
|
||||
rake (0.8.7)
|
||||
@@ -124,12 +123,14 @@ GEM
|
||||
ruby-openid (2.1.8)
|
||||
ruby-openid-apps-discovery (1.2.0)
|
||||
ruby-openid (>= 2.1.7)
|
||||
sqlite3-ruby (1.3.2)
|
||||
sqlite3 (1.3.3)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
thor (0.14.6)
|
||||
treetop (1.4.9)
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.23)
|
||||
warden (1.0.2)
|
||||
tzinfo (0.3.24)
|
||||
warden (1.0.3)
|
||||
rack (>= 1.0.0)
|
||||
weakling (0.0.4-java)
|
||||
webrat (0.7.2)
|
||||
@@ -144,17 +145,14 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
bson_ext (= 1.1.2)
|
||||
bson_ext (= 1.2.1)
|
||||
devise!
|
||||
mocha
|
||||
mongo (= 1.1.2)
|
||||
mongoid (= 2.0.0.beta.20)
|
||||
oa-oauth
|
||||
oa-openid
|
||||
orm_adapter (~> 0.0.2)
|
||||
rails (~> 3.0.0)
|
||||
oa-oauth (~> 0.2.0)
|
||||
oa-openid (~> 0.2.0)
|
||||
rails (~> 3.0.4)
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3-ruby
|
||||
warden (~> 1.0.2)
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
Copyright 2009-2011 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
40
README.rdoc
40
README.rdoc
@@ -9,7 +9,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
|
||||
It's composed of 12 modules:
|
||||
|
||||
* Database Authenticatable: encrypts and stores a password in the database to validate the authenticity of an user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* Database Authenticatable: encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* Token Authenticatable: signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
* Omniauthable: adds Omniauth (github.com/intridea/omniauth) support;
|
||||
* Confirmable: sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
@@ -20,11 +20,11 @@ It's composed of 12 modules:
|
||||
* Timeoutable: expires sessions that have no activity in a specified period of time.
|
||||
* Validatable: provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* Lockable: locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
* Encryptable: allows support of other authentication mechanisms besides Bcrypt (the default).
|
||||
* Encryptable: adds support of other authentication mechanisms besides the built-in Bcrypt (the default).
|
||||
|
||||
== Information
|
||||
|
||||
=== The Devise Wiki
|
||||
=== The Devise wiki
|
||||
|
||||
The Devise Wiki has lots of additional information about Devise including many "how-to" articles and answers to the most frequently asked questions. Please browse the Wiki after finishing this README:
|
||||
|
||||
@@ -36,11 +36,11 @@ If you discover a problem with Devise, we would like to know about it. However,
|
||||
|
||||
http://github.com/plataformatec/devise/wiki/Bug-reports
|
||||
|
||||
If you found a security bug, do *NOT* use the GitHub Issue tracker. Send private GitHub message or email to the maintainers listed in the bottom of the README.
|
||||
If you found a security bug, do *NOT* use the GitHub issue tracker. Send email or a private GitHub message to the maintainers listed at the bottom of the README.
|
||||
|
||||
=== Google Group
|
||||
=== Mailing list
|
||||
|
||||
If you have any questions, comments, or concerns please use the Google Group instead of the GitHub Issues tracker:
|
||||
If you have any questions, comments, or concerns, please use the Google Group instead of the GitHub issue tracker:
|
||||
|
||||
http://groups.google.com/group/plataformatec-devise
|
||||
|
||||
@@ -52,7 +52,7 @@ http://rubydoc.info/github/plataformatec/devise/master/frames
|
||||
|
||||
If you need to use Devise with Rails 2.3, you can always run `gem server` from the command line after you install the gem to access the old documentation.
|
||||
|
||||
=== Example Applications
|
||||
=== Example applications
|
||||
|
||||
There are a few example applications available on GitHub that demonstrate various features of Devise with different versions of Rails. You can view them here:
|
||||
|
||||
@@ -70,6 +70,8 @@ We hope that you will consider contributing to Devise. Please read this short ov
|
||||
|
||||
http://github.com/plataformatec/devise/wiki/Contributing
|
||||
|
||||
You will usually want to write tests for your changes. To run the test suite, `cd` into Devise's top-level directory and run `bundle install` and `rake`. For the tests to pass, you will need to have a MongoDB server (version 1.6 or newer) running on your system.
|
||||
|
||||
== Installation
|
||||
|
||||
You can use the latest Rails 3 gem with the latest Devise gem:
|
||||
@@ -84,10 +86,19 @@ 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.
|
||||
|
||||
== Starting with Rails?
|
||||
|
||||
If you are building your first Rails application, we recommend you to *not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch, today we have two resources:
|
||||
|
||||
* Michael Hartl's online book: http://railstutorial.org/chapters/modeling-and-viewing-users-two#top
|
||||
* Ryan Bates' Railscast: http://railscasts.com/episodes/250-authentication-from-scratch
|
||||
|
||||
Once you have solidified you understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
|
||||
|
||||
== Getting started
|
||||
|
||||
This is a walkthrough with all steps you need to setup a devise resource, including model, migration, route files, and optional configuration.
|
||||
@@ -141,7 +152,7 @@ You can access the session for this scope:
|
||||
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use user_root_path if it exists, otherwise default root_path will be used. This means that you need to set the root inside your routes:
|
||||
|
||||
root :to => "home"
|
||||
root :to => "home#index"
|
||||
|
||||
You can also overwrite after_sign_in_path_for and after_sign_out_path_for to customize your redirect hooks.
|
||||
|
||||
@@ -201,8 +212,6 @@ Since Devise is an engine, all its views are packaged inside the gem. These view
|
||||
|
||||
rails generate devise:views
|
||||
|
||||
If you are using HAML, you will need hpricot installed to convert Devise views to HAML.
|
||||
|
||||
If you have more than one role in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all roles. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
|
||||
|
||||
After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new". You can also use the generator to generate scoped views:
|
||||
@@ -250,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:
|
||||
@@ -306,12 +315,11 @@ If you're using RSpec and want the helpers automatically included within all +de
|
||||
|
||||
Do not use such helpers for integration tests such as Cucumber or Webrat. Instead, fill in the form or explicitly set the user in session. For more tips, check the wiki (http://wiki.github.com/plataformatec/devise).
|
||||
|
||||
=== OAuth2
|
||||
=== Omniauth
|
||||
|
||||
Devise comes with OAuth support out of the box if you're using Devise from the git repository (for now). You can read more about OAuth2 support in the wiki:
|
||||
Devise comes with Omniauth support out of the box to authenticate from other providers. You can read more about Omniauth support in the wiki:
|
||||
|
||||
* http://github.com/plataformatec/devise/wiki/OAuth2:-Overview
|
||||
* http://github.com/plataformatec/devise/wiki/OAuth2:-Testing
|
||||
* https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
|
||||
|
||||
=== Other ORMs
|
||||
|
||||
|
||||
29
Rakefile
29
Rakefile
@@ -1,9 +1,7 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'devise', 'version')
|
||||
|
||||
desc 'Default: run tests for all ORMs.'
|
||||
task :default => :pre_commit
|
||||
@@ -12,7 +10,9 @@ desc 'Run Devise tests for all ORMs.'
|
||||
task :pre_commit do
|
||||
Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file|
|
||||
orm = File.basename(file).split(".").first
|
||||
system "rake test DEVISE_ORM=#{orm}"
|
||||
# "Some day, my son, rake's inner wisdom will reveal itself. Until then,
|
||||
# take this `system` -- may its brute force protect you well."
|
||||
exit 1 unless system "rake test DEVISE_ORM=#{orm}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,26 +32,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_files.include('README.rdoc')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |s|
|
||||
root_files = FileList["README.rdoc", "MIT-LICENSE", "CHANGELOG.rdoc"]
|
||||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
s.description = "Flexible authentication solution for Rails with Warden"
|
||||
s.authors = ['José Valim', 'Carlos Antônio']
|
||||
s.files = root_files + FileList["{app,config,lib}/**/*"]
|
||||
s.extra_rdoc_files = root_files
|
||||
s.add_dependency("warden", "~> 1.0.2")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.2")
|
||||
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
|
||||
end
|
||||
|
||||
Jeweler::GemcutterTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
|
||||
end
|
||||
|
||||
4
TODO
4
TODO
@@ -1,4 +0,0 @@
|
||||
* Move integration tests to Capybara
|
||||
* Better ORM integration
|
||||
* Add support to automatically refresh the access token for OAuth
|
||||
* Add test to generators using the new Rails::Generators::TestCase
|
||||
@@ -12,10 +12,10 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :send_instructions
|
||||
redirect_to new_session_path(resource_name)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => after_resending_confirmation_instructions_path_for(resource_name)
|
||||
else
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,10 +24,18 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :confirmed
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
set_flash_message(:notice, :confirmed) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with_navigational(resource){ redirect_to redirect_location(resource_name, resource) }
|
||||
else
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The path used after resending confirmation instructions.
|
||||
def after_resending_confirmation_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,18 +9,18 @@ class Devise::OmniauthCallbacksController < ApplicationController
|
||||
protected
|
||||
|
||||
def failed_strategy
|
||||
env["omniauth.failed_strategy"]
|
||||
env["omniauth.error.strategy"]
|
||||
end
|
||||
|
||||
def failure_message
|
||||
exception = env["omniauth.error"]
|
||||
error = exception.error_reason if exception.respond_to?(:error_reason)
|
||||
error ||= exception.error if exception.respond_to?(:error)
|
||||
error ||= env["omniauth.failure_key"]
|
||||
error ||= env["omniauth.error.type"].to_s
|
||||
error.to_s.humanize if error
|
||||
end
|
||||
|
||||
def after_omniauth_failure_path_for(scope)
|
||||
new_session_path(scope)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,10 +13,10 @@ class Devise::PasswordsController < ApplicationController
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :send_instructions
|
||||
redirect_to new_session_path(resource_name)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
else
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,10 +32,11 @@ class Devise::PasswordsController < ApplicationController
|
||||
self.resource = resource_class.reset_password_by_token(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :updated
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
set_flash_message(:notice, :updated) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
else
|
||||
render_with_scope :edit
|
||||
respond_with_navigational(resource){ render_with_scope :edit }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,26 +5,27 @@ 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/sign_up
|
||||
# POST /resource
|
||||
def create
|
||||
build_resource
|
||||
|
||||
if resource.save
|
||||
if resource.active?
|
||||
set_flash_message :notice, :signed_up
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
if resource.active_for_authentication?
|
||||
set_flash_message :notice, :signed_up if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
else
|
||||
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s
|
||||
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s if is_navigational_format?
|
||||
expire_session_data_after_sign_in!
|
||||
redirect_to after_inactive_sign_up_path_for(resource)
|
||||
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
|
||||
end
|
||||
else
|
||||
clean_up_passwords(resource)
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource) { render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,20 +37,21 @@ class Devise::RegistrationsController < ApplicationController
|
||||
# PUT /resource
|
||||
def update
|
||||
if resource.update_with_password(params[resource_name])
|
||||
set_flash_message :notice, :updated
|
||||
set_flash_message :notice, :updated if is_navigational_format?
|
||||
sign_in resource_name, resource, :bypass => true
|
||||
redirect_to after_update_path_for(resource)
|
||||
respond_with resource, :location => after_update_path_for(resource)
|
||||
else
|
||||
clean_up_passwords(resource)
|
||||
render_with_scope :edit
|
||||
respond_with_navigational(resource){ render_with_scope :edit }
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /resource
|
||||
def destroy
|
||||
resource.destroy
|
||||
sign_out_and_redirect(self.resource)
|
||||
set_flash_message :notice, :destroyed
|
||||
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
||||
set_flash_message :notice, :destroyed if is_navigational_format?
|
||||
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
|
||||
end
|
||||
|
||||
# GET /resource/cancel
|
||||
@@ -78,8 +80,8 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
|
||||
# Overwrite redirect_for_sign_in so it takes uses after_sign_up_path_for.
|
||||
def redirect_for_sign_in(scope, resource) #:nodoc:
|
||||
redirect_to stored_location_for(scope) || after_sign_up_path_for(resource)
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
stored_location_for(scope) || after_sign_up_path_for(resource)
|
||||
end
|
||||
|
||||
# The path used after sign up for inactive accounts. You need to overwrite
|
||||
@@ -104,7 +106,7 @@ class Devise::RegistrationsController < ApplicationController
|
||||
# We need to use a copy because we don't want actions like update changing
|
||||
# the current user in place.
|
||||
def authenticate_scope!
|
||||
send(:"authenticate_#{resource_name}!")
|
||||
send(:"authenticate_#{resource_name}!", true)
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,21 +4,42 @@ 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")
|
||||
set_flash_message :notice, :signed_in
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
end
|
||||
|
||||
# GET /resource/sign_out
|
||||
def destroy
|
||||
signed_in = signed_in?(resource_name)
|
||||
sign_out_and_redirect(resource_name)
|
||||
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
||||
set_flash_message :notice, :signed_out if signed_in
|
||||
|
||||
# We actually need to hardcode this, as Rails default responder doesn't
|
||||
# support returning empty response on GET request
|
||||
respond_to do |format|
|
||||
format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name) }
|
||||
format.all do
|
||||
method = "to_#{request_format}"
|
||||
text = {}.respond_to?(method) ? {}.send(method) : ""
|
||||
render :text => text, :status => :ok
|
||||
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
|
||||
@@ -13,10 +13,10 @@ class Devise::UnlocksController < ApplicationController
|
||||
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :send_instructions
|
||||
redirect_to new_session_path(resource_name)
|
||||
set_flash_message :notice, :send_instructions if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
else
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,10 +25,11 @@ class Devise::UnlocksController < ApplicationController
|
||||
self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :unlocked
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
set_flash_message :notice, :unlocked if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with_navigational(resource){ redirect_to redirect_location(resource_name, resource) }
|
||||
else
|
||||
render_with_scope :new
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
module DeviseHelper
|
||||
# A simple way to show error messages for the current devise resource. If you need
|
||||
# to customize this method, you can either overwrite it in your application helpers or
|
||||
# copy the views to your application.
|
||||
#
|
||||
# This method is intended to stay simple and it is unlikely that we are going to change
|
||||
# it to add more behavior or options.
|
||||
def devise_error_messages!
|
||||
return "" if resource.errors.empty?
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Additional translations at http://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
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"
|
||||
@@ -10,6 +13,7 @@ en:
|
||||
|
||||
devise:
|
||||
failure:
|
||||
already_authenticated: 'You are already signed in.'
|
||||
unauthenticated: 'You need to sign in or sign up before continuing.'
|
||||
unconfirmed: 'You have to confirm your account before continuing.'
|
||||
locked: 'Your account is locked.'
|
||||
|
||||
221
devise.gemspec
221
devise.gemspec
@@ -1,208 +1,25 @@
|
||||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||
# -*- encoding: utf-8 -*-
|
||||
$:.push File.expand_path("../lib", __FILE__)
|
||||
require "devise/version"
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{devise}
|
||||
s.version = "1.2.rc"
|
||||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
s.description = "Flexible authentication solution for Rails with Warden"
|
||||
s.authors = ['José Valim', 'Carlos Antônio']
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Jos\303\251 Valim", "Carlos Ant\303\264nio"]
|
||||
s.date = %q{2010-11-26}
|
||||
s.description = %q{Flexible authentication solution for Rails with Warden}
|
||||
s.email = %q{contact@plataformatec.com.br}
|
||||
s.extra_rdoc_files = [
|
||||
"CHANGELOG.rdoc",
|
||||
"MIT-LICENSE",
|
||||
"README.rdoc"
|
||||
]
|
||||
s.files = [
|
||||
"CHANGELOG.rdoc",
|
||||
"MIT-LICENSE",
|
||||
"README.rdoc",
|
||||
"app/controllers/devise/confirmations_controller.rb",
|
||||
"app/controllers/devise/omniauth_callbacks_controller.rb",
|
||||
"app/controllers/devise/passwords_controller.rb",
|
||||
"app/controllers/devise/registrations_controller.rb",
|
||||
"app/controllers/devise/sessions_controller.rb",
|
||||
"app/controllers/devise/unlocks_controller.rb",
|
||||
"app/helpers/devise_helper.rb",
|
||||
"app/mailers/devise/mailer.rb",
|
||||
"app/views/devise/confirmations/new.html.erb",
|
||||
"app/views/devise/mailer/confirmation_instructions.html.erb",
|
||||
"app/views/devise/mailer/reset_password_instructions.html.erb",
|
||||
"app/views/devise/mailer/unlock_instructions.html.erb",
|
||||
"app/views/devise/passwords/edit.html.erb",
|
||||
"app/views/devise/passwords/new.html.erb",
|
||||
"app/views/devise/registrations/edit.html.erb",
|
||||
"app/views/devise/registrations/new.html.erb",
|
||||
"app/views/devise/sessions/new.html.erb",
|
||||
"app/views/devise/shared/_links.erb",
|
||||
"app/views/devise/unlocks/new.html.erb",
|
||||
"config/locales/en.yml",
|
||||
"lib/devise.rb",
|
||||
"lib/devise/controllers/helpers.rb",
|
||||
"lib/devise/controllers/internal_helpers.rb",
|
||||
"lib/devise/controllers/scoped_views.rb",
|
||||
"lib/devise/controllers/url_helpers.rb",
|
||||
"lib/devise/encryptors/authlogic_sha512.rb",
|
||||
"lib/devise/encryptors/base.rb",
|
||||
"lib/devise/encryptors/clearance_sha1.rb",
|
||||
"lib/devise/encryptors/restful_authentication_sha1.rb",
|
||||
"lib/devise/encryptors/sha1.rb",
|
||||
"lib/devise/encryptors/sha512.rb",
|
||||
"lib/devise/failure_app.rb",
|
||||
"lib/devise/hooks/activatable.rb",
|
||||
"lib/devise/hooks/forgetable.rb",
|
||||
"lib/devise/hooks/rememberable.rb",
|
||||
"lib/devise/hooks/timeoutable.rb",
|
||||
"lib/devise/hooks/trackable.rb",
|
||||
"lib/devise/mapping.rb",
|
||||
"lib/devise/models.rb",
|
||||
"lib/devise/models/authenticatable.rb",
|
||||
"lib/devise/models/confirmable.rb",
|
||||
"lib/devise/models/database_authenticatable.rb",
|
||||
"lib/devise/models/encryptable.rb",
|
||||
"lib/devise/models/lockable.rb",
|
||||
"lib/devise/models/omniauthable.rb",
|
||||
"lib/devise/models/recoverable.rb",
|
||||
"lib/devise/models/registerable.rb",
|
||||
"lib/devise/models/rememberable.rb",
|
||||
"lib/devise/models/timeoutable.rb",
|
||||
"lib/devise/models/token_authenticatable.rb",
|
||||
"lib/devise/models/trackable.rb",
|
||||
"lib/devise/models/validatable.rb",
|
||||
"lib/devise/modules.rb",
|
||||
"lib/devise/omniauth.rb",
|
||||
"lib/devise/omniauth/config.rb",
|
||||
"lib/devise/omniauth/test_helpers.rb",
|
||||
"lib/devise/omniauth/url_helpers.rb",
|
||||
"lib/devise/orm/active_record.rb",
|
||||
"lib/devise/orm/mongoid.rb",
|
||||
"lib/devise/path_checker.rb",
|
||||
"lib/devise/rails.rb",
|
||||
"lib/devise/rails/routes.rb",
|
||||
"lib/devise/rails/warden_compat.rb",
|
||||
"lib/devise/schema.rb",
|
||||
"lib/devise/strategies/authenticatable.rb",
|
||||
"lib/devise/strategies/base.rb",
|
||||
"lib/devise/strategies/database_authenticatable.rb",
|
||||
"lib/devise/strategies/rememberable.rb",
|
||||
"lib/devise/strategies/token_authenticatable.rb",
|
||||
"lib/devise/test_helpers.rb",
|
||||
"lib/devise/version.rb",
|
||||
"lib/generators/active_record/devise_generator.rb",
|
||||
"lib/generators/active_record/templates/migration.rb",
|
||||
"lib/generators/devise/devise_generator.rb",
|
||||
"lib/generators/devise/install_generator.rb",
|
||||
"lib/generators/devise/orm_helpers.rb",
|
||||
"lib/generators/devise/views_generator.rb",
|
||||
"lib/generators/mongoid/devise_generator.rb",
|
||||
"lib/generators/templates/README",
|
||||
"lib/generators/templates/devise.rb"
|
||||
]
|
||||
s.homepage = %q{http://github.com/plataformatec/devise}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.rubyforge_project = "devise"
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.3.7}
|
||||
s.summary = %q{Flexible authentication solution for Rails with Warden}
|
||||
s.test_files = [
|
||||
"test/controllers/helpers_test.rb",
|
||||
"test/controllers/internal_helpers_test.rb",
|
||||
"test/controllers/url_helpers_test.rb",
|
||||
"test/devise_test.rb",
|
||||
"test/encryptors_test.rb",
|
||||
"test/failure_app_test.rb",
|
||||
"test/generators/generators_test_helper.rb",
|
||||
"test/generators/install_generator_test.rb",
|
||||
"test/generators/views_generator_test.rb",
|
||||
"test/integration/authenticatable_test.rb",
|
||||
"test/integration/confirmable_test.rb",
|
||||
"test/integration/database_authenticatable_test.rb",
|
||||
"test/integration/http_authenticatable_test.rb",
|
||||
"test/integration/lockable_test.rb",
|
||||
"test/integration/omniauthable_test.rb",
|
||||
"test/integration/recoverable_test.rb",
|
||||
"test/integration/registerable_test.rb",
|
||||
"test/integration/rememberable_test.rb",
|
||||
"test/integration/timeoutable_test.rb",
|
||||
"test/integration/token_authenticatable_test.rb",
|
||||
"test/integration/trackable_test.rb",
|
||||
"test/mailers/confirmation_instructions_test.rb",
|
||||
"test/mailers/reset_password_instructions_test.rb",
|
||||
"test/mailers/unlock_instructions_test.rb",
|
||||
"test/mapping_test.rb",
|
||||
"test/models/confirmable_test.rb",
|
||||
"test/models/database_authenticatable_test.rb",
|
||||
"test/models/encryptable_test.rb",
|
||||
"test/models/lockable_test.rb",
|
||||
"test/models/recoverable_test.rb",
|
||||
"test/models/rememberable_test.rb",
|
||||
"test/models/timeoutable_test.rb",
|
||||
"test/models/token_authenticatable_test.rb",
|
||||
"test/models/trackable_test.rb",
|
||||
"test/models/validatable_test.rb",
|
||||
"test/models_test.rb",
|
||||
"test/omniauth/url_helpers_test.rb",
|
||||
"test/orm/active_record.rb",
|
||||
"test/orm/mongoid.rb",
|
||||
"test/rails_app/app/active_record/admin.rb",
|
||||
"test/rails_app/app/active_record/shim.rb",
|
||||
"test/rails_app/app/active_record/user.rb",
|
||||
"test/rails_app/app/controllers/admins/sessions_controller.rb",
|
||||
"test/rails_app/app/controllers/admins_controller.rb",
|
||||
"test/rails_app/app/controllers/application_controller.rb",
|
||||
"test/rails_app/app/controllers/home_controller.rb",
|
||||
"test/rails_app/app/controllers/publisher/registrations_controller.rb",
|
||||
"test/rails_app/app/controllers/publisher/sessions_controller.rb",
|
||||
"test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb",
|
||||
"test/rails_app/app/controllers/users_controller.rb",
|
||||
"test/rails_app/app/helpers/application_helper.rb",
|
||||
"test/rails_app/app/mongoid/admin.rb",
|
||||
"test/rails_app/app/mongoid/shim.rb",
|
||||
"test/rails_app/app/mongoid/user.rb",
|
||||
"test/rails_app/config/application.rb",
|
||||
"test/rails_app/config/boot.rb",
|
||||
"test/rails_app/config/environment.rb",
|
||||
"test/rails_app/config/environments/development.rb",
|
||||
"test/rails_app/config/environments/production.rb",
|
||||
"test/rails_app/config/environments/test.rb",
|
||||
"test/rails_app/config/initializers/backtrace_silencers.rb",
|
||||
"test/rails_app/config/initializers/devise.rb",
|
||||
"test/rails_app/config/initializers/inflections.rb",
|
||||
"test/rails_app/config/initializers/secret_token.rb",
|
||||
"test/rails_app/config/routes.rb",
|
||||
"test/rails_app/db/migrate/20100401102949_create_tables.rb",
|
||||
"test/rails_app/db/schema.rb",
|
||||
"test/rails_app/lib/shared_admin.rb",
|
||||
"test/rails_app/lib/shared_user.rb",
|
||||
"test/routes_test.rb",
|
||||
"test/support/assertions.rb",
|
||||
"test/support/helpers.rb",
|
||||
"test/support/integration.rb",
|
||||
"test/support/webrat/integrations/rails.rb",
|
||||
"test/test_helper.rb",
|
||||
"test/test_helpers_test.rb"
|
||||
]
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_runtime_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_runtime_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
else
|
||||
s.add_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
end
|
||||
end
|
||||
|
||||
s.add_dependency("warden", "~> 1.0.3")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.3")
|
||||
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
|
||||
end
|
||||
@@ -1,3 +1,4 @@
|
||||
require 'rails'
|
||||
require 'active_support/core_ext/numeric/time'
|
||||
require 'active_support/dependencies'
|
||||
require 'orm_adapter'
|
||||
@@ -13,7 +14,9 @@ module Devise
|
||||
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
|
||||
|
||||
@@ -68,8 +71,9 @@ module Devise
|
||||
@@request_keys = []
|
||||
|
||||
# Keys that should be case-insensitive.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :case_insensitive_keys
|
||||
@@case_insensitive_keys = [ :email ]
|
||||
@@case_insensitive_keys = false
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -89,11 +93,11 @@ module Devise
|
||||
|
||||
# Email regex used to validate email formats. Adapted from authlogic.
|
||||
mattr_accessor :email_regexp
|
||||
@@email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
|
||||
@@email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
|
||||
# Range validation for password length
|
||||
mattr_accessor :password_length
|
||||
@@password_length = 6..20
|
||||
@@password_length = 6..128
|
||||
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
mattr_accessor :remember_for
|
||||
@@ -116,6 +120,10 @@ module Devise
|
||||
mattr_accessor :confirm_within
|
||||
@@confirm_within = 0.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
mattr_accessor :confirmation_keys
|
||||
@@confirmation_keys = [ :email ]
|
||||
|
||||
# Time interval to timeout the user session without activity.
|
||||
mattr_accessor :timeout_in
|
||||
@@timeout_in = 30.minutes
|
||||
@@ -143,6 +151,10 @@ module Devise
|
||||
mattr_accessor :lock_strategy
|
||||
@@lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
mattr_accessor :unlock_keys
|
||||
@@unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy can be used to unlock an account.
|
||||
# Values: :email, :time, :both
|
||||
mattr_accessor :unlock_strategy
|
||||
@@ -156,6 +168,14 @@ module Devise
|
||||
mattr_accessor :unlock_in
|
||||
@@unlock_in = 1.hour
|
||||
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
mattr_accessor :reset_password_keys
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key
|
||||
mattr_accessor :reset_password_within
|
||||
@@reset_password_within = nil
|
||||
|
||||
# The default scope which is used by warden.
|
||||
mattr_accessor :default_scope
|
||||
@@default_scope = nil
|
||||
@@ -173,10 +193,11 @@ module Devise
|
||||
@@stateless_token = false
|
||||
|
||||
# Which formats should be treated as navigational.
|
||||
# We need both :"*/*" and "*/*" to work on different Rails versions.
|
||||
mattr_accessor :navigational_formats
|
||||
@@navigational_formats = [:"*/*", :html]
|
||||
@@navigational_formats = [:"*/*", "*/*", :html]
|
||||
|
||||
# When set to true, signing out an user signs out all other scopes.
|
||||
# When set to true, signing out a user signs out all other scopes.
|
||||
mattr_accessor :sign_out_all_scopes
|
||||
@@sign_out_all_scopes = true
|
||||
|
||||
@@ -210,24 +231,30 @@ module Devise
|
||||
yield self
|
||||
end
|
||||
|
||||
def self.ref(arg)
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
ActiveSupport::Dependencies::Reference.store(arg)
|
||||
else
|
||||
ActiveSupport::Dependencies.ref(arg)
|
||||
end
|
||||
end
|
||||
|
||||
def self.omniauth_providers
|
||||
omniauth_configs.keys
|
||||
end
|
||||
|
||||
def self.cookie_domain=(value)
|
||||
ActiveSupport::Deprecation.warn "Devise.cookie_domain=(value) is deprecated. "
|
||||
"Please use Devise.cookie_options = { :domain => value } instead."
|
||||
self.cookie_options[:domain] = value
|
||||
end
|
||||
|
||||
# Get the mailer class from the mailer reference object.
|
||||
def self.mailer
|
||||
@@mailer_ref.get
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@@mailer_ref.get "Devise::Mailer"
|
||||
else
|
||||
@@mailer_ref.get
|
||||
end
|
||||
end
|
||||
|
||||
# Set the mailer reference object to access the mailer.
|
||||
def self.mailer=(class_name)
|
||||
@@mailer_ref = ActiveSupport::Dependencies.ref(class_name)
|
||||
@@mailer_ref = ref(class_name)
|
||||
end
|
||||
self.mailer = "Devise::Mailer"
|
||||
|
||||
@@ -291,7 +318,8 @@ module Devise
|
||||
|
||||
if options[:model]
|
||||
path = (options[:model] == true ? "devise/models/#{module_name}" : options[:model])
|
||||
Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, path)
|
||||
camelized = ActiveSupport::Inflector.camelize(module_name.to_s)
|
||||
Devise::Models.send(:autoload, camelized.to_sym, path)
|
||||
end
|
||||
|
||||
Devise::Mapping.add_module module_name
|
||||
@@ -357,7 +385,17 @@ module Devise
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
def self.friendly_token
|
||||
ActiveSupport::SecureRandom.base64(44).tr('+/=', 'xyz')
|
||||
ActiveSupport::SecureRandom.base64(15).tr('+/=', 'xyz')
|
||||
end
|
||||
|
||||
# constant-time comparison algorithm to prevent timing attacks
|
||||
def self.secure_compare(a, b)
|
||||
return false if a.blank? || b.blank? || a.bytesize != b.bytesize
|
||||
l = a.unpack "C#{a.bytesize}"
|
||||
|
||||
res = 0
|
||||
b.each_byte { |byte| res |= byte ^ l.shift }
|
||||
res == 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ module Devise
|
||||
# Generated methods:
|
||||
# authenticate_user! # Signs user in or redirect
|
||||
# authenticate_admin! # Signs admin in or redirect
|
||||
# user_signed_in? # Checks whether there is an user signed in or not
|
||||
# user_signed_in? # Checks whether there is a user signed in or not
|
||||
# admin_signed_in? # Checks whether there is an admin signed in or not
|
||||
# current_user # Current signed in user
|
||||
# current_admin # Current signed in admin
|
||||
@@ -36,8 +36,8 @@ module Devise
|
||||
mapping = mapping.name
|
||||
|
||||
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
||||
def authenticate_#{mapping}!
|
||||
warden.authenticate!(:scope => :#{mapping})
|
||||
def authenticate_#{mapping}!(force = false)
|
||||
warden.authenticate!(:scope => :#{mapping}) if !devise_controller? || force
|
||||
end
|
||||
|
||||
def #{mapping}_signed_in?
|
||||
@@ -72,19 +72,15 @@ module Devise
|
||||
false
|
||||
end
|
||||
|
||||
# Check if the given scope is signed in session, without running
|
||||
# authentication hooks.
|
||||
def signed_in?(scope)
|
||||
warden.authenticate?(:scope => scope)
|
||||
# Return true if the given scope is signed in session. If no scope given, return
|
||||
# true if any scope is signed in. Does not run authentication hooks.
|
||||
def signed_in?(scope=nil)
|
||||
[ scope || Devise.mappings.keys ].flatten.any? do |scope|
|
||||
warden.authenticate?(:scope => scope)
|
||||
end
|
||||
end
|
||||
|
||||
# Check if the any scope is signed in session, without running
|
||||
# authentication hooks.
|
||||
def anybody_signed_in?
|
||||
Devise.mappings.keys.any? { |scope| signed_in?(scope) }
|
||||
end
|
||||
|
||||
# Sign in an user that already was authenticated. This helper is useful for logging
|
||||
# Sign in a user that already was authenticated. This helper is useful for logging
|
||||
# users in after sign up.
|
||||
#
|
||||
# All options given to sign_in is passed forward to the set_user method in warden.
|
||||
@@ -108,12 +104,14 @@ module Devise
|
||||
|
||||
if options[:bypass]
|
||||
warden.session_serializer.store(resource, scope)
|
||||
elsif warden.user(scope) == resource && !options.delete(:force)
|
||||
# Do nothing. User already signed in and we are not forcing it.
|
||||
else
|
||||
warden.set_user(resource, options.merge!(:scope => scope))
|
||||
end
|
||||
end
|
||||
|
||||
# Sign out a given user or scope. This helper is useful for signing out an user
|
||||
# Sign out a given user or scope. This helper is useful for signing out a user
|
||||
# after deleting accounts.
|
||||
#
|
||||
# Examples:
|
||||
@@ -132,6 +130,7 @@ module Devise
|
||||
# Sign out all active users or scopes. This helper is useful for signing out all roles
|
||||
# in one click. This signs out ALL scopes in warden.
|
||||
def sign_out_all_scopes
|
||||
Devise.mappings.keys.each { |s| warden.user(s) }
|
||||
warden.raw_session.inspect
|
||||
warden.logout
|
||||
end
|
||||
@@ -180,7 +179,7 @@ module Devise
|
||||
respond_to?(home_path, true) ? send(home_path) : root_path
|
||||
end
|
||||
|
||||
# Method used by sessions controller to sign out an user. You can overwrite
|
||||
# Method used by sessions controller to sign out a user. You can overwrite
|
||||
# it in your ApplicationController to provide a custom hook for a custom
|
||||
# scope. Notice that differently from +after_sign_in_path_for+ this method
|
||||
# receives a symbol with the scope, and not the resource.
|
||||
@@ -190,36 +189,26 @@ module Devise
|
||||
root_path
|
||||
end
|
||||
|
||||
# Sign in an user and tries to redirect first to the stored location and
|
||||
# Sign in a user and tries to redirect first to the stored location and
|
||||
# then to the url specified by after_sign_in_path_for. It accepts the same
|
||||
# parameters as the sign_in method.
|
||||
def sign_in_and_redirect(resource_or_scope, *args)
|
||||
options = args.extract_options!
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
resource = args.last || resource_or_scope
|
||||
|
||||
if warden.user(scope) == resource
|
||||
expire_session_data_after_sign_in!
|
||||
else
|
||||
sign_in(scope, resource, options)
|
||||
end
|
||||
|
||||
redirect_for_sign_in(scope, resource)
|
||||
sign_in(scope, resource, options)
|
||||
redirect_to redirect_location(scope, resource)
|
||||
end
|
||||
|
||||
def redirect_for_sign_in(scope, resource) #:nodoc:
|
||||
redirect_to stored_location_for(scope) || after_sign_in_path_for(resource)
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
stored_location_for(scope) || after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
# Sign out an user and tries to redirect to the url specified by
|
||||
# Sign out a user and tries to redirect to the url specified by
|
||||
# after_sign_out_path_for.
|
||||
def sign_out_and_redirect(resource_or_scope)
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
Devise.sign_out_all_scopes ? sign_out : sign_out(scope)
|
||||
redirect_for_sign_out(scope)
|
||||
end
|
||||
|
||||
def redirect_for_sign_out(scope) #:nodoc:
|
||||
redirect_to after_sign_out_path_for(scope)
|
||||
end
|
||||
|
||||
@@ -228,6 +217,12 @@ module Devise
|
||||
def expire_session_data_after_sign_in!
|
||||
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
||||
end
|
||||
|
||||
# Overwrite Rails' handle unverified request to sign out all scopes.
|
||||
def handle_unverified_request
|
||||
sign_out_all_scopes
|
||||
super # call the default behaviour which resets the session
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ module Devise
|
||||
module InternalHelpers #:nodoc:
|
||||
extend ActiveSupport::Concern
|
||||
include Devise::Controllers::ScopedViews
|
||||
include Devise::Controllers::SharedHelpers
|
||||
|
||||
included do
|
||||
helper DeviseHelper
|
||||
@@ -16,7 +17,7 @@ module Devise
|
||||
helper_method *helpers
|
||||
|
||||
prepend_before_filter :is_devise_resource?
|
||||
skip_before_filter *Devise.mappings.keys.map { |m| :"authenticate_#{m}!" }
|
||||
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
|
||||
end
|
||||
|
||||
# Gets the actual resource stored in the instance variable
|
||||
@@ -54,7 +55,19 @@ module Devise
|
||||
|
||||
# Checks whether it's a devise mapped resource or not.
|
||||
def is_devise_resource? #:nodoc:
|
||||
unknown_action!("Could not find devise mapping for path #{request.fullpath.inspect}") unless devise_mapping
|
||||
unknown_action! <<-MESSAGE unless devise_mapping
|
||||
Could not find devise mapping for path #{request.fullpath.inspect}.
|
||||
Maybe you forgot to wrap your route inside the scope block? For example:
|
||||
|
||||
devise_scope :user do
|
||||
match "/some/route" => "some_devise_controller"
|
||||
end
|
||||
MESSAGE
|
||||
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] }
|
||||
end
|
||||
|
||||
def unknown_action!(msg)
|
||||
@@ -80,6 +93,7 @@ module Devise
|
||||
def require_no_authentication
|
||||
if warden.authenticated?(resource_name)
|
||||
resource = warden.user(resource_name)
|
||||
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
end
|
||||
@@ -109,6 +123,12 @@ module Devise
|
||||
def clean_up_passwords(object) #:nodoc:
|
||||
object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
|
||||
end
|
||||
|
||||
def respond_with_navigational(*args, &block)
|
||||
respond_with(*args) do |format|
|
||||
format.any(*navigational_formats, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
52
lib/devise/controllers/rememberable.rb
Normal file
52
lib/devise/controllers/rememberable.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
module Devise
|
||||
module Controllers
|
||||
# A module that may be optionally included in a controller in order
|
||||
# to provide remember me behavior.
|
||||
module Rememberable
|
||||
# Return default cookie values retrieved from session options.
|
||||
def self.cookie_values
|
||||
Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
end
|
||||
|
||||
# A small warden proxy so we can remember and forget uses from hooks.
|
||||
class Proxy #:nodoc:
|
||||
include Devise::Controllers::Rememberable
|
||||
|
||||
delegate :cookies, :env, :to => :@warden
|
||||
|
||||
def initialize(warden)
|
||||
@warden = warden
|
||||
end
|
||||
end
|
||||
|
||||
# Remembers the given resource by setting up a cookie
|
||||
def remember_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.remember_me!(resource.extend_remember_period)
|
||||
cookies.signed["remember_#{scope}_token"] = remember_cookie_values(resource)
|
||||
end
|
||||
|
||||
# Forgets the given resource by deleting a cookie
|
||||
def forget_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.forget_me! unless resource.frozen?
|
||||
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def forget_cookie_values(resource)
|
||||
Devise::Controllers::Rememberable.cookie_values.merge!(resource.cookie_options)
|
||||
end
|
||||
|
||||
def remember_cookie_values(resource)
|
||||
options = { :httponly => true }
|
||||
options.merge!(forget_cookie_values(resource))
|
||||
options.merge!(
|
||||
:value => resource.class.serialize_into_cookie(resource),
|
||||
:expires => resource.remember_expires_at
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
@@ -4,7 +4,7 @@ module Devise
|
||||
module Encryptors
|
||||
# = AuthlogicSha512
|
||||
# Simulates Authlogic's default encryption mechanism.
|
||||
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to silumate
|
||||
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to simulate
|
||||
# the default behavior.
|
||||
class AuthlogicSha512 < Base
|
||||
# Gererates a default password digest based on salt, pepper and the
|
||||
|
||||
@@ -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,7 +65,11 @@ module Devise
|
||||
end
|
||||
|
||||
def redirect_url
|
||||
send(:"new_#{scope}_session_path")
|
||||
if request_format == :html
|
||||
send(:"new_#{scope}_session_path")
|
||||
else
|
||||
send(:"new_#{scope}_session_path", :format => request_format)
|
||||
end
|
||||
end
|
||||
|
||||
# Choose whether we should respond in a http authentication fashion,
|
||||
@@ -79,7 +84,7 @@ module Devise
|
||||
if request.xhr?
|
||||
Devise.http_authenticatable_on_xhr
|
||||
else
|
||||
!(request.format && Devise.navigational_formats.include?(request.format.to_sym))
|
||||
!(request_format && is_navigational_format?)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -90,14 +95,22 @@ module Devise
|
||||
end
|
||||
|
||||
def http_auth_body
|
||||
return i18n_message unless request.format
|
||||
method = "to_#{request.format.to_sym}"
|
||||
{}.respond_to?(method) ? { :error => i18n_message }.send(method) : i18n_message
|
||||
return i18n_message unless request_format
|
||||
method = "to_#{request_format}"
|
||||
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)
|
||||
controller, action = app.split("#")
|
||||
"#{controller.camelize}Controller".constantize.action(action)
|
||||
controller_name = ActiveSupport::Inflector.camelize(controller)
|
||||
controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
|
||||
controller_klass.action(action)
|
||||
end
|
||||
|
||||
def warden
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Deny user access whenever his account is not active yet. All strategies that inherits from
|
||||
# Devise::Strategies::Authenticatable and uses the validate already check if the user is active?
|
||||
# Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
|
||||
# before actively signing him in. However, we need this as hook to validate the user activity
|
||||
# in each request and in case the user is using other strategies beside Devise ones.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
if record && record.respond_to?(:active?) && !record.active?
|
||||
if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
|
||||
scope = options[:scope]
|
||||
warden.logout(scope)
|
||||
throw :warden, :scope => scope, :message => record.inactive_message
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
# This avoids forgetting deleted users.
|
||||
Warden::Manager.before_logout do |record, warden, options|
|
||||
if record.respond_to?(:forget_me!)
|
||||
record.forget_me! unless record.frozen?
|
||||
cookie_options = Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
cookie_options.merge!(record.cookie_options)
|
||||
warden.cookies.delete("remember_#{options[:scope]}_token", cookie_options)
|
||||
Devise::Controllers::Rememberable::Proxy.new(warden).forget_me(record)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,45 +1,6 @@
|
||||
module Devise
|
||||
module Hooks
|
||||
# Overwrite success! in authentication strategies allowing users to be remembered.
|
||||
# We choose to implement this as an strategy hook instead of a warden hook to allow a specific
|
||||
# strategy (like token authenticatable or facebook authenticatable) to turn off remember_me?
|
||||
# cookies.
|
||||
module Rememberable #:nodoc:
|
||||
def success!(resource)
|
||||
super
|
||||
|
||||
if succeeded? && resource.respond_to?(:remember_me!) && remember_me?
|
||||
resource.remember_me!(extend_remember_period?)
|
||||
cookies.signed["remember_#{scope}_token"] = cookie_values(resource)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def cookie_values(resource)
|
||||
options = Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
options.merge!(resource.cookie_options)
|
||||
options.merge!(
|
||||
:value => resource.class.serialize_into_cookie(resource),
|
||||
:expires => resource.remember_expires_at
|
||||
)
|
||||
options
|
||||
end
|
||||
|
||||
def succeeded?
|
||||
@result == :success
|
||||
end
|
||||
|
||||
def extend_remember_period?
|
||||
false
|
||||
end
|
||||
|
||||
def remember_me?
|
||||
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
||||
end
|
||||
end
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
|
||||
Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
|
||||
end
|
||||
end
|
||||
|
||||
Devise::Strategies::Authenticatable.send :include, Devise::Hooks::Rememberable
|
||||
|
||||
end
|
||||
@@ -6,7 +6,7 @@
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope)
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
|
||||
last_request_at = warden.session(scope)['last_request_at']
|
||||
|
||||
if record.timedout?(last_request_at)
|
||||
|
||||
@@ -50,7 +50,7 @@ module Devise
|
||||
@singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
|
||||
|
||||
@class_name = (options[:class_name] || name.to_s.classify).to_s
|
||||
@ref = ActiveSupport::Dependencies.ref(@class_name)
|
||||
@ref = Devise.ref(@class_name)
|
||||
|
||||
@path = (options[:path] || name).to_s
|
||||
@path_prefix = options[:path_prefix]
|
||||
@@ -73,7 +73,11 @@ module Devise
|
||||
|
||||
# Gives the class the mapping points to.
|
||||
def to
|
||||
@ref.get
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@ref.get @class_name
|
||||
else
|
||||
@ref.get
|
||||
end
|
||||
end
|
||||
|
||||
def strategies
|
||||
|
||||
@@ -2,7 +2,7 @@ module Devise
|
||||
module Models
|
||||
# Creates configuration values for Devise and for the given module.
|
||||
#
|
||||
# Devise::Models.config(Devise::Authenticable, :stretches, 10)
|
||||
# Devise::Models.config(Devise::Authenticatable, :stretches, 10)
|
||||
#
|
||||
# The line above creates:
|
||||
#
|
||||
@@ -17,6 +17,9 @@ module Devise
|
||||
# inside the given class.
|
||||
#
|
||||
def self.config(mod, *accessors) #:nodoc:
|
||||
(class << mod; self; end).send :attr_accessor, :available_configs
|
||||
mod.available_configs = accessors
|
||||
|
||||
accessors.each do |accessor|
|
||||
mod.class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
||||
def #{accessor}
|
||||
@@ -46,11 +49,33 @@ module Devise
|
||||
#
|
||||
def devise(*modules)
|
||||
include Devise::Models::Authenticatable
|
||||
options = modules.extract_options!
|
||||
self.devise_modules += Devise::ALL & modules.map(&:to_sym).uniq
|
||||
options = modules.extract_options!.dup
|
||||
|
||||
selected_modules = modules.map(&:to_sym).uniq.sort_by do |s|
|
||||
Devise::ALL.index(s) || -1 # follow Devise::ALL order
|
||||
end
|
||||
|
||||
devise_modules_hook! do
|
||||
devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) }
|
||||
selected_modules.each do |m|
|
||||
mod = Devise::Models.const_get(m.to_s.classify)
|
||||
|
||||
if mod.const_defined?("ClassMethods")
|
||||
class_mod = mod.const_get("ClassMethods")
|
||||
extend class_mod
|
||||
|
||||
if class_mod.respond_to?(:available_configs)
|
||||
available_configs = class_mod.available_configs
|
||||
available_configs.each do |config|
|
||||
next unless options.key?(config)
|
||||
send(:"#{config}=", options.delete(config))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include mod
|
||||
end
|
||||
|
||||
self.devise_modules |= selected_modules
|
||||
options.each { |key, value| send(:"#{key}=", value) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'devise/hooks/activatable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Authenticable module. Holds common settings for authentication.
|
||||
# Authenticatable module. Holds common settings for authentication.
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
@@ -24,19 +24,19 @@ module Devise
|
||||
# * +params_authenticatable+: if this model allows authentication through request params. By default true.
|
||||
# It also accepts an array specifying the strategies that should allow params authentication.
|
||||
#
|
||||
# == Active?
|
||||
# == active_for_authentication?
|
||||
#
|
||||
# Before authenticating an user and in each request, Devise checks if your model is active by
|
||||
# calling model.active?. This method is overwriten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active? to only return true if your model was confirmed.
|
||||
# Before authenticating a user and in each request, Devise checks if your model is active by
|
||||
# calling model.active_for_authentication?. This method is overwriten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
|
||||
#
|
||||
# You overwrite this method yourself, but if you do, don't forget to call super:
|
||||
#
|
||||
# def active?
|
||||
# def active_for_authentication?
|
||||
# super && special_condition_is_valid?
|
||||
# end
|
||||
#
|
||||
# Whenever active? returns false, Devise asks the reason why your model is inactive using
|
||||
# Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using
|
||||
# the inactive_message method. You can overwrite it as well:
|
||||
#
|
||||
# def inactive_message
|
||||
@@ -55,17 +55,17 @@ module Devise
|
||||
# find_for_authentication are the methods used in a Warden::Strategy to check
|
||||
# if a model should be signed in or not.
|
||||
#
|
||||
# However, you should not overwrite this method, you should overwrite active? and
|
||||
# inactive_message instead.
|
||||
# However, you should not overwrite this method, you should overwrite active_for_authentication?
|
||||
# and inactive_message instead.
|
||||
def valid_for_authentication?
|
||||
if active?
|
||||
if active_for_authentication?
|
||||
block_given? ? yield : true
|
||||
else
|
||||
inactive_message
|
||||
end
|
||||
end
|
||||
|
||||
def active?
|
||||
def active_for_authentication?
|
||||
true
|
||||
end
|
||||
|
||||
@@ -76,6 +76,19 @@ module Devise
|
||||
def authenticatable_salt
|
||||
end
|
||||
|
||||
%w(to_xml to_json).each do |method|
|
||||
class_eval <<-RUBY, __FILE__, __LINE__
|
||||
def #{method}(options={})
|
||||
if self.class.respond_to?(:accessible_attributes)
|
||||
options = { :only => self.class.accessible_attributes.to_a }.merge(options || {})
|
||||
super(options)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
||||
|
||||
@@ -100,7 +113,8 @@ module Devise
|
||||
# end
|
||||
#
|
||||
def find_for_authentication(conditions)
|
||||
case_insensitive_keys.each { |k| conditions[k].try(:downcase!) }
|
||||
filter_auth_params(conditions)
|
||||
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
||||
to_adapter.find_first(conditions)
|
||||
end
|
||||
|
||||
@@ -111,13 +125,13 @@ 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!) }
|
||||
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
||||
|
||||
attributes = attributes.slice(*required_attributes)
|
||||
attributes.delete_if { |key, value| value.blank? }
|
||||
|
||||
if attributes.size == required_attributes.size
|
||||
record = to_adapter.find_first(attributes)
|
||||
record = to_adapter.find_first(filter_auth_params(attributes))
|
||||
end
|
||||
|
||||
unless record
|
||||
@@ -133,6 +147,15 @@ module Devise
|
||||
record
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# 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
|
||||
end if conditions.is_a?(Hash)
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def generate_token(column)
|
||||
loop do
|
||||
|
||||
@@ -55,11 +55,11 @@ module Devise
|
||||
unless_confirmed { send_confirmation_instructions }
|
||||
end
|
||||
|
||||
# Overwrites active? from Devise::Models::Activatable for confirmation
|
||||
# by verifying whether an user is active to sign in or not. If the user
|
||||
# Overwrites active_for_authentication? for confirmation
|
||||
# by verifying whether a user is active to sign in or not. If the user
|
||||
# is already confirmed, it should never be blocked. Otherwise we need to
|
||||
# calculate if the confirm time has not expired for this user.
|
||||
def active?
|
||||
def active_for_authentication?
|
||||
super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
|
||||
end
|
||||
|
||||
@@ -84,7 +84,7 @@ module Devise
|
||||
# Checks if the confirmation for the user is within the limit time.
|
||||
# We do this by calculating if the difference between today and the
|
||||
# confirmation sent date does not exceed the confirm in time configured.
|
||||
# Confirm_in is a model configuration, must always be an integer value.
|
||||
# Confirm_within is a model configuration, must always be an integer value.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
@@ -133,7 +133,7 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
def send_confirmation_instructions(attributes={})
|
||||
confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
|
||||
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
||||
confirmable.resend_confirmation_token if confirmable.persisted?
|
||||
confirmable
|
||||
end
|
||||
@@ -153,7 +153,7 @@ module Devise
|
||||
generate_token(:confirmation_token)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :confirm_within)
|
||||
Devise::Models.config(self, :confirm_within, :confirmation_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'bcrypt'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Authenticable Module, responsible for encrypting password and validating
|
||||
# Authenticatable Module, responsible for encrypting password and validating
|
||||
# authenticity of a user while signing in.
|
||||
#
|
||||
# == Options
|
||||
@@ -22,7 +22,7 @@ module Devise
|
||||
included do
|
||||
attr_reader :password, :current_password
|
||||
attr_accessor :password_confirmation
|
||||
before_save :downcase_keys
|
||||
before_validation :downcase_keys
|
||||
end
|
||||
|
||||
# Generates password encryption based on the given value.
|
||||
@@ -31,14 +31,17 @@ module Devise
|
||||
self.encrypted_password = password_digest(@password) if @password.present?
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
# Verifies whether an password (ie from sign in) is the user password.
|
||||
def valid_password?(password)
|
||||
::BCrypt::Password.new(self.encrypted_password) == "#{password}#{self.class.pepper}"
|
||||
return false if encrypted_password.blank?
|
||||
bcrypt = ::BCrypt::Password.new(self.encrypted_password)
|
||||
password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
|
||||
Devise.secure_compare(password, self.encrypted_password)
|
||||
end
|
||||
|
||||
# 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
|
||||
@@ -76,7 +79,7 @@ module Devise
|
||||
|
||||
# Downcase case-insensitive keys
|
||||
def downcase_keys
|
||||
self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) }
|
||||
(self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
# Digests the password using bcrypt.
|
||||
|
||||
@@ -36,7 +36,7 @@ module Devise
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
password_digest(incoming_password) == self.encrypted_password
|
||||
Devise.secure_compare(password_digest(incoming_password), self.encrypted_password)
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -53,7 +53,14 @@ module Devise
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
@encryptor_class ||= case encryptor
|
||||
when :bcrypt
|
||||
raise "In order to use bcrypt as encryptor, simply remove :encryptable from your devise model"
|
||||
when nil
|
||||
raise "You need to give an :encryptor as option in order to use :encryptable"
|
||||
else
|
||||
::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
end
|
||||
end
|
||||
|
||||
def password_salt
|
||||
|
||||
@@ -15,13 +15,14 @@ module Devise
|
||||
# * +lock_strategy+: lock the user account by :failed_attempts or :none.
|
||||
# * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
|
||||
# * +unlock_in+: the time you want to lock the user after to lock happens. Only available when unlock_strategy is :time or :both.
|
||||
# * +unlock_keys+: the keys you want to use when locking and unlocking an account
|
||||
#
|
||||
module Lockable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
|
||||
|
||||
# Lock an user setting it's locked_at to actual time.
|
||||
# Lock a user setting it's locked_at to actual time.
|
||||
def lock_access!
|
||||
self.locked_at = Time.now
|
||||
|
||||
@@ -33,14 +34,12 @@ module Devise
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Unlock an user by cleaning locket_at and failed_attempts.
|
||||
# Unlock a user by cleaning locket_at and failed_attempts.
|
||||
def unlock_access!
|
||||
if_access_locked do
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
self.unlock_token = nil if respond_to?(:unlock_token=)
|
||||
save(:validate => false)
|
||||
end
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
self.unlock_token = nil if respond_to?(:unlock_token=)
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Verifies whether a user is locked or not.
|
||||
@@ -58,9 +57,9 @@ module Devise
|
||||
if_access_locked { send_unlock_instructions }
|
||||
end
|
||||
|
||||
# Overwrites active? from Devise::Models::Activatable for locking purposes
|
||||
# by verifying whether an user is active to sign in or not based on locked?
|
||||
def active?
|
||||
# Overwrites active_for_authentication? from Devise::Models::Activatable for locking purposes
|
||||
# by verifying whether a user is active to sign in or not based on locked?
|
||||
def active_for_authentication?
|
||||
super && !access_locked?
|
||||
end
|
||||
|
||||
@@ -71,16 +70,21 @@ module Devise
|
||||
end
|
||||
|
||||
# Overwrites valid_for_authentication? from Devise::Models::Authenticatable
|
||||
# for verifying whether an user is allowed to sign in or not. If the user
|
||||
# for verifying whether a user is allowed to sign in or not. If the user
|
||||
# is locked, it should never be allowed.
|
||||
def valid_for_authentication?
|
||||
return super unless persisted? && lock_strategy_enabled?(:failed_attempts)
|
||||
|
||||
# Unlock the user if the lock is expired, no matter
|
||||
# if the user can login or not (wrong password, etc)
|
||||
unlock_access! if lock_expired?
|
||||
|
||||
case (result = super)
|
||||
when Symbol
|
||||
return result
|
||||
when TrueClass
|
||||
self.failed_attempts = 0
|
||||
save(:validate => false)
|
||||
when FalseClass
|
||||
# PostgreSQL uses nil as the default value for integer columns set to 0
|
||||
self.failed_attempts ||= 0
|
||||
@@ -88,10 +92,11 @@ module Devise
|
||||
if attempts_exceeded?
|
||||
lock_access!
|
||||
return :locked
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
save(:validate => false) if changed?
|
||||
result
|
||||
end
|
||||
|
||||
@@ -132,7 +137,7 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
def send_unlock_instructions(attributes={})
|
||||
lockable = find_or_initialize_with_errors(authentication_keys, attributes, :not_found)
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
end
|
||||
@@ -161,7 +166,7 @@ module Devise
|
||||
Devise.friendly_token
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in)
|
||||
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in, :unlock_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,12 @@ module Devise
|
||||
|
||||
# Recoverable takes care of reseting the user password and send reset instructions.
|
||||
#
|
||||
# ==Options
|
||||
#
|
||||
# Recoverable adds the following options to devise_for:
|
||||
#
|
||||
# * +reset_password_keys+: the keys you want to use when recovering the password for an account
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# # resets the user password and save the record, true if valid passwords are given, otherwise false
|
||||
@@ -29,15 +35,46 @@ module Devise
|
||||
|
||||
# Resets reset password token and send reset password instructions by email
|
||||
def send_reset_password_instructions
|
||||
generate_reset_password_token!
|
||||
generate_reset_password_token! if should_generate_token?
|
||||
::Devise.mailer.reset_password_instructions(self).deliver
|
||||
end
|
||||
|
||||
# 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 ressource is not responding to reset_password_sent_at at all.
|
||||
# reset_password_within is a model configuration, must always be an integer value.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# # reset_password_within = 1.day and reset_password_sent_at = today
|
||||
# reset_password_period_valid? # returns true
|
||||
#
|
||||
# # reset_password_within = 5.days and reset_password_sent_at = 4.days.ago
|
||||
# reset_password_period_valid? # returns true
|
||||
#
|
||||
# # reset_password_within = 5.days and reset_password_sent_at = 5.days.ago
|
||||
# reset_password_period_valid? # returns false
|
||||
#
|
||||
# # reset_password_within = 0.days
|
||||
# reset_password_period_valid? # will always return false
|
||||
#
|
||||
def reset_password_period_valid?
|
||||
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
|
||||
|
||||
def should_generate_token?
|
||||
reset_password_token.nil? || !reset_password_period_valid?
|
||||
end
|
||||
|
||||
# Generates a new random token for reset password
|
||||
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
|
||||
@@ -49,6 +86,7 @@ module Devise
|
||||
# Removes reset_password token
|
||||
def clear_reset_password_token
|
||||
self.reset_password_token = nil
|
||||
self.reset_password_sent_at = nil if respond_to?(:reset_password_sent_at=)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
@@ -57,7 +95,7 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Attributes must contain the user email
|
||||
def send_reset_password_instructions(attributes={})
|
||||
recoverable = find_or_initialize_with_errors(authentication_keys, attributes, :not_found)
|
||||
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
|
||||
recoverable.send_reset_password_instructions if recoverable.persisted?
|
||||
recoverable
|
||||
end
|
||||
@@ -67,16 +105,24 @@ module Devise
|
||||
generate_token(:reset_password_token)
|
||||
end
|
||||
|
||||
# Attempt to find a user by it's reset_password_token to reset it's
|
||||
# password. If a user is found, reset it's password and automatically
|
||||
# Attempt to find a user by it's reset_password_token to reset its
|
||||
# password. If a user is found and token is still valid, reset its password and automatically
|
||||
# try saving the record. If not user is found, returns a new user
|
||||
# containing an error in reset_password_token attribute.
|
||||
# Attributes must contain reset_password_token, password and confirmation
|
||||
def reset_password_by_token(attributes={})
|
||||
recoverable = find_or_initialize_with_error_by(:reset_password_token, attributes[:reset_password_token])
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation]) if recoverable.persisted?
|
||||
if recoverable.persisted?
|
||||
if recoverable.reset_password_period_valid?
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
||||
else
|
||||
recoverable.errors.add(:reset_password_token, :expired)
|
||||
end
|
||||
end
|
||||
recoverable
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :reset_password_keys, :reset_password_within)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Devise
|
||||
|
||||
module ClassMethods
|
||||
# A convenience method that receives both parameters and session to
|
||||
# initialize an user. This can be used by OAuth, for example, to send
|
||||
# initialize a user. This can be used by OAuth, for example, to send
|
||||
# in the user token and be stored on initialization.
|
||||
#
|
||||
# By default discards all information sent by the session by calling
|
||||
|
||||
@@ -44,10 +44,7 @@ module Devise
|
||||
module Rememberable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Remember me option available in after_authentication hook.
|
||||
attr_accessor :remember_me
|
||||
end
|
||||
attr_accessor :remember_me, :extend_remember_period
|
||||
|
||||
# Generate a new remember token and save the record without validations
|
||||
# unless remember_across_browsers is true and the user already has a valid token.
|
||||
@@ -60,7 +57,7 @@ module Devise
|
||||
# Removes the remember token only if it exists, and save the record
|
||||
# without validations.
|
||||
def forget_me!
|
||||
self.remember_token = nil if respond_to?(:remember_token)
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# TokenAuthenticable adds the following options to devise_for:
|
||||
# TokenAuthenticatable adds the following options to devise_for:
|
||||
#
|
||||
# * +token_authentication_key+: Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
|
||||
#
|
||||
@@ -38,17 +38,17 @@ module Devise
|
||||
# Generate new authentication token and save the record.
|
||||
def reset_authentication_token!
|
||||
reset_authentication_token
|
||||
self.save(:validate => false)
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists.
|
||||
def ensure_authentication_token
|
||||
self.reset_authentication_token if self.authentication_token.blank?
|
||||
reset_authentication_token if authentication_token.blank?
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists and save the record.
|
||||
def ensure_authentication_token!
|
||||
self.reset_authentication_token! if self.authentication_token.blank?
|
||||
reset_authentication_token! if authentication_token.blank?
|
||||
end
|
||||
|
||||
# Hook called after token authentication.
|
||||
|
||||
@@ -10,7 +10,7 @@ module Devise
|
||||
# Validatable adds the following options to devise_for:
|
||||
#
|
||||
# * +email_regexp+: the regular expression used to validate e-mails;
|
||||
# * +password_length+: a range expressing password length. Defaults to 6..20.
|
||||
# * +password_length+: a range expressing password length. Defaults to 6..128.
|
||||
#
|
||||
module Validatable
|
||||
# All validations used by this module.
|
||||
@@ -23,8 +23,7 @@ module Devise
|
||||
|
||||
base.class_eval do
|
||||
validates_presence_of :email, :if => :email_required?
|
||||
validates_uniqueness_of :email, :scope => authentication_keys[1..-1],
|
||||
:case_sensitive => case_insensitive_keys.exclude?(:email), :allow_blank => true
|
||||
validates_uniqueness_of :email, :case_sensitive => (case_insensitive_keys != false), :allow_blank => true
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true
|
||||
|
||||
with_options :if => :password_required? do |v|
|
||||
|
||||
@@ -5,39 +5,24 @@ rescue LoadError => e
|
||||
raise
|
||||
end
|
||||
|
||||
module OmniAuth
|
||||
# TODO HAXES Backport to OmniAuth
|
||||
module Strategy #:nodoc:
|
||||
def initialize(app, name, *args)
|
||||
@app = app
|
||||
@name = name.to_sym
|
||||
@options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
def fail!(message_key, exception = nil)
|
||||
self.env['omniauth.error'] = exception
|
||||
self.env['omniauth.failure_key'] = message_key
|
||||
self.env['omniauth.failed_strategy'] = self
|
||||
OmniAuth.config.on_failure.call(self.env, message_key.to_sym)
|
||||
end
|
||||
end
|
||||
unless OmniAuth.config.respond_to? :test_mode
|
||||
raise "You are using an old OmniAuth version, please ensure you have 0.2.0.beta version or later installed."
|
||||
end
|
||||
|
||||
# Clean up the default path_prefix. It will be automatically set by Devise.
|
||||
OmniAuth.config.path_prefix = nil
|
||||
|
||||
OmniAuth.config.on_failure = Proc.new do |env, key|
|
||||
OmniAuth.config.on_failure = Proc.new do |env|
|
||||
env['devise.mapping'] = Devise::Mapping.find_by_path!(env['PATH_INFO'], :path)
|
||||
controller_klass = "#{env['devise.mapping'].controllers[:omniauth_callbacks].camelize}Controller"
|
||||
controller_klass.constantize.action(:failure).call(env)
|
||||
controller_name = ActiveSupport::Inflector.camelize(env['devise.mapping'].controllers[:omniauth_callbacks])
|
||||
controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
|
||||
controller_klass.action(:failure).call(env)
|
||||
end
|
||||
|
||||
module Devise
|
||||
module OmniAuth
|
||||
autoload :Config, "devise/omniauth/config"
|
||||
autoload :UrlHelpers, "devise/omniauth/url_helpers"
|
||||
autoload :TestHelpers, "devise/omniauth/test_helpers"
|
||||
|
||||
class << self
|
||||
delegate :short_circuit_authorizers!, :unshort_circuit_authorizers!,
|
||||
|
||||
@@ -13,18 +13,6 @@ module Devise
|
||||
def strategy_class
|
||||
::OmniAuth::Strategies.const_get("#{::OmniAuth::Utils.camelize(@provider.to_s)}")
|
||||
end
|
||||
|
||||
def check_if_allow_stubs!
|
||||
raise "OmniAuth strategy for #{@provider} does not allow stubs, only OAuth2 ones do." unless allow_stubs?
|
||||
end
|
||||
|
||||
def allow_stubs?
|
||||
defined?(::OmniAuth::Strategies::OAuth2) && strategy.is_a?(::OmniAuth::Strategies::OAuth2)
|
||||
end
|
||||
|
||||
def build_connection(&block)
|
||||
strategy.client.connection.build(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,57 +0,0 @@
|
||||
module Devise
|
||||
module OmniAuth
|
||||
module TestHelpers
|
||||
def self.test_mode!
|
||||
Faraday.default_adapter = :test if defined?(Faraday)
|
||||
ActiveSupport.on_load(:action_controller) { include Devise::OmniAuth::TestHelpers }
|
||||
ActiveSupport.on_load(:action_view) { include Devise::OmniAuth::TestHelpers }
|
||||
end
|
||||
|
||||
def self.stub!(provider, stubs=nil, &block)
|
||||
raise "You either need to pass stubs as a block or as a parameter" unless block_given? || stubs
|
||||
|
||||
config = Devise.omniauth_configs[provider]
|
||||
raise "Could not find configuration for #{provider.to_s} omniauth provider" unless config
|
||||
|
||||
config.check_if_allow_stubs!
|
||||
stubs ||= Faraday::Adapter::Test::Stubs.new(&block)
|
||||
|
||||
config.build_connection do |b|
|
||||
b.adapter :test, stubs
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset_stubs!(*providers)
|
||||
target = providers.any? ? Devise.omniauth_configs.slice(*providers) : Devise.omniauth_configs
|
||||
target.each_value do |config|
|
||||
next unless config.allow_stubs?
|
||||
config.build_connection { |b| b.adapter Faraday.default_adapter }
|
||||
end
|
||||
end
|
||||
|
||||
def self.short_circuit_authorizers!
|
||||
module_eval <<-ALIASES, __FILE__, __LINE__ + 1
|
||||
def omniauth_authorize_path(*args)
|
||||
omniauth_callback_path(*args)
|
||||
end
|
||||
ALIASES
|
||||
|
||||
Devise.mappings.each_value do |m|
|
||||
next unless m.omniauthable?
|
||||
|
||||
module_eval <<-ALIASES, __FILE__, __LINE__ + 1
|
||||
def #{m.name}_omniauth_authorize_path(provider)
|
||||
#{m.name}_omniauth_callback_path(provider)
|
||||
end
|
||||
ALIASES
|
||||
end
|
||||
end
|
||||
|
||||
def self.unshort_circuit_authorizers!
|
||||
module_eval do
|
||||
instance_methods.each { |m| remove_method(m) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,11 @@ module Devise
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
|
||||
if Devise.omniauth_configs[provider.to_sym]
|
||||
"/#{mapping.path}/auth/\#{provider}\#{'?'+params.to_param if params.present?}"
|
||||
script_name = request.env["SCRIPT_NAME"]
|
||||
|
||||
path = "\#{script_name}/#{mapping.path}/auth/\#{provider}\".squeeze("/")
|
||||
path << '?' + params.to_param if params.present?
|
||||
path
|
||||
else
|
||||
raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
|
||||
end
|
||||
@@ -26,4 +30,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,17 @@ module Devise
|
||||
Devise.include_helpers(Devise::Controllers)
|
||||
end
|
||||
|
||||
initializer "devise.auth_keys" do
|
||||
if Devise.authentication_keys.size > 1
|
||||
puts "[DEVISE] You are configuring Devise to use more than one authentication key. " \
|
||||
"In previous versions, we automatically added #{Devise.authentication_keys[1..-1].inspect} " \
|
||||
"as scope to your e-mail validation, but this was changed now. If you were relying in such " \
|
||||
"behavior, you should remove :validatable from your models and add the validations manually. " \
|
||||
"To get rid of this warning, you can comment config.authentication_keys in your initializer " \
|
||||
"and pass the current values as key to the devise call in your model."
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.omniauth" do |app|
|
||||
Devise.omniauth_configs.each do |provider, config|
|
||||
app.middleware.use config.strategy_class, *config.args do |strategy|
|
||||
@@ -28,22 +39,5 @@ module Devise
|
||||
Devise.include_helpers(Devise::OmniAuth)
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.encryptor_check" do
|
||||
case Devise.encryptor
|
||||
when :bcrypt
|
||||
puts "[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt " <<
|
||||
"since encryptors are only enabled if you include :encryptable in your models. " <<
|
||||
"With this change, we can integrate better with bcrypt and get rid of the " <<
|
||||
"password_salt column (since bcrypt stores the salt with password). " <<
|
||||
"Please comment config.encryptor in your initializer to get rid of this warning."
|
||||
when nil
|
||||
# Nothing to say
|
||||
else
|
||||
puts "[DEVISE] You are using #{Devise.encryptor} as encryptor. From version 1.2, " <<
|
||||
"you need to explicitly add `devise :encryptable, :encryptor => #{Devise.encryptor.to_sym}` " <<
|
||||
"to your models and comment the current value in the config/initializers/devise.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -99,6 +99,11 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# devise_for :users, :skip => :sessions
|
||||
#
|
||||
# * :only => the opposite of :skip, tell which controllers only to generate routes to:
|
||||
#
|
||||
# devise_for :users, :only => :sessions
|
||||
#
|
||||
#
|
||||
# ==== Scoping
|
||||
#
|
||||
# Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
|
||||
@@ -173,6 +178,9 @@ module ActionDispatch::Routing
|
||||
end
|
||||
|
||||
routes = mapping.routes
|
||||
if options.has_key?(:only)
|
||||
routes = Array(options.delete(:only)).map { |s| s.to_s.singularize.to_sym } & mapping.routes
|
||||
end
|
||||
routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
|
||||
|
||||
devise_scope mapping.name do
|
||||
@@ -263,7 +271,8 @@ module ActionDispatch::Routing
|
||||
end
|
||||
|
||||
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
||||
path_prefix = "/#{mapping.path}/auth"
|
||||
path, @scope[:path] = @scope[:path], nil
|
||||
path_prefix = "/#{mapping.path}/auth".squeeze("/")
|
||||
|
||||
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
|
||||
warn "[DEVISE] You can only add :omniauthable behavior to one model."
|
||||
@@ -271,8 +280,10 @@ module ActionDispatch::Routing
|
||||
::OmniAuth.config.path_prefix = path_prefix
|
||||
end
|
||||
|
||||
match "/auth/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
|
||||
match "#{path_prefix}/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
|
||||
:to => controllers[:omniauth_callbacks], :as => :omniauth_callback
|
||||
ensure
|
||||
@scope[:path] = path
|
||||
end
|
||||
|
||||
def with_devise_exclusive_scope(new_path, new_as) #:nodoc:
|
||||
|
||||
@@ -21,14 +21,14 @@ class Warden::SessionSerializer
|
||||
def deserialize(keys)
|
||||
if keys.size == 2
|
||||
raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
|
||||
"you can fix it by changing one character in your cookie secret or cleaning up your " <<
|
||||
"you can fix it by changing one character in your secret_token or cleaning up your " <<
|
||||
"database sessions if you are using a db store."
|
||||
end
|
||||
|
||||
klass, id, salt = keys
|
||||
|
||||
begin
|
||||
record = klass.constantize.to_adapter.get(id)
|
||||
record = ActiveSupport::Inflector.constantize(klass).to_adapter.get(id)
|
||||
record if record && record.authenticatable_salt == salt
|
||||
rescue NameError => e
|
||||
if e.message =~ /uninitialized constant/
|
||||
@@ -47,6 +47,10 @@ unless Devise.rack_session?
|
||||
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
||||
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
||||
|
||||
def [](key)
|
||||
super(convert_key(key))
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
regular_writer(convert_key(key), value)
|
||||
end
|
||||
@@ -91,6 +95,7 @@ unless Devise.rack_session?
|
||||
def symbolize_keys; to_hash.symbolize_keys end
|
||||
|
||||
def to_options!; self end
|
||||
def to_hash; Hash.new.update(self) end
|
||||
|
||||
protected
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ module Devise
|
||||
# and overwrite the apply_schema method.
|
||||
module Schema
|
||||
|
||||
# Creates email, encrypted_password and password_salt.
|
||||
# Creates email when enabled (on by default), encrypted_password and password_salt.
|
||||
#
|
||||
# == Options
|
||||
# * :null - When true, allow columns to be null.
|
||||
@@ -15,8 +15,9 @@ module Devise
|
||||
def database_authenticatable(options={})
|
||||
null = options[:null] || false
|
||||
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
||||
include_email = !respond_to?(:authentication_keys) || self.authentication_keys.include?(:email)
|
||||
|
||||
apply_devise_schema :email, String, :null => null, :default => default
|
||||
apply_devise_schema :email, String, :null => null, :default => default if include_email
|
||||
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
||||
end
|
||||
|
||||
@@ -37,9 +38,14 @@ module Devise
|
||||
apply_devise_schema :confirmation_sent_at, DateTime
|
||||
end
|
||||
|
||||
# Creates reset_password_token.
|
||||
def recoverable
|
||||
# Creates reset_password_token and reset_password_sent_at.
|
||||
#
|
||||
# == Options
|
||||
# * :reset_within - When true, adds a column that reset passwords within some date
|
||||
def recoverable(options={})
|
||||
use_within = options.fetch(:reset_within, Devise.reset_password_within.present?)
|
||||
apply_devise_schema :reset_password_token, String
|
||||
apply_devise_schema :reset_password_sent_at, DateTime if use_within
|
||||
end
|
||||
|
||||
# Creates remember_token and remember_created_at.
|
||||
|
||||
@@ -19,13 +19,27 @@ module Devise
|
||||
result = resource && resource.valid_for_authentication?(&block)
|
||||
|
||||
case result
|
||||
when Symbol, String
|
||||
when String, Symbol
|
||||
fail!(result)
|
||||
false
|
||||
when TrueClass
|
||||
decorate(resource)
|
||||
true
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# Get values from params and set in the resource.
|
||||
def decorate(resource)
|
||||
resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
|
||||
end
|
||||
|
||||
# Should this resource be marked to be remembered?
|
||||
def remember_me?
|
||||
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
||||
end
|
||||
|
||||
# Check if this is strategy is valid for http authentication by:
|
||||
#
|
||||
# * Validating if the model allows params authentication;
|
||||
@@ -143,7 +157,8 @@ module Devise
|
||||
# becomes simply :database.
|
||||
def authenticatable_name
|
||||
@authenticatable_name ||=
|
||||
self.class.name.split("::").last.underscore.sub("_authenticatable", "").to_sym
|
||||
ActiveSupport::Inflector.underscore(self.class.name.split("::").last).
|
||||
sub("_authenticatable", "").to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ module Devise
|
||||
if validate(resource){ resource.valid_password?(password) }
|
||||
resource.after_database_authentication
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
fail(:invalid)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
|
||||
if validate(resource)
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
cookies.delete(remember_key)
|
||||
pass
|
||||
end
|
||||
@@ -28,6 +28,11 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
def decorate(resource)
|
||||
super
|
||||
resource.extend_remember_period = mapping.to.extend_remember_period if resource.respond_to?(:extend_remember_period=)
|
||||
end
|
||||
|
||||
def remember_me?
|
||||
true
|
||||
end
|
||||
@@ -36,10 +41,6 @@ module Devise
|
||||
"remember_#{scope}_token"
|
||||
end
|
||||
|
||||
def extend_remember_period?
|
||||
mapping.to.extend_remember_period
|
||||
end
|
||||
|
||||
# Accessor for remember cookie
|
||||
def remember_cookie
|
||||
@remember_cookie ||= cookies.signed[remember_key]
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
if validate(resource)
|
||||
resource.after_token_authentication
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
fail(:invalid_token)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Devise
|
||||
# Devise::TestHelpers provides a facility to test controllers in isolation
|
||||
# when using ActionController::TestCase allowing you to quickly sign_in or
|
||||
# sign_out an user. Do not use Devise::TestHelpers in integration tests.
|
||||
# sign_out a user. Do not use Devise::TestHelpers in integration tests.
|
||||
#
|
||||
# Notice you should not test Warden specific behavior (like Warden callbacks)
|
||||
# using Devise::TestHelpers since it is a stub of the actual behavior. Such
|
||||
@@ -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._before_failure.each{ |hook| hook.call(env, result) }
|
||||
|
||||
status, headers, body = Devise::FailureApp.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.2.rc".freeze
|
||||
VERSION = "1.3.3".freeze
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ module ActiveRecord
|
||||
source_root File.expand_path("../templates", __FILE__)
|
||||
|
||||
def generate_model
|
||||
invoke "active_record:model", [name], :migration => false unless model_exists?
|
||||
invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
|
||||
end
|
||||
|
||||
def copy_devise_migration
|
||||
@@ -18,7 +18,7 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_class model_path, class_name, model_contents + <<-CONTENT
|
||||
inject_into_class(model_path, class_name, model_contents + <<CONTENT) if model_exists?
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me
|
||||
CONTENT
|
||||
|
||||
@@ -22,6 +22,7 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
||||
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
||||
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
||||
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
||||
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
||||
end
|
||||
|
||||
def self.down
|
||||
|
||||
@@ -10,7 +10,9 @@ module Devise
|
||||
hook_for :orm
|
||||
|
||||
def add_devise_routes
|
||||
route "devise_for :#{table_name}"
|
||||
devise_route = "devise_for :#{plural_name}"
|
||||
devise_route += %Q(, :class_name => "#{class_name}") if class_name.include?("::")
|
||||
route devise_route
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,8 +12,7 @@ CONTENT
|
||||
end
|
||||
|
||||
def model_exists?
|
||||
return @model_exists if instance_variable_defined?(:@model_exists)
|
||||
@model_exists = File.exists?(File.join(destination_root, model_path))
|
||||
File.exists?(File.join(destination_root, model_path))
|
||||
end
|
||||
|
||||
def model_path
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'tmpdir'
|
||||
|
||||
module Devise
|
||||
module Generators
|
||||
class ViewsGenerator < Rails::Generators::Base
|
||||
@@ -7,57 +9,12 @@ module Devise
|
||||
argument :scope, :required => false, :default => nil,
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
class_option :template_engine, :type => :string, :aliases => "-t",
|
||||
:desc => "Template engine for the views. Available options are 'erb' and 'haml'."
|
||||
# class_option :template_engine, :type => :string, :aliases => "-t",
|
||||
# :desc => "Template engine for the views. Available options are 'erb', 'haml' and 'slim'."
|
||||
|
||||
def copy_views
|
||||
case options[:template_engine].to_s
|
||||
when "haml"
|
||||
verify_haml_existence
|
||||
verify_haml_version
|
||||
create_and_copy_haml_views
|
||||
else
|
||||
directory "devise", "app/views/#{scope || :devise}"
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def verify_haml_existence
|
||||
begin
|
||||
require 'haml'
|
||||
rescue LoadError
|
||||
say "HAML is not installed, or it is not specified in your Gemfile."
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def verify_haml_version
|
||||
unless Haml.version[:major] == 2 and Haml.version[:minor] >= 3 or Haml.version[:major] >= 3
|
||||
say "To generate HAML templates, you need to install HAML 2.3 or above."
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def create_and_copy_haml_views
|
||||
require 'tmpdir'
|
||||
html_root = "#{self.class.source_root}/devise"
|
||||
|
||||
Dir.mktmpdir("devise-haml.") do |haml_root|
|
||||
Dir["#{html_root}/**/*"].each do |path|
|
||||
relative_path = path.sub(html_root, "")
|
||||
source_path = (haml_root + relative_path).sub(/erb$/, "haml")
|
||||
|
||||
if File.directory?(path)
|
||||
FileUtils.mkdir_p(source_path)
|
||||
else
|
||||
`html2haml -r #{path} #{source_path}`
|
||||
end
|
||||
end
|
||||
|
||||
directory haml_root, "app/views/#{scope || :devise}"
|
||||
end
|
||||
directory "devise", "app/views/#{scope || :devise}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,11 +6,11 @@ module Mongoid
|
||||
include Devise::Generators::OrmHelpers
|
||||
|
||||
def generate_model
|
||||
invoke "mongoid:model", [name] unless model_exists?
|
||||
invoke "mongoid:model", [name] unless model_exists? && behavior == :invoke
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_file model_path, model_contents, :after => "include Mongoid::Document\n"
|
||||
inject_into_file model_path, model_contents, :after => "include Mongoid::Document\n" if model_exists?
|
||||
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"
|
||||
@@ -34,7 +34,7 @@ Devise.setup do |config|
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# 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 ]
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
@@ -53,6 +53,9 @@ Devise.setup do |config|
|
||||
# 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 %>
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
# he will be able to access your application without confirming. Default is 0.days
|
||||
@@ -62,6 +65,9 @@ Devise.setup do |config|
|
||||
# (ie 2 days).
|
||||
# config.confirm_within = 2.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
# config.remember_for = 2.weeks
|
||||
@@ -76,12 +82,16 @@ Devise.setup do |config|
|
||||
# to false if you are not using database authenticatable.
|
||||
config.use_salt_as_remember_token = true
|
||||
|
||||
# Options to be passed to the created cookie. For instance, you can set
|
||||
# :secure => true in order to force SSL only cookies.
|
||||
# config.cookie_options = {}
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length. Default is 6..20.
|
||||
# config.password_length = 6..20
|
||||
# Range for password length. Default is 6..128.
|
||||
# config.password_length = 6..128
|
||||
|
||||
# Regex to use to validate the email address
|
||||
# config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
|
||||
# config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
|
||||
# ==> Configuration for :timeoutable
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
@@ -94,6 +104,9 @@ Devise.setup do |config|
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
@@ -108,6 +121,16 @@ Devise.setup do |config|
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key.
|
||||
# Don't put a too small interval or your users won't have the time to
|
||||
# change their passwords.
|
||||
config.reset_password_within = 2.hours
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
@@ -116,9 +139,6 @@ Devise.setup do |config|
|
||||
# REST_AUTH_SITE_KEY to pepper)
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :token_authenticatable
|
||||
# Defines name of the authentication token params key
|
||||
# config.token_authentication_key = :auth_token
|
||||
@@ -150,8 +170,9 @@ Devise.setup do |config|
|
||||
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||
# should add them to the navigational formats lists.
|
||||
#
|
||||
# The :"*/*" format below is required to match Internet Explorer requests.
|
||||
# config.navigational_formats = [:"*/*", :html]
|
||||
# The :"*/*" and "*/*" formats below is required to match Internet
|
||||
# Explorer requests.
|
||||
# config.navigational_formats = [:"*/*", "*/*", :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :get.
|
||||
# config.sign_out_via = :get
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'test_helper'
|
||||
require 'ostruct'
|
||||
|
||||
class ControllerAuthenticableTest < ActionController::TestCase
|
||||
class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
tests ApplicationController
|
||||
|
||||
def setup
|
||||
@@ -13,16 +13,16 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
assert_equal @mock_warden, @controller.warden
|
||||
end
|
||||
|
||||
test 'proxy signed_in? to authenticated' do
|
||||
test 'proxy signed_in?(scope) to authenticate?' do
|
||||
@mock_warden.expects(:authenticate?).with(:scope => :my_scope)
|
||||
@controller.signed_in?(:my_scope)
|
||||
end
|
||||
|
||||
test 'proxy anybody_signed_in? to signed_in?' do
|
||||
test 'proxy signed_in?(nil) to authenticate?' do
|
||||
Devise.mappings.keys.each do |scope| # :user, :admin, :manager
|
||||
@controller.expects(:signed_in?).with(scope)
|
||||
@mock_warden.expects(:authenticate?).with(:scope => scope)
|
||||
end
|
||||
@controller.anybody_signed_in?
|
||||
@controller.signed_in?
|
||||
end
|
||||
|
||||
test 'proxy current_user to authenticate with user scope' do
|
||||
@@ -90,16 +90,32 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
|
||||
test 'sign in proxy to set_user on warden' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(nil)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(:user, user)
|
||||
end
|
||||
|
||||
test 'sign in accepts a resource as argument' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(nil)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(user)
|
||||
end
|
||||
|
||||
test 'does not sign in again if the user is already in' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(user)
|
||||
@mock_warden.expects(:set_user).never
|
||||
@controller.sign_in(user)
|
||||
end
|
||||
|
||||
test 'sign in again when the user is already in only if force is given' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(user)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(user, :force => true)
|
||||
end
|
||||
|
||||
test 'sign in accepts bypass as option' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:session_serializer).returns(serializer = mock())
|
||||
@@ -120,11 +136,13 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
test 'sign out without args proxy to sign out all scopes' do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@controller.sign_out
|
||||
end
|
||||
|
||||
test 'sign out everybody proxy to logout on warden' do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@controller.sign_out_all_scopes
|
||||
end
|
||||
@@ -185,6 +203,17 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
@controller.sign_in_and_redirect(admin)
|
||||
end
|
||||
|
||||
test 'redirect_location returns the stored location if set' do
|
||||
user = User.new
|
||||
@controller.session[:"user_return_to"] = "/foo.bar"
|
||||
assert_equal '/foo.bar', @controller.redirect_location('user', user)
|
||||
end
|
||||
|
||||
test 'redirect_location returns the after sign in path by default' do
|
||||
user = User.new
|
||||
assert_equal @controller.after_sign_in_path_for(:user), @controller.redirect_location('user', user)
|
||||
end
|
||||
|
||||
test 'sign out and redirect uses the configured after sign out path when signing out only the current scope' do
|
||||
swap Devise, :sign_out_all_scopes => false do
|
||||
@mock_warden.expects(:user).with(:admin).returns(true)
|
||||
@@ -197,6 +226,7 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
|
||||
test 'sign out and redirect uses the configured after sign out path when signing out all scopes' do
|
||||
swap Devise, :sign_out_all_scopes => true do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@controller.expects(:redirect_to).with(admin_root_path)
|
||||
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
|
||||
|
||||
@@ -45,6 +45,14 @@ class HelpersTest < ActionController::TestCase
|
||||
@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(:user).with(:user).returns(User.new)
|
||||
@controller.expects(:redirect_to).with(root_path)
|
||||
@controller.send :require_no_authentication
|
||||
assert flash[:alert] == I18n.t("devise.failure.already_authenticated")
|
||||
end
|
||||
|
||||
test 'signed in resource returns signed in resource for current scope' do
|
||||
@mock_warden.expects(:authenticate).with(:scope => :user).returns(User.new)
|
||||
assert_kind_of User, @controller.signed_in_resource
|
||||
@@ -69,4 +77,11 @@ class HelpersTest < ActionController::TestCase
|
||||
assert flash[:notice] == 'non-blank'
|
||||
MyController.send(:protected, :set_flash_message)
|
||||
end
|
||||
|
||||
test 'navigational_formats not returning a wild card' do
|
||||
MyController.send(:public, :navigational_formats)
|
||||
Devise.navigational_formats = [:"*/*", :html]
|
||||
assert_not @controller.navigational_formats.include?(:"*/*")
|
||||
MyController.send(:protected, :navigational_formats)
|
||||
end
|
||||
end
|
||||
|
||||
16
test/controllers/sessions_controller_test.rb
Normal file
16
test/controllers/sessions_controller_test.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SessionsControllerTest < ActionController::TestCase
|
||||
tests Devise::SessionsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
post :create, :user => {
|
||||
:email => "nosuchuser@example.com",
|
||||
:password => "wevdude"
|
||||
}
|
||||
assert_equal 200, @response.status
|
||||
assert_template "devise/sessions/new"
|
||||
end
|
||||
end
|
||||
@@ -58,8 +58,15 @@ class DeviseTest < ActiveSupport::TestCase
|
||||
assert_equal :fruits, Devise::CONTROLLERS[:kivi]
|
||||
Devise::ALL.delete(:kivi)
|
||||
Devise::CONTROLLERS.delete(:kivi)
|
||||
|
||||
assert_nothing_raised(Exception) { Devise.add_module(:authenticatable_again, :model => 'devise/model/authenticatable') }
|
||||
assert defined?(Devise::Models::AuthenticatableAgain)
|
||||
end
|
||||
|
||||
test 'should complain when comparing empty or different sized passes' do
|
||||
[nil, ""].each do |empty|
|
||||
assert_not Devise.secure_compare(empty, "something")
|
||||
assert_not Devise.secure_compare("something", empty)
|
||||
assert_not Devise.secure_compare(empty, empty)
|
||||
end
|
||||
assert_not Devise.secure_compare("size_1", "size_four")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'warden.options' => { :scope => :user },
|
||||
'rack.session' => {},
|
||||
'action_dispatch.request.formats' => Array(env_params.delete('formats') || :html),
|
||||
'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime::HTML),
|
||||
'rack.input' => "",
|
||||
'warden' => OpenStruct.new(:message => nil)
|
||||
}.merge!(env_params)
|
||||
@@ -69,6 +69,13 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert_equal 302, @response.first
|
||||
end
|
||||
end
|
||||
|
||||
test 'redirects the correct format if it is a non-html format request' do
|
||||
swap Devise, :navigational_formats => [:js] do
|
||||
call_failure('formats' => :js)
|
||||
assert_equal 'http://test.host/users/sign_in.js', @response.second["Location"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'For HTTP request' do
|
||||
@@ -77,6 +84,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
|
||||
@@ -120,7 +139,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
swap Devise, :http_authenticatable_on_xhr => false do
|
||||
call_failure('formats' => :json, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
|
||||
assert_equal 'http://test.host/users/sign_in.json', @response.second["Location"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -144,7 +163,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
context 'With recall' do
|
||||
test 'calls the original controller' do
|
||||
test 'calls the original controller if invalid email or password' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in" },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
@@ -154,5 +173,27 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('Invalid email or password.')
|
||||
end
|
||||
|
||||
test 'calls the original controller if not confirmed email' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :unconfirmed },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
"warden" => stub_everything
|
||||
}
|
||||
call_failure(env)
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('You have to confirm your account before continuing.')
|
||||
end
|
||||
|
||||
test 'calls the original controller if inactive account' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :inactive },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
"warden" => stub_everything
|
||||
}
|
||||
call_failure(env)
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('Your account was not activated yet.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
24
test/generators/active_record_generator_test.rb
Normal file
24
test/generators/active_record_generator_test.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
require "test_helper"
|
||||
|
||||
if DEVISE_ORM == :active_record
|
||||
require "generators/active_record/devise_generator"
|
||||
|
||||
class ActiveRecordGeneratorTest < Rails::Generators::TestCase
|
||||
tests ActiveRecord::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
|
||||
assert_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
|
||||
test "all files are properly deleted" do
|
||||
run_generator %w(monster)
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_file "app/models/monster.rb"
|
||||
assert_no_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
33
test/generators/devise_generator_test.rb
Normal file
33
test/generators/devise_generator_test.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require 'test_helper'
|
||||
|
||||
require "generators/devise/devise_generator"
|
||||
|
||||
class DeviseGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
|
||||
setup do
|
||||
prepare_destination
|
||||
copy_routes
|
||||
end
|
||||
|
||||
test "route generation for simple model names" do
|
||||
run_generator %w(monster name:string)
|
||||
assert_file "config/routes.rb", /devise_for :monsters/
|
||||
end
|
||||
|
||||
test "route generation for namespaced model names" do
|
||||
run_generator %w(monster/goblin name:string)
|
||||
match = /devise_for :goblins, :class_name => "Monster::Goblin"/
|
||||
assert_file "config/routes.rb", match
|
||||
end
|
||||
|
||||
def copy_routes
|
||||
routes = File.expand_path("../../rails_app/config/routes.rb", __FILE__)
|
||||
destination = File.join(destination_root, "config")
|
||||
|
||||
FileUtils.mkdir_p(destination)
|
||||
FileUtils.cp routes, destination
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
require "rubygems"
|
||||
require "rails/generators/test_case"
|
||||
require File.join(File.dirname(__FILE__), "../../lib/generators/devise/install_generator")
|
||||
require File.join(File.dirname(__FILE__), "../../lib/generators/devise/views_generator")
|
||||
@@ -1,14 +1,13 @@
|
||||
require File.join(File.dirname(__FILE__),"generators_test_helper.rb")
|
||||
require "test_helper"
|
||||
|
||||
class InstallGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::InstallGenerator
|
||||
destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "Assert all files are properly created" do
|
||||
run_generator
|
||||
assert_file "config/initializers/devise.rb"
|
||||
assert_file "config/initializers/devise.rb"
|
||||
assert_file "config/locales/devise.en.yml"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
22
test/generators/mongoid_generator_test.rb
Normal file
22
test/generators/mongoid_generator_test.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require "test_helper"
|
||||
|
||||
if DEVISE_ORM == :mongo_id
|
||||
require "generators/mongo_id/devise_generator"
|
||||
|
||||
class MongoidGeneratorTest < Rails::Generators::TestCase
|
||||
tests Mongoid::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb", /devise/
|
||||
end
|
||||
|
||||
test "all files are properly deleted" do
|
||||
run_generator %w(monster)
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_file "app/models/monster.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,8 @@
|
||||
require File.join(File.dirname(__FILE__),"generators_test_helper.rb")
|
||||
require "test_helper"
|
||||
|
||||
class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::ViewsGenerator
|
||||
destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "Assert all views are properly created with no params" do
|
||||
@@ -20,18 +20,16 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
|
||||
def assert_files(scope = nil, template_engine = nil)
|
||||
scope = "devise" if scope.nil?
|
||||
assert_file "app/views/#{scope}/confirmations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/confirmation_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/reset_password_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/unlock_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/sessions/new.html.erb"
|
||||
assert_file "app/views/#{scope}/shared/_links.erb"
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb"
|
||||
|
||||
assert_file "app/views/#{scope}/confirmations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/confirmation_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/reset_password_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/unlock_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/sessions/new.html.erb"
|
||||
assert_file "app/views/#{scope}/shared/_links.erb"
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
33
test/indifferent_hash.rb
Normal file
33
test/indifferent_hash.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require 'test_helper'
|
||||
|
||||
class IndifferentHashTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@hash = Devise::IndifferentHash.new
|
||||
end
|
||||
|
||||
test "it overwrites getter and setter" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash["foo"] = "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it overwrites update" do
|
||||
@hash.update :foo => "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash.update "foo" => "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it returns a Hash on to_hash" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal Hash["foo", "bar"], @hash.to_hash
|
||||
assert_kind_of Hash, @hash.to_hash
|
||||
end
|
||||
end if defined?(Devise::IndifferentHash)
|
||||
@@ -209,6 +209,12 @@ class AuthenticationRedirectTest < ActionController::IntegrationTest
|
||||
sign_in_as_admin
|
||||
assert_equal "/admin_area/home", @request.path
|
||||
end
|
||||
|
||||
test 'require_no_authentication should set the already_authenticated flash message' do
|
||||
sign_in_as_user
|
||||
visit new_user_session_path
|
||||
assert_equal flash[:alert], I18n.t("devise.failure.already_authenticated")
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationSessionTest < ActionController::IntegrationTest
|
||||
@@ -330,9 +336,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
|
||||
|
||||
@@ -347,6 +368,27 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
end
|
||||
|
||||
test 'sign in with xml format returns xml response' do
|
||||
create_user
|
||||
post user_session_path(:format => 'xml'), :user => {:email => "user@test.com", :password => '123456'}
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
end
|
||||
|
||||
test 'sign out with xml format returns ok response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'xml')
|
||||
assert_response :ok
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign out with json format returns empty json response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'json')
|
||||
assert_response :ok
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationRequestKeysTest < ActionController::IntegrationTest
|
||||
|
||||
@@ -101,4 +101,32 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert_contain 'Not confirmed user'
|
||||
end
|
||||
end
|
||||
|
||||
test 'resent confirmation token with valid E-Mail in XML format should return valid response' do
|
||||
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>)
|
||||
end
|
||||
|
||||
test 'resent confirmation token with invalid E-Mail in XML format should return invalid response' do
|
||||
user = create_user(:confirm => false)
|
||||
post user_confirmation_path(:format => 'xml'), :user => { :email => 'invalid.test@test.com' }
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'confirm account with valid confirmation token in XML format should return valid response' do
|
||||
user = create_user(:confirm => false)
|
||||
get user_confirmation_path(:confirmation_token => user.confirmation_token, :format => 'xml')
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
end
|
||||
|
||||
test 'confirm account with invalid confirmation token in XML format should return invalid response' do
|
||||
user = create_user(:confirm => false)
|
||||
get user_confirmation_path(:confirmation_token => 'invalid_confirmation', :format => 'xml')
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class LockTest < ActionController::IntegrationTest
|
||||
|
||||
|
||||
def visit_user_unlock_with_token(unlock_token)
|
||||
visit user_unlock_path(:unlock_token => unlock_token)
|
||||
end
|
||||
@@ -106,4 +106,38 @@ class LockTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'user should be able to request a new unlock token via XML request' do
|
||||
user = create_user(:locked => true)
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
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 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
test 'unlocked user should not be able to request a unlock token via XML request' do
|
||||
user = create_user(:locked => false)
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
post user_unlock_path(:format => 'xml'), :user => {:email => user.email}
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
test 'user with valid unlock token should be able to unlock account via XML request' do
|
||||
user = create_user(:locked => true)
|
||||
assert user.access_locked?
|
||||
get user_unlock_path(:format => 'xml', :unlock_token => user.unlock_token)
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
end
|
||||
|
||||
|
||||
test 'user with invalid unlock token should not be able to unlock the account via XML request' do
|
||||
get user_unlock_path(:format => 'xml', :unlock_token => 'invalid_token')
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,32 +2,42 @@ require 'test_helper'
|
||||
|
||||
class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
FACEBOOK_INFO = {
|
||||
:id => '12345',
|
||||
:link => 'http://facebook.com/josevalim',
|
||||
:email => 'user@example.com',
|
||||
:first_name => 'Jose',
|
||||
:last_name => 'Valim',
|
||||
:website => 'http://blog.plataformatec.com.br'
|
||||
}
|
||||
|
||||
ACCESS_TOKEN = {
|
||||
:access_token => "plataformatec"
|
||||
"id" => '12345',
|
||||
"link" => 'http://facebook.com/josevalim',
|
||||
"email" => 'user@example.com',
|
||||
"first_name" => 'Jose',
|
||||
"last_name" => 'Valim',
|
||||
"website" => 'http://blog.plataformatec.com.br'
|
||||
}
|
||||
|
||||
setup do
|
||||
OmniAuth.config.test_mode = true
|
||||
stub_facebook!
|
||||
Devise::OmniAuth.short_circuit_authorizers!
|
||||
end
|
||||
|
||||
teardown do
|
||||
Devise::OmniAuth.unshort_circuit_authorizers!
|
||||
Devise::OmniAuth.reset_stubs!
|
||||
OmniAuth.config.test_mode = false
|
||||
end
|
||||
|
||||
def stub_facebook!
|
||||
Devise::OmniAuth.stub!(:facebook) do |b|
|
||||
b.post('/oauth/access_token') { [200, {}, ACCESS_TOKEN.to_json] }
|
||||
b.get('/me?access_token=plataformatec') { [200, {}, FACEBOOK_INFO.to_json] }
|
||||
OmniAuth.config.mock_auth[:facebook] = {
|
||||
"uid" => '12345',
|
||||
"provider" => 'facebook',
|
||||
"user_info" => {"nickname" => 'josevalim'},
|
||||
"credentials" => {"token" => 'plataformatec'},
|
||||
"extra" => {"user_hash" => FACEBOOK_INFO}
|
||||
}
|
||||
end
|
||||
|
||||
def stub_action!(name)
|
||||
Users::OmniauthCallbacksController.class_eval do
|
||||
alias_method :__old_facebook, :facebook
|
||||
alias_method :facebook, name
|
||||
end
|
||||
yield
|
||||
ensure
|
||||
Users::OmniauthCallbacksController.class_eval do
|
||||
alias_method :facebook, :__old_facebook
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,11 +50,11 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_equal "12345", json["uid"]
|
||||
assert_equal "facebook", json["provider"]
|
||||
assert_equal "josevalim", json["user_info"]["nickname"]
|
||||
assert_equal FACEBOOK_INFO, json["extra"]["user_hash"].symbolize_keys
|
||||
assert_equal FACEBOOK_INFO, json["extra"]["user_hash"]
|
||||
assert_equal "plataformatec", json["credentials"]["token"]
|
||||
end
|
||||
|
||||
test "cleans up session on sign up" do
|
||||
test "cleans up session on sign up" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -65,7 +75,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_not session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "cleans up session on cancel" do
|
||||
test "cleans up session on cancel" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -76,7 +86,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert !session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "cleans up session on sign in" do
|
||||
test "cleans up session on sign in" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -87,16 +97,37 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert !session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "sign in and send remember token if configured" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
assert_nil warden.cookies["remember_user_token"]
|
||||
|
||||
stub_action!(:sign_in_facebook) do
|
||||
create_user
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.cookies["remember_user_token"]
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
test "handles callback error parameter according to the specification" do
|
||||
OmniAuth.config.mock_auth[:facebook] = :access_denied
|
||||
visit "/users/auth/facebook/callback?error=access_denied"
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authorize you from Facebook because "Access denied".'
|
||||
end
|
||||
|
||||
test "handles other exceptions from omniauth" do
|
||||
Devise::OmniAuth.stub!(:facebook) do |b|
|
||||
b.post('/oauth/access_token') { [401, {}, {}.to_json] }
|
||||
end
|
||||
OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
|
||||
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with facebook"
|
||||
@@ -104,4 +135,4 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authorize you from Facebook because "Invalid credentials".'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -157,4 +157,41 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert !warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'reset password request with valid E-Mail in XML format should return valid response' do
|
||||
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>)
|
||||
end
|
||||
|
||||
test 'reset password request with invalid E-Mail in XML format should return valid response' do
|
||||
create_user
|
||||
post user_password_path(:format => 'xml'), :user => {:email => "invalid.test@test.com"}
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'change password with valid parameters in XML format should return valid response' do
|
||||
user = create_user
|
||||
request_forgot_password
|
||||
put user_password_path(:format => 'xml'), :user => {:reset_password_token => user.reload.reset_password_token, :password => '987654321', :password_confirmation => '987654321'}
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'change password with invalid token in XML format should return invalid response' do
|
||||
user = create_user
|
||||
request_forgot_password
|
||||
put user_password_path(:format => 'xml'), :user => {:reset_password_token => 'invalid.token', :password => '987654321', :password_confirmation => '987654321'}
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'change password with invalid new password in XML format should return invalid response' do
|
||||
user = create_user
|
||||
request_forgot_password
|
||||
put user_password_path(:format => 'xml'), :user => {:reset_password_token => user.reload.reset_password_token, :password => '', :password_confirmation => '987654321'}
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,11 +15,27 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
|
||||
assert_contain 'Welcome! You have signed up successfully.'
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_current_url "/admin_area/home"
|
||||
|
||||
admin = Admin.last :order => "id"
|
||||
assert_equal admin.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a guest admin should be able to sign in and be redirected to a custom location' do
|
||||
Devise::RegistrationsController.any_instance.stubs(:after_sign_up_path_for).returns("/?custom=1")
|
||||
get new_admin_session_path
|
||||
click_link 'Sign up'
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_contain 'Welcome! You have signed up successfully.'
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_current_url "/?custom=1"
|
||||
end
|
||||
|
||||
test 'a guest user should be able to sign up successfully and be blocked by confirmation' do
|
||||
get new_user_registration_path
|
||||
|
||||
@@ -30,6 +46,7 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
|
||||
assert_contain 'You have signed up successfully. However, we could not sign you in because your account is unconfirmed.'
|
||||
assert_not_contain 'You have to confirm your account before continuing'
|
||||
assert_current_url "/"
|
||||
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
@@ -38,6 +55,19 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
assert_not user.confirmed?
|
||||
end
|
||||
|
||||
test 'a guest user should be blocked by confirmation and redirected to a custom path' do
|
||||
Devise::RegistrationsController.any_instance.stubs(:after_inactive_sign_up_path_for).returns("/?custom=1")
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_current_url "/?custom=1"
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'a guest user cannot sign up with invalid information' do
|
||||
get new_user_registration_path
|
||||
|
||||
@@ -88,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
|
||||
@@ -116,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
|
||||
@@ -176,4 +206,63 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
assert_nil @request.session["devise.foo_bar"]
|
||||
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
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<admin>)
|
||||
|
||||
admin = Admin.last :order => "id"
|
||||
assert_equal admin.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a user sign up with valid information in XML format should return valid response' do
|
||||
post user_registration_path(:format => 'xml'), :user => { :email => 'new_user@test.com', :password => 'new_user123', :password_confirmation => 'new_user123' }
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
|
||||
user = User.last :order => "id"
|
||||
assert_equal user.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a user sign up with invalid information in XML format should return invalid response' do
|
||||
post user_registration_path(:format => 'xml'), :user => { :email => 'new_user@test.com', :password => 'new_user123', :password_confirmation => 'invalid' }
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'a user update information with valid data in XML format should return valid response' do
|
||||
user = sign_in_as_user
|
||||
put user_registration_path(:format => 'xml'), :user => { :current_password => '123456', :email => 'user.new@test.com' }
|
||||
assert_response :success
|
||||
assert_equal user.reload.email, 'user.new@test.com'
|
||||
end
|
||||
|
||||
test 'a user update information with invalid data in XML format should return invalid response' do
|
||||
user = sign_in_as_user
|
||||
put user_registration_path(:format => 'xml'), :user => { :current_password => 'invalid', :email => 'user.new@test.com' }
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal user.reload.email, 'user@test.com'
|
||||
end
|
||||
|
||||
test 'a user cancel his account in XML format should return valid response' do
|
||||
user = sign_in_as_user
|
||||
delete user_registration_path(:format => 'xml')
|
||||
assert_response :success
|
||||
assert_equal User.count, 0
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,9 +28,9 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
def cookie_expires(key)
|
||||
cookie = response.headers["Set-Cookie"].split("\n").grep(/^#{key}/).first
|
||||
cookie.split(";").map(&:strip).grep(/^expires=/)
|
||||
Time.parse($')
|
||||
cookie = response.headers["Set-Cookie"].split("\n").grep(/^#{key}/).first
|
||||
expires = cookie.split(";").map(&:strip).grep(/^expires=/).first
|
||||
Time.parse(expires).utc
|
||||
end
|
||||
|
||||
test 'do not remember the user if he has not checked remember me option' do
|
||||
@@ -69,6 +69,17 @@ 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."
|
||||
end
|
||||
|
||||
test 'cookies are destroyed on unverified requests' do
|
||||
swap ApplicationController, :allow_forgery_protection => true do
|
||||
user = create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
post root_path, :authenticity_token => 'INVALID'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'does not extend remember period through sign in' do
|
||||
@@ -150,7 +161,6 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
assert_nil warden.cookies['remember_user_token']
|
||||
end
|
||||
|
||||
test 'do not remember the admin anymore after forget' do
|
||||
@@ -160,11 +170,11 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
|
||||
get destroy_admin_session_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
assert_nil admin.reload.remember_token
|
||||
assert_nil warden.cookies['remember_admin_token']
|
||||
|
||||
get root_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
assert_nil warden.cookies['remember_admin_token']
|
||||
end
|
||||
|
||||
test 'changing user password expires remember me token' do
|
||||
@@ -176,4 +186,4 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,15 +76,42 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and do not store if stateless and timeoutable are enabled' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :stateless_token => true, :timeout_in => (0.1).second do
|
||||
user = sign_in_as_new_user_with_token
|
||||
assert warden.authenticated?(:user)
|
||||
|
||||
# Expiring does not work because we are setting the session value when accessing it
|
||||
sleep 0.3
|
||||
|
||||
get_users_path_as_existing_user(user)
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not be subject to injection' do
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
user1 = create_user_with_authentication_token()
|
||||
|
||||
# Clean up user cache
|
||||
@user = nil
|
||||
|
||||
user2 = create_user_with_authentication_token(:email => "another@test.com")
|
||||
user2.update_attribute(:authentication_token, "ANOTHERTOKEN")
|
||||
|
||||
assert_not_equal user1, user2
|
||||
visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token)
|
||||
assert_nil warden.user(:user)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_as_new_user_with_token(options = {})
|
||||
options[:auth_token_key] ||= Devise.token_authentication_key
|
||||
options[:auth_token] ||= VALID_AUTHENTICATION_TOKEN
|
||||
user = options.delete(:user) || create_user_with_authentication_token(options)
|
||||
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
options[:auth_token_key] ||= Devise.token_authentication_key
|
||||
options[:auth_token] ||= user.authentication_token
|
||||
|
||||
if options[:http_auth]
|
||||
header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
|
||||
@@ -96,4 +123,15 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
user
|
||||
end
|
||||
|
||||
def create_user_with_authentication_token(options={})
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
user
|
||||
end
|
||||
|
||||
def get_users_path_as_existing_user(user)
|
||||
sign_in_as_new_user_with_token(:user => user)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -51,7 +51,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
assert_equal "was already confirmed, please try signing in", user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should find and confirm an user automatically' do
|
||||
test 'should find and confirm a user automatically' do
|
||||
user = create_user
|
||||
confirmed_user = User.confirm_by_token(user.confirmation_token)
|
||||
assert_equal confirmed_user, 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
|
||||
@@ -127,7 +127,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
User.send_confirmation_instructions(:email => user.email)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test 'should always have confirmation token when email is sent' do
|
||||
user = new_user
|
||||
user.instance_eval { def confirmation_required?; false end }
|
||||
@@ -167,10 +167,10 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
swap Devise, :confirm_within => 1.day do
|
||||
user = new_user
|
||||
user.confirmation_sent_at = 2.days.ago
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
|
||||
Devise.confirm_within = 3.days
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,42 +180,59 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
user = create_user
|
||||
|
||||
user.confirmation_sent_at = 4.days.ago
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
|
||||
user.confirmation_sent_at = 5.days.ago
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
end
|
||||
|
||||
test 'should be active when already confirmed' do
|
||||
user = create_user
|
||||
assert_not user.confirmed?
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
|
||||
user.confirm!
|
||||
assert user.confirmed?
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should not be active when confirm in is zero' do
|
||||
Devise.confirm_within = 0.days
|
||||
user = create_user
|
||||
user.confirmation_sent_at = Date.today
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should not be active without confirmation' do
|
||||
user = create_user
|
||||
user.confirmation_sent_at = nil
|
||||
user.save
|
||||
assert_not user.reload.active?
|
||||
assert_not user.reload.active_for_authentication?
|
||||
end
|
||||
|
||||
|
||||
test 'should be active without confirmation when confirmation is not required' do
|
||||
user = create_user
|
||||
user.instance_eval { def confirmation_required?; false end }
|
||||
user.confirmation_sent_at = nil
|
||||
user.save
|
||||
assert user.reload.active?
|
||||
assert user.reload.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should find a user to send email instructions for the user confirm it\'s email by authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
confirm_user = User.send_confirmation_instructions(:email => user.email, :username => user.username)
|
||||
assert_equal confirm_user, user
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all confirmation_keys' do
|
||||
swap Devise, :confirmation_keys => [:username, :email] do
|
||||
user = create_user
|
||||
confirm_user = User.send_confirmation_instructions(:email => user.email)
|
||||
assert_not confirm_user.persisted?
|
||||
assert_equal "can't be blank", confirm_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,12 +6,12 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
# case_insensitive_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.downcase, user.email
|
||||
end
|
||||
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
user = new_user
|
||||
assert user.respond_to?(:password)
|
||||
@@ -48,6 +48,18 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert_not user.valid_password?('654321')
|
||||
end
|
||||
|
||||
test 'should not raise error with an empty password' do
|
||||
user = create_user
|
||||
user.encrypted_password = ''
|
||||
assert_nothing_raised { user.valid_password?('123456') }
|
||||
end
|
||||
|
||||
test 'should be an invalid password if the user has an empty password' do
|
||||
user = create_user
|
||||
user.encrypted_password = ''
|
||||
assert_not user.valid_password?('654321')
|
||||
end
|
||||
|
||||
test 'should respond to current password' do
|
||||
assert new_user.respond_to?(:current_password)
|
||||
end
|
||||
@@ -77,8 +89,8 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
|
||||
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
|
||||
@@ -95,4 +107,10 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert user.password.blank?
|
||||
assert user.password_confirmation.blank?
|
||||
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")
|
||||
assert !user.valid?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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(44).returns('friendly_token')
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
|
||||
assert_equal 'friendly_token', create_admin.password_salt
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,15 +47,15 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert user.access_locked?
|
||||
end
|
||||
|
||||
test "active? should be the opposite of locked?" do
|
||||
test "active_for_authentication? should be the opposite of locked?" do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
user.lock_access!
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
|
||||
test "should unlock an user by cleaning locked_at, falied_attempts and unlock_token" do
|
||||
test "should unlock a user by cleaning locked_at, falied_attempts and unlock_token" do
|
||||
user = create_user
|
||||
user.lock_access!
|
||||
assert_not_nil user.reload.locked_at
|
||||
@@ -67,12 +67,6 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert_equal 0, user.reload.failed_attempts
|
||||
end
|
||||
|
||||
test 'should not unlock an unlocked user' do
|
||||
user = create_user
|
||||
assert_not user.unlock_access!
|
||||
assert_match "was not locked", user.errors[:email].join
|
||||
end
|
||||
|
||||
test "new user should not be locked and should have zero failed_attempts" do
|
||||
assert_not new_user.access_locked?
|
||||
assert_equal 0, create_user.failed_attempts
|
||||
@@ -141,7 +135,7 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'should find and unlock an user automatically' do
|
||||
test 'should find and unlock a user automatically' do
|
||||
user = create_user
|
||||
user.lock_access!
|
||||
locked_user = User.unlock_access_by_token(user.unlock_token)
|
||||
@@ -169,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
|
||||
|
||||
@@ -186,13 +180,13 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
unlock_user = User.send_unlock_instructions(:email => user.email)
|
||||
assert_not unlock_user.persisted?
|
||||
assert_equal "can't be blank", unlock_user.errors[:username].join
|
||||
end
|
||||
test 'should require all unlock_keys' do
|
||||
swap Devise, :unlock_keys => [:username, :email] do
|
||||
user = create_user
|
||||
unlock_user = User.send_unlock_instructions(:email => user.email)
|
||||
assert_not unlock_user.persisted?
|
||||
assert_equal "can't be blank", unlock_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not be able to send instructions if the user is not locked' do
|
||||
@@ -201,4 +195,31 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert_not user.access_locked?
|
||||
assert_equal 'was not locked', user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should unlock account if lock has expired and increase attempts on failure' do
|
||||
swap Devise, :unlock_in => 1.minute do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
|
||||
user.failed_attempts = 2
|
||||
user.locked_at = 2.minutes.ago
|
||||
|
||||
user.valid_for_authentication? { false }
|
||||
assert_equal 1, user.failed_attempts
|
||||
end
|
||||
end
|
||||
|
||||
test 'should unlock account if lock has expired on success' do
|
||||
swap Devise, :unlock_in => 1.minute do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
|
||||
user.failed_attempts = 2
|
||||
user.locked_at = 2.minutes.ago
|
||||
|
||||
user.valid_for_authentication? { true }
|
||||
assert_equal 0, user.failed_attempts
|
||||
assert_nil user.locked_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,15 +10,6 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_nil new_user.reset_password_token
|
||||
end
|
||||
|
||||
test 'should regenerate reset password token each time' do
|
||||
user = create_user
|
||||
3.times do
|
||||
token = user.reset_password_token
|
||||
user.send_reset_password_instructions
|
||||
assert_not_equal token, user.reset_password_token
|
||||
end
|
||||
end
|
||||
|
||||
test 'should never generate the same reset password token for different users' do
|
||||
reset_password_tokens = []
|
||||
3.times do
|
||||
@@ -81,11 +72,11 @@ 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
|
||||
|
||||
|
||||
test 'should find a user to send instructions by authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
@@ -93,14 +84,14 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_equal reset_password_user, user
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
reset_password_user = User.send_reset_password_instructions(:email => user.email)
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "can't be blank", reset_password_user.errors[:username].join
|
||||
end
|
||||
|
||||
test 'should require all reset_password_keys' do
|
||||
swap Devise, :reset_password_keys => [:username, :email] do
|
||||
user = create_user
|
||||
reset_password_user = User.send_reset_password_instructions(:email => user.email)
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "can't be blank", reset_password_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should reset reset_password_token before send the reset instructions email' do
|
||||
@@ -125,18 +116,27 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_equal reset_password_user, user
|
||||
end
|
||||
|
||||
test 'should a new record with errors if no reset_password_token is found' do
|
||||
test 'should return a new record with errors if no reset_password_token is found' do
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => 'invalid_token')
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "is invalid", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
|
||||
test 'should a new record with errors if reset_password_token is blank' do
|
||||
test 'should return a new record with errors if reset_password_token is blank' do
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => '')
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_match "can't be blank", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
|
||||
test 'should return a new record with errors if password is blank' do
|
||||
user = create_user
|
||||
user.send :generate_reset_password_token!
|
||||
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token, :password => '')
|
||||
assert_not reset_password_user.errors.empty?
|
||||
assert_match "can't be blank", reset_password_user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should reset successfully user password given the new password and confirmation' do
|
||||
user = create_user
|
||||
old_password = user.password
|
||||
@@ -152,4 +152,63 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_not user.valid_password?(old_password)
|
||||
assert user.valid_password?('new_password')
|
||||
end
|
||||
|
||||
test 'should not reset reset password token during reset_password_within time' do
|
||||
swap Devise, :reset_password_within => 1.hour do
|
||||
user = create_user
|
||||
user.send_reset_password_instructions
|
||||
3.times do
|
||||
token = user.reset_password_token
|
||||
user.send_reset_password_instructions
|
||||
assert_equal token, user.reset_password_token
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'should reset reset password token after reset_password_within time' do
|
||||
swap Devise, :reset_password_within => 1.hour do
|
||||
user = create_user
|
||||
user.reset_password_sent_at = 2.days.ago
|
||||
token = user.reset_password_token
|
||||
user.send_reset_password_instructions
|
||||
assert_not_equal token, user.reset_password_token
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not reset password after reset_password_within time' do
|
||||
swap Devise, :reset_password_within => 1.hour do
|
||||
user = create_user
|
||||
old_password = user.password
|
||||
user.send :generate_reset_password_token!
|
||||
user.reset_password_sent_at = 2.days.ago
|
||||
user.save!
|
||||
|
||||
reset_password_user = User.reset_password_by_token(
|
||||
:reset_password_token => user.reset_password_token,
|
||||
:password => 'new_password',
|
||||
:password_confirmation => 'new_password'
|
||||
)
|
||||
user.reload
|
||||
|
||||
assert user.valid_password?(old_password)
|
||||
assert_not user.valid_password?('new_password')
|
||||
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
|
||||
user.stubs(:respond_to?).with(:reset_password_sent_at=).returns(false)
|
||||
user.stubs(:respond_to?).with(:headers_for).returns(false)
|
||||
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
|
||||
user.stubs(:respond_to?).with(:reset_password_sent_at).returns(false)
|
||||
assert user.reset_password_period_valid?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -27,6 +27,12 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'should return nil when authenticating an invalid user by authentication token' do
|
||||
if DEVISE_ORM == :mongoid
|
||||
raise 'There is an incompatibility between Devise and Mongoid' <<
|
||||
' that makes this test break. For more information, check' <<
|
||||
' this issue: https://github.com/mongoid/mongoid/issues/725'
|
||||
end
|
||||
|
||||
user = create_user
|
||||
user.ensure_authentication_token!
|
||||
user.confirm!
|
||||
@@ -34,4 +40,16 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert_nil authenticated_user
|
||||
end
|
||||
|
||||
end
|
||||
test 'should not be subject to injection' do
|
||||
user1 = create_user
|
||||
user1.ensure_authentication_token!
|
||||
user1.confirm!
|
||||
|
||||
user2 = create_user
|
||||
user2.ensure_authentication_token!
|
||||
user2.confirm!
|
||||
|
||||
user = User.find_for_token_authentication(:auth_token => {'$ne' => user1.authentication_token})
|
||||
assert_nil user
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,10 +75,10 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
assert_equal 'is too short (minimum is 6 characters)', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should require a password with maximum of 20 characters long' do
|
||||
user = new_user(:password => 'x'*21, :password_confirmation => 'x'*21)
|
||||
test 'should require a password with maximum of 128 characters long' do
|
||||
user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129)
|
||||
assert user.invalid?
|
||||
assert_equal 'is too long (maximum is 20 characters)', user.errors[:password].join
|
||||
assert_equal 'is too long (maximum is 128 characters)', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should not require password length when it\'s not changed' do
|
||||
|
||||
@@ -6,6 +6,15 @@ class Configurable < User
|
||||
:remember_for => 7.days, :timeout_in => 15.minutes, :unlock_in => 10.days
|
||||
end
|
||||
|
||||
class WithValidation < Admin
|
||||
devise :database_authenticatable, :validatable, :password_length => 2..6
|
||||
end
|
||||
|
||||
class Several < Admin
|
||||
devise :validatable
|
||||
devise :lockable
|
||||
end
|
||||
|
||||
class Inheritable < Admin
|
||||
end
|
||||
|
||||
@@ -29,6 +38,20 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable, :encryptable
|
||||
end
|
||||
|
||||
if DEVISE_ORM == :active_record
|
||||
test 'validations options are not applied to late' do
|
||||
validators = WithValidation.validators_on :password
|
||||
length = validators.find { |v| v.kind == :length }
|
||||
assert_equal 2, length.options[:minimum]
|
||||
assert_equal 6, length.options[:maximum]
|
||||
end
|
||||
|
||||
test 'validations are applied just once' do
|
||||
validators = Several.validators_on :password
|
||||
assert_equal 1, validators.select{ |v| v.kind == :length }.length
|
||||
end
|
||||
end
|
||||
|
||||
test 'chosen modules are inheritable' do
|
||||
assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable, :encryptable
|
||||
end
|
||||
@@ -47,6 +70,13 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
assert_equal module_constants, (Admin.included_modules & module_constants).reverse
|
||||
end
|
||||
|
||||
test 'raise error on invalid module' do
|
||||
assert_raise NameError do
|
||||
# Mix valid an invalid modules.
|
||||
Configurable.class_eval { devise :database_authenticatable, :doesnotexit }
|
||||
end
|
||||
end
|
||||
|
||||
test 'set a default value for stretches' do
|
||||
assert_equal 15, Configurable.stretches
|
||||
end
|
||||
|
||||
@@ -44,4 +44,11 @@ class OmniAuthRoutesTest < ActionController::TestCase
|
||||
assert_equal "/users/auth/open_id",
|
||||
@controller.omniauth_authorize_path(:user, :open_id)
|
||||
end
|
||||
|
||||
test 'should set script name in the path if present' do
|
||||
@request.env['SCRIPT_NAME'] = '/q'
|
||||
|
||||
assert_equal "/q/users/auth/facebook",
|
||||
@controller.omniauth_authorize_path(:user, :facebook)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
before_filter :current_user
|
||||
before_filter :authenticate_user!, :if => :devise_controller?
|
||||
end
|
||||
|
||||
@@ -4,4 +4,11 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
session["devise.facebook_data"] = data["extra"]["user_hash"]
|
||||
render :json => data
|
||||
end
|
||||
|
||||
def sign_in_facebook
|
||||
user = User.find_by_email('user@test.com')
|
||||
user.remember_me = true
|
||||
sign_in user
|
||||
render :text => ""
|
||||
end
|
||||
end
|
||||
@@ -31,5 +31,10 @@ module RailsApp
|
||||
config.filter_parameters << :password
|
||||
|
||||
config.action_mailer.default_url_options = { :host => "localhost:3000" }
|
||||
|
||||
# This was used to break devise in some situations
|
||||
config.to_prepare do
|
||||
Devise::SessionsController.layout "application"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,9 +15,9 @@ Devise.setup do |config|
|
||||
require "devise/orm/#{DEVISE_ORM}"
|
||||
|
||||
# ==> Configuration for any authentication mechanism
|
||||
# Configure which keys are used when authenticating an user. By default is
|
||||
# Configure which keys are used when authenticating a user. By default is
|
||||
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||
# authenticating an user, both parameters are required. Remember that those
|
||||
# authenticating a user, both parameters are required. Remember that those
|
||||
# parameters are used only when authenticating and not when retrieving from
|
||||
# session. If you need permissions, you should implement that in a before filter.
|
||||
# You can also supply hash where the value is a boolean expliciting if authentication
|
||||
@@ -31,6 +31,11 @@ Devise.setup do |config|
|
||||
# The same considerations mentioned for authentication_keys also apply to request_keys.
|
||||
# config.request_keys = []
|
||||
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# 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 ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
@@ -57,6 +62,9 @@ Devise.setup do |config|
|
||||
# (ie 2 days).
|
||||
# config.confirm_within = 2.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
# config.remember_for = 2.weeks
|
||||
@@ -72,8 +80,8 @@ Devise.setup do |config|
|
||||
config.use_salt_as_remember_token = true
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length. Default is 6..20.
|
||||
# config.password_length = 6..20
|
||||
# Range for password length. Default is 6..128.
|
||||
# config.password_length = 6..128
|
||||
|
||||
# Regex to use to validate the email address
|
||||
# config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
|
||||
@@ -89,6 +97,9 @@ Devise.setup do |config|
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
@@ -103,6 +114,16 @@ Devise.setup do |config|
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key.
|
||||
# Don't put a too small interval or your users won't have the time to
|
||||
# change their passwords.
|
||||
config.reset_password_within = 2.hours
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
|
||||
@@ -29,6 +29,8 @@ Rails.application.routes.draw do
|
||||
end
|
||||
|
||||
# Other routes for routing_test.rb
|
||||
devise_for :reader, :class_name => "User", :only => :passwords
|
||||
|
||||
namespace :publisher, :path_names => { :sign_in => "i_dont_care", :sign_out => "get_out" } do
|
||||
devise_for :accounts, :class_name => "Admin", :path_names => { :sign_in => "get_in" }
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -123,6 +123,13 @@ class CustomizedRoutingTest < ActionController::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'does only map reader password' do
|
||||
assert_raise ActionController::RoutingError do
|
||||
assert_recognizes({:controller => 'devise/sessions', :action => 'new'}, 'reader/sessions/new')
|
||||
end
|
||||
assert_recognizes({:controller => 'devise/passwords', :action => 'new'}, 'reader/password/new')
|
||||
end
|
||||
|
||||
test 'map account with custom path name for session sign in' do
|
||||
assert_recognizes({:controller => 'devise/sessions', :action => 'new', :locale => 'en'}, '/en/accounts/login')
|
||||
end
|
||||
|
||||
33
test/schema_test.rb
Normal file
33
test/schema_test.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
if DEVISE_ORM == :mongoid
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class User2
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable
|
||||
end
|
||||
|
||||
class User3
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable, :authentication_keys => [:username, :email]
|
||||
end
|
||||
|
||||
class User4
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable, :authentication_keys => [:username]
|
||||
end
|
||||
|
||||
class SchemaTest < ActiveSupport::TestCase
|
||||
test 'should create an email field if there are no custom authentication keys' do
|
||||
assert_not_equal User2.fields['email'], nil
|
||||
end
|
||||
|
||||
test 'should create an email field if there are custom authentication keys and they include email' do
|
||||
assert_not_equal User3.fields['email'], nil
|
||||
end
|
||||
|
||||
test 'should not create an email field if there are custom authentication keys they don\'t include email' do
|
||||
assert_equal User4.fields['email'], nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
|
||||
@@ -17,8 +17,11 @@ Webrat.configure do |config|
|
||||
config.open_error_files = false
|
||||
end
|
||||
|
||||
Devise::OmniAuth.test_mode!
|
||||
|
||||
# Add support to load paths so we can overwrite broken webrat setup
|
||||
$:.unshift File.expand_path('../support', __FILE__)
|
||||
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
||||
|
||||
# For generators
|
||||
require "rails/generators/test_case"
|
||||
require "generators/devise/install_generator"
|
||||
require "generators/devise/views_generator"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user