mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
234 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4902af15a | ||
|
|
ab9d856568 | ||
|
|
dd1d128333 | ||
|
|
08a8d7bf51 | ||
|
|
335d36088f | ||
|
|
0b9a95e294 | ||
|
|
98acc84111 | ||
|
|
261c01dfa3 | ||
|
|
ea7f15917f | ||
|
|
df3e711ee0 | ||
|
|
263e903046 | ||
|
|
f7bbac0ab9 | ||
|
|
9ebcb691b0 | ||
|
|
601e1d3dc9 | ||
|
|
7b0a8f9bdc | ||
|
|
dd36324756 | ||
|
|
1b5d0af824 | ||
|
|
edcca8cd3f | ||
|
|
c95ca15b49 | ||
|
|
055117e07a | ||
|
|
ebbabaea5b | ||
|
|
eba53f8f94 | ||
|
|
071f54ac59 | ||
|
|
8796c1c601 | ||
|
|
ef4eb47d50 | ||
|
|
295088f9e8 | ||
|
|
4222afe3c7 | ||
|
|
79d89a3c20 | ||
|
|
8ad414b217 | ||
|
|
7b1418be3b | ||
|
|
7396c6911d | ||
|
|
673c707085 | ||
|
|
f21d05a235 | ||
|
|
1dd19c1a72 | ||
|
|
a8d9695324 | ||
|
|
99d539b9a7 | ||
|
|
179cb2c88a | ||
|
|
9629da863d | ||
|
|
4f76e6f577 | ||
|
|
0f3cef4091 | ||
|
|
7665cbf21d | ||
|
|
b9413ab316 | ||
|
|
a3bff7d6a2 | ||
|
|
7e54dc7903 | ||
|
|
fb1220af97 | ||
|
|
282c7e85ec | ||
|
|
bc15bb53dc | ||
|
|
a729e059de | ||
|
|
7c628f7689 | ||
|
|
6d65c28f1f | ||
|
|
31e4ef5e4b | ||
|
|
d38341b5e0 | ||
|
|
ff90d9da9c | ||
|
|
84c62ed034 | ||
|
|
e76ba05516 | ||
|
|
90d99b16f1 | ||
|
|
3cedba1de8 | ||
|
|
ccbf26be0a | ||
|
|
6448490de5 | ||
|
|
98651dae9d | ||
|
|
bf57ef400d | ||
|
|
27cae04446 | ||
|
|
430eadc1b2 | ||
|
|
e954737a92 | ||
|
|
191d5222e7 | ||
|
|
e77af4b40f | ||
|
|
da3c47259d | ||
|
|
c95575b284 | ||
|
|
7a5086a2be | ||
|
|
c3a665320e | ||
|
|
372dfecf05 | ||
|
|
68bd6809a7 | ||
|
|
7bfdd07a71 | ||
|
|
6bc93173f1 | ||
|
|
55af9f8a40 | ||
|
|
866b35d27c | ||
|
|
5374119f18 | ||
|
|
919404df53 | ||
|
|
fd07c74578 | ||
|
|
560961e3fc | ||
|
|
873e49ab66 | ||
|
|
0f8f786f9f | ||
|
|
7b3e267729 | ||
|
|
7264bb55b2 | ||
|
|
ed6dfed67f | ||
|
|
3488066031 | ||
|
|
bc9ea93f50 | ||
|
|
1920b79a0d | ||
|
|
9131570703 | ||
|
|
770c1a973f | ||
|
|
b7b21a0b72 | ||
|
|
4d91fb4910 | ||
|
|
4ce9d6f29a | ||
|
|
d2a4c503f7 | ||
|
|
a2700bc17f | ||
|
|
0a04d73883 | ||
|
|
502dae3c1f | ||
|
|
e9c766277d | ||
|
|
762f3907fa | ||
|
|
3698b64a10 | ||
|
|
2a6c160d39 | ||
|
|
795754cd60 | ||
|
|
517343ddb5 | ||
|
|
90a5e2f9af | ||
|
|
93180fbb6d | ||
|
|
04cb78947a | ||
|
|
5423f2d5cb | ||
|
|
51d15b7293 | ||
|
|
7a2e018df8 | ||
|
|
1fd4beb18a | ||
|
|
33d7644b4f | ||
|
|
5a98e4f4e8 | ||
|
|
82ae53dd75 | ||
|
|
07db04e773 | ||
|
|
6a8ee475fd | ||
|
|
767a7a7c21 | ||
|
|
a3b56f7eb1 | ||
|
|
5e1a998cde | ||
|
|
219fbc0056 | ||
|
|
dcee6413f4 | ||
|
|
e2895239d8 | ||
|
|
c8077c8d9f | ||
|
|
46c2d5a8f2 | ||
|
|
adb127bb3e | ||
|
|
42f0285278 | ||
|
|
13ef23f517 | ||
|
|
0bf28b19ab | ||
|
|
29a0af78bc | ||
|
|
cf487c771e | ||
|
|
7e711089a8 | ||
|
|
1c81a40a76 | ||
|
|
dba8f91f99 | ||
|
|
8e70e71143 | ||
|
|
f43a7c4f24 | ||
|
|
4e56d92ed8 | ||
|
|
5645d733ba | ||
|
|
42b07f1f47 | ||
|
|
e75354b3b0 | ||
|
|
80122856c4 | ||
|
|
308238ab42 | ||
|
|
e937cf78cf | ||
|
|
2ae2fdc9f8 | ||
|
|
3184834d72 | ||
|
|
8ef5534d92 | ||
|
|
41bb96be5d | ||
|
|
b37055fa47 | ||
|
|
515b727f52 | ||
|
|
77d6d1e8c2 | ||
|
|
04b614ce10 | ||
|
|
62e11ddbe4 | ||
|
|
8e3ab5921f | ||
|
|
1d87997647 | ||
|
|
b58e0ef991 | ||
|
|
db959da247 | ||
|
|
6199252011 | ||
|
|
40c0a7b50b | ||
|
|
422bc4aaa6 | ||
|
|
225c89fbf1 | ||
|
|
76281ff15c | ||
|
|
8b54ff699f | ||
|
|
7d160650b8 | ||
|
|
803e46cda7 | ||
|
|
004fe2ad12 | ||
|
|
09baf2091e | ||
|
|
135a94b4f7 | ||
|
|
a41d185768 | ||
|
|
c3432e57b1 | ||
|
|
a8d88d193e | ||
|
|
471e4d6e72 | ||
|
|
14fec4cfb3 | ||
|
|
4bcd1c6fcd | ||
|
|
84e1a89c44 | ||
|
|
e0162df465 | ||
|
|
7631456047 | ||
|
|
2bc51ab2bd | ||
|
|
d23ecef831 | ||
|
|
c0017ce76d | ||
|
|
30f9da9d71 | ||
|
|
e242ca0937 | ||
|
|
17596b0dc6 | ||
|
|
8e87a2d80d | ||
|
|
4964f53a42 | ||
|
|
6250fa8529 | ||
|
|
944e1c0378 | ||
|
|
4f446241a4 | ||
|
|
97659a1193 | ||
|
|
0bcf71f8df | ||
|
|
ab3bb9cf4d | ||
|
|
69126a31db | ||
|
|
03e3803cff | ||
|
|
58f8c7c613 | ||
|
|
acd1c76c3b | ||
|
|
4c8cc5e3f3 | ||
|
|
72bb33f962 | ||
|
|
2e61e52520 | ||
|
|
75490d0375 | ||
|
|
0fbe4cb6b9 | ||
|
|
d2b3f49384 | ||
|
|
136992b8df | ||
|
|
a130f848f2 | ||
|
|
e10bc9e3c0 | ||
|
|
d56741ca4f | ||
|
|
92c9ed2d6c | ||
|
|
50a5ad54ce | ||
|
|
9dcb44ba61 | ||
|
|
8bdc4b544f | ||
|
|
e763f843c4 | ||
|
|
b5732e31c6 | ||
|
|
ea24ffdd51 | ||
|
|
56f7fbf2d1 | ||
|
|
89b53ea39c | ||
|
|
9cc69277bc | ||
|
|
7e79ed6d4e | ||
|
|
b5190d8df2 | ||
|
|
b03c93c4fe | ||
|
|
8e12ddf7ed | ||
|
|
4fd866d113 | ||
|
|
a59410a254 | ||
|
|
b1a27ad633 | ||
|
|
4a3ad7f348 | ||
|
|
89e4ab8a45 | ||
|
|
fd8e34650e | ||
|
|
e26c8ce499 | ||
|
|
64cf8a4534 | ||
|
|
ae976f60ca | ||
|
|
f152860bc5 | ||
|
|
40153b7422 | ||
|
|
fdfe6a8340 | ||
|
|
79c100008a | ||
|
|
f132c7891b | ||
|
|
bdad984ace | ||
|
|
a229627a54 | ||
|
|
0b598cf132 | ||
|
|
0e657eece1 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,4 +7,6 @@ coverage/*
|
||||
rdoc/*
|
||||
pkg
|
||||
log
|
||||
test/tmp/*
|
||||
test/tmp/*
|
||||
Gemfile.lock
|
||||
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -1,6 +1,12 @@
|
||||
script: "rake test"
|
||||
script: "bundle exec rake test"
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- ree
|
||||
- jruby
|
||||
- rbx
|
||||
- rbx-2.0
|
||||
- jruby
|
||||
notifications:
|
||||
recipients:
|
||||
- jose.valim@plataformatec.com.br
|
||||
- carlos@plataformatec.com.br
|
||||
|
||||
@@ -1,3 +1,94 @@
|
||||
== 1.4.7
|
||||
|
||||
* bug fix
|
||||
* Fix backward incompatible change from 1.4.6 for those using custom controllers
|
||||
|
||||
== 1.4.6
|
||||
|
||||
* enhancements
|
||||
* Allow devise_for :skip => :all
|
||||
* Allow options to be passed to authenticate_user!
|
||||
* Allow --skip-routes to devise generator
|
||||
* Add allow_params_authentication! to make it explicit when params authentication is allowed in a controller
|
||||
|
||||
== 1.4.5
|
||||
|
||||
* bug fix
|
||||
* Failure app tries the root path if a session one does not exist
|
||||
* No need to finalize Devise helpers all the time (by github.com/bradleypriest)
|
||||
* Reset password shows proper message if user is not active
|
||||
* `clean_up_passwords` sets the accessors to nil to skip validations
|
||||
|
||||
== 1.4.4
|
||||
|
||||
* bug fix
|
||||
* Do not always skip helpers, instead provide :skip_helpers as option to trigger it manually
|
||||
|
||||
== 1.4.3
|
||||
|
||||
* enhancements
|
||||
* Improve Rails 3.1 compatibility
|
||||
* Use serialize_into_session and serialize_from_session in Warden serialize to improve extensibility
|
||||
|
||||
* bug fix
|
||||
* Generator properly generates a change_table migration if a model already exists
|
||||
* Properly deprecate setup_mail
|
||||
* Fix encoding issues with email regexp
|
||||
* Only generate helpers for the used mappings
|
||||
* Wrap :action constraints in the proper hash
|
||||
|
||||
* deprecations
|
||||
* Loosened the used email regexp to simply assert the existent of "@". If someone relies on a more strict regexp, they may use https://github.com/SixArm/sixarm_ruby_email_address_validation
|
||||
|
||||
== 1.4.2
|
||||
|
||||
* bug fix
|
||||
* Provide a more robust behavior to serializers and add :force_except option
|
||||
|
||||
== 1.4.1
|
||||
|
||||
* enhancements
|
||||
* Add :defaults and :format support on router
|
||||
* Add simple form generators
|
||||
* Better localization for devise_error_messages! (by github.com/zedtux)
|
||||
|
||||
* bug fix
|
||||
* Ensure to_xml is properly white listened
|
||||
* Ensure handle_unverified_request clean up any cached signed-in user
|
||||
|
||||
== 1.4.0
|
||||
|
||||
* enhancements
|
||||
* Added authenticated and unauthenticated to the router to route the used based on his status (by github.com/sj26)
|
||||
* Improve e-mail regexp (by github.com/rodrigoflores)
|
||||
* Add strip_whitespace_keys and default to e-mail (by github.com/swrobel)
|
||||
* Do not run format and uniqueness validations on e-mail if it hasn't changed (by github.com/Thibaut)
|
||||
* Added update_without_password to update models but not allowing the password to change (by github.com/fschwahn)
|
||||
* Added config.paranoid, check the generator for more information (by github.com/rodrigoflores)
|
||||
|
||||
* bug fix
|
||||
* password_required? should not affect length validation
|
||||
* User cannot access sign up and similar pages if he is already signed in through a cookie or token
|
||||
* Do not convert booleans to strings on finders (by github.com/xavier)
|
||||
* Run validations even if current_password fails (by github.com/crx)
|
||||
* Devise now honors routes constraints (by github.com/macmartine)
|
||||
* Do not return the user resource when requesting instructions (by github.com/rodrigoflores)
|
||||
|
||||
== 1.3.4
|
||||
|
||||
* bug fix
|
||||
* Do not add formats if html or "*/*"
|
||||
|
||||
== 1.3.3
|
||||
|
||||
* bug fix
|
||||
* Explicitly mark the token as expired if so
|
||||
|
||||
== 1.3.2
|
||||
|
||||
* bug fix
|
||||
* Fix another regression related to reset_password_sent_at (by github.com/alexdreher)
|
||||
|
||||
== 1.3.1
|
||||
|
||||
* enhancements
|
||||
|
||||
23
Gemfile
23
Gemfile
@@ -2,28 +2,35 @@ source "http://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.0.4"
|
||||
gem "rails", "~> 3.1.0"
|
||||
gem "oa-oauth", '~> 0.2.0', :require => "omniauth/oauth"
|
||||
gem "oa-openid", '~> 0.2.0', :require => "omniauth/openid"
|
||||
|
||||
gem "rdoc"
|
||||
|
||||
group :test do
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
gem "mocha", :require => false
|
||||
end
|
||||
|
||||
platforms :jruby do
|
||||
gem 'activerecord-jdbc-adapter', :git => 'https://github.com/nicksieger/activerecord-jdbc-adapter.git'
|
||||
gem 'activerecord-jdbcsqlite3-adapter'
|
||||
gem 'jruby-openssl'
|
||||
end
|
||||
|
||||
platforms :mri_18 do
|
||||
group :test do
|
||||
gem "ruby-debug", ">= 0.10.3"
|
||||
end
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
group :test do
|
||||
gem "sqlite3-ruby"
|
||||
gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9'
|
||||
end
|
||||
gem "sqlite3-ruby"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "1.1.2"
|
||||
gem "mongoid", "2.0.0.beta.20"
|
||||
gem "bson_ext", "1.2.1"
|
||||
gem "mongo", "~> 1.3.0"
|
||||
gem "mongoid", "~> 2.0"
|
||||
gem "bson_ext", "~> 1.3.0"
|
||||
end
|
||||
end
|
||||
|
||||
158
Gemfile.lock
158
Gemfile.lock
@@ -1,158 +0,0 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (1.3.0)
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
orm_adapter (~> 0.0.3)
|
||||
warden (~> 1.0.3)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
abstract (1.0.0)
|
||||
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.7)
|
||||
tzinfo (~> 0.3.23)
|
||||
activemodel (3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
builder (~> 2.1.2)
|
||||
i18n (~> 0.4)
|
||||
activerecord (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
arel (~> 2.0.2)
|
||||
tzinfo (~> 0.3.23)
|
||||
activerecord-jdbc-adapter (1.1.1)
|
||||
activerecord-jdbcsqlite3-adapter (1.1.1)
|
||||
activerecord-jdbc-adapter (= 1.1.1)
|
||||
jdbc-sqlite3 (~> 3.6.0)
|
||||
activeresource (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
activesupport (3.0.4)
|
||||
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.7)
|
||||
addressable (~> 2.2.4)
|
||||
multipart-post (~> 1.1.0)
|
||||
rack (>= 1.1.0, < 2)
|
||||
i18n (0.5.0)
|
||||
jdbc-sqlite3 (3.6.14.2.056-java)
|
||||
linecache (0.43)
|
||||
mail (2.2.15)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.16)
|
||||
mocha (0.9.12)
|
||||
mongo (1.1.2)
|
||||
bson (>= 1.1.1)
|
||||
mongoid (2.0.0.beta.20)
|
||||
activemodel (~> 3.0)
|
||||
mongo (~> 1.1)
|
||||
tzinfo (~> 0.3.22)
|
||||
will_paginate (~> 3.0.pre)
|
||||
multi_json (0.0.5)
|
||||
multipart-post (1.1.0)
|
||||
nokogiri (1.4.4)
|
||||
nokogiri (1.4.4-java)
|
||||
weakling (>= 0.0.3)
|
||||
oa-core (0.2.0)
|
||||
rack (~> 1.1)
|
||||
oa-oauth (0.2.0)
|
||||
multi_json (~> 0.0.2)
|
||||
nokogiri (~> 1.4.2)
|
||||
oa-core (= 0.2.0)
|
||||
oauth (~> 0.4.0)
|
||||
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.1)
|
||||
faraday (~> 0.5.0)
|
||||
multi_json (~> 0.0.4)
|
||||
orm_adapter (0.0.4)
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.1)
|
||||
rack-mount (0.6.13)
|
||||
rack (>= 1.0.0)
|
||||
rack-openid (1.2.0)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-test (0.5.7)
|
||||
rack (>= 1.0)
|
||||
rails (3.0.4)
|
||||
actionmailer (= 3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activerecord (= 3.0.4)
|
||||
activeresource (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
bundler (~> 1.0)
|
||||
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)
|
||||
ruby-debug (0.10.4)
|
||||
columnize (>= 0.1)
|
||||
ruby-debug-base (~> 0.10.4.0)
|
||||
ruby-debug-base (0.10.4)
|
||||
linecache (>= 0.3)
|
||||
ruby-openid (2.1.8)
|
||||
ruby-openid-apps-discovery (1.2.0)
|
||||
ruby-openid (>= 2.1.7)
|
||||
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.24)
|
||||
warden (1.0.3)
|
||||
rack (>= 1.0.0)
|
||||
weakling (0.0.4-java)
|
||||
webrat (0.7.2)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
will_paginate (3.0.pre2)
|
||||
|
||||
PLATFORMS
|
||||
java
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bson_ext (= 1.2.1)
|
||||
devise!
|
||||
mocha
|
||||
mongo (= 1.1.2)
|
||||
mongoid (= 2.0.0.beta.20)
|
||||
oa-oauth (~> 0.2.0)
|
||||
oa-openid (~> 0.2.0)
|
||||
rails (~> 3.0.4)
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3-ruby
|
||||
webrat (= 0.7.2)
|
||||
@@ -7,7 +7,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
|
||||
* Is based on a modularity concept: use just what you really need.
|
||||
|
||||
It's composed of 12 modules:
|
||||
It's comprised of 12 modules:
|
||||
|
||||
* 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.
|
||||
@@ -97,7 +97,7 @@ If you are building your first Rails application, we recommend you to *not* use
|
||||
* 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. :)
|
||||
Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
|
||||
|
||||
== Getting started
|
||||
|
||||
@@ -108,7 +108,7 @@ Devise must be set up within the model (or models) you want to use. Devise route
|
||||
We're assuming here you want a User model with some Devise modules, as outlined below:
|
||||
|
||||
class User < ActiveRecord::Base
|
||||
devise :database_authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
|
||||
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
|
||||
end
|
||||
|
||||
After you choose which modules to use, you need to set up your migrations. Luckily, Devise has some helpers to save you from this boring work:
|
||||
@@ -174,7 +174,7 @@ Notice that if your devise model is not called "user" but "member", then the hel
|
||||
|
||||
The devise method in your models also accepts some options to configure its modules. For example, you can choose which encryptor to use in database_authenticatable:
|
||||
|
||||
devise :database_authenticatable, :confirmable, :recoverable, :stretches => 20
|
||||
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20
|
||||
|
||||
Besides :stretches, you can define :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the "devise:install" generator described above.
|
||||
|
||||
|
||||
4
Rakefile
4
Rakefile
@@ -1,10 +1,10 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require 'rdoc/task'
|
||||
|
||||
desc 'Default: run tests for all ORMs.'
|
||||
task :default => :pre_commit
|
||||
task :default => :test
|
||||
|
||||
desc 'Run Devise tests for all ORMs.'
|
||||
task :pre_commit do
|
||||
|
||||
@@ -11,9 +11,9 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => after_resending_confirmation_instructions_path_for(resource_name)
|
||||
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
@@ -26,7 +26,7 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
if resource.errors.empty?
|
||||
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) }
|
||||
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
|
||||
else
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
|
||||
end
|
||||
@@ -38,4 +38,10 @@ class Devise::ConfirmationsController < ApplicationController
|
||||
def after_resending_confirmation_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
|
||||
# The path used after confirmation.
|
||||
def after_confirmation_path_for(resource_name, resource)
|
||||
redirect_location(resource_name, resource)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -12,9 +12,9 @@ class Devise::PasswordsController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
@@ -32,11 +32,20 @@ class Devise::PasswordsController < ApplicationController
|
||||
self.resource = resource_class.reset_password_by_token(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message(:notice, :updated) if is_navigational_format?
|
||||
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
|
||||
set_flash_message(:notice, flash_message) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :edit }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The path used after sending reset password instructions
|
||||
def after_sending_reset_password_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -19,7 +19,7 @@ class Devise::RegistrationsController < ApplicationController
|
||||
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 if is_navigational_format?
|
||||
set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
|
||||
expire_session_data_after_sign_in!
|
||||
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
|
||||
end
|
||||
@@ -35,7 +35,11 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
|
||||
# PUT /resource
|
||||
# We need to use a copy of the resource because we don't want to change
|
||||
# the current user in place.
|
||||
def update
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
|
||||
if resource.update_with_password(params[resource_name])
|
||||
set_flash_message :notice, :updated if is_navigational_format?
|
||||
sign_in resource_name, resource, :bypass => true
|
||||
@@ -80,10 +84,16 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
|
||||
# Overwrite redirect_for_sign_in so it takes uses after_sign_up_path_for.
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
def redirect_location(scope, resource)
|
||||
stored_location_for(scope) || after_sign_up_path_for(resource)
|
||||
end
|
||||
|
||||
# Returns the inactive reason translated.
|
||||
def inactive_reason(resource)
|
||||
reason = resource.inactive_message.to_s
|
||||
I18n.t("devise.registrations.reasons.#{reason}", :default => reason)
|
||||
end
|
||||
|
||||
# The path used after sign up for inactive accounts. You need to overwrite
|
||||
# this method in your own RegistrationsController.
|
||||
def after_inactive_sign_up_path_for(resource)
|
||||
@@ -102,11 +112,9 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# Authenticates the current scope and gets a copy of the current resource.
|
||||
# We need to use a copy because we don't want actions like update changing
|
||||
# the current user in place.
|
||||
# Authenticates the current scope and gets the current resource from the session.
|
||||
def authenticate_scope!
|
||||
send(:"authenticate_#{resource_name}!", true)
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
send(:"authenticate_#{resource_name}!", :force => true)
|
||||
self.resource = send(:"current_#{resource_name}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class Devise::SessionsController < ApplicationController
|
||||
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
|
||||
prepend_before_filter :allow_params_authentication!, :only => :create
|
||||
include Devise::Controllers::InternalHelpers
|
||||
|
||||
# GET /resource/sign_in
|
||||
@@ -38,8 +39,10 @@ class Devise::SessionsController < ApplicationController
|
||||
protected
|
||||
|
||||
def stub_options(resource)
|
||||
array = resource_class.authentication_keys.dup
|
||||
array << :password if resource.respond_to?(:password)
|
||||
{ :methods => array, :only => [:password] }
|
||||
methods = resource_class.authentication_keys.dup
|
||||
methods = methods.keys if methods.is_a?(Hash)
|
||||
methods << :password if resource.respond_to?(:password)
|
||||
{ :methods => methods, :only => [:password] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ class Devise::UnlocksController < ApplicationController
|
||||
def create
|
||||
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
if successful_and_sane?(resource)
|
||||
set_flash_message :notice, :send_instructions if is_navigational_format?
|
||||
respond_with resource, :location => new_session_path(resource_name)
|
||||
respond_with({}, :location => new_session_path(resource_name))
|
||||
else
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ module DeviseHelper
|
||||
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
|
||||
sentence = I18n.t("errors.messages.not_saved",
|
||||
:count => resource.errors.count,
|
||||
:resource => resource_name)
|
||||
:resource => resource.class.model_name.human.downcase)
|
||||
|
||||
html = <<-HTML
|
||||
<div id="error_explanation">
|
||||
|
||||
@@ -1,88 +1,15 @@
|
||||
class Devise::Mailer < ::ActionMailer::Base
|
||||
include Devise::Controllers::ScopedViews
|
||||
attr_reader :scope_name, :resource
|
||||
include Devise::Mailers::Helpers
|
||||
|
||||
def confirmation_instructions(record)
|
||||
setup_mail(record, :confirmation_instructions)
|
||||
devise_mail(record, :confirmation_instructions)
|
||||
end
|
||||
|
||||
def reset_password_instructions(record)
|
||||
setup_mail(record, :reset_password_instructions)
|
||||
devise_mail(record, :reset_password_instructions)
|
||||
end
|
||||
|
||||
def unlock_instructions(record)
|
||||
setup_mail(record, :unlock_instructions)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Configure default email options
|
||||
def setup_mail(record, action)
|
||||
initialize_from_record(record)
|
||||
mail headers_for(action)
|
||||
end
|
||||
|
||||
def initialize_from_record(record)
|
||||
@scope_name = Devise::Mapping.find_scope!(record)
|
||||
@resource = instance_variable_set("@#{devise_mapping.name}", record)
|
||||
end
|
||||
|
||||
def devise_mapping
|
||||
@devise_mapping ||= Devise.mappings[scope_name]
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
headers = {
|
||||
:subject => translate(devise_mapping, action),
|
||||
:from => mailer_sender(devise_mapping),
|
||||
:to => resource.email,
|
||||
:template_path => template_paths
|
||||
}
|
||||
|
||||
if resource.respond_to?(:headers_for)
|
||||
headers.merge!(resource.headers_for(action))
|
||||
end
|
||||
|
||||
unless headers.key?(:reply_to)
|
||||
headers[:reply_to] = headers[:from]
|
||||
end
|
||||
|
||||
headers
|
||||
end
|
||||
|
||||
def mailer_sender(mapping)
|
||||
if Devise.mailer_sender.is_a?(Proc)
|
||||
Devise.mailer_sender.call(mapping.name)
|
||||
else
|
||||
Devise.mailer_sender
|
||||
end
|
||||
end
|
||||
|
||||
def template_paths
|
||||
template_path = [self.class.mailer_name]
|
||||
template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
|
||||
template_path
|
||||
end
|
||||
|
||||
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
|
||||
# based on the current mapping:
|
||||
#
|
||||
# en:
|
||||
# devise:
|
||||
# mailer:
|
||||
# confirmation_instructions:
|
||||
# user_subject: '...'
|
||||
#
|
||||
# If one does not exist, it fallbacks to ActionMailer default:
|
||||
#
|
||||
# en:
|
||||
# devise:
|
||||
# mailer:
|
||||
# confirmation_instructions:
|
||||
# subject: '...'
|
||||
#
|
||||
def translate(mapping, key)
|
||||
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
|
||||
:default => [:subject, key.to_s.humanize])
|
||||
devise_mail(record, :unlock_instructions)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.submit "Resend confirmation instructions" %></p>
|
||||
<div><%= f.submit "Resend confirmation instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -4,13 +4,13 @@
|
||||
<%= devise_error_messages! %>
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
|
||||
<p><%= f.label :password, "New password" %><br />
|
||||
<%= f.password_field :password %></p>
|
||||
<div><%= f.label :password, "New password" %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
|
||||
<p><%= f.label :password_confirmation, "Confirm new password" %><br />
|
||||
<%= f.password_field :password_confirmation %></p>
|
||||
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
|
||||
<p><%= f.submit "Change my password" %></p>
|
||||
<div><%= f.submit "Change my password" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -3,10 +3,10 @@
|
||||
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.submit "Send me reset password instructions" %></p>
|
||||
<div><%= f.submit "Send me reset password instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -3,19 +3,19 @@
|
||||
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
||||
<%= f.password_field :password %></p>
|
||||
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
||||
<%= f.password_field :password %></div>
|
||||
|
||||
<p><%= f.label :password_confirmation %><br />
|
||||
<%= f.password_field :password_confirmation %></p>
|
||||
<div><%= f.label :password_confirmation %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
|
||||
<p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
|
||||
<%= f.password_field :current_password %></p>
|
||||
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
|
||||
<%= f.password_field :current_password %></div>
|
||||
|
||||
<p><%= f.submit "Update" %></p>
|
||||
<div><%= f.submit "Update" %></div>
|
||||
<% end %>
|
||||
|
||||
<h3>Cancel my account</h3>
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></p>
|
||||
<div><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
|
||||
<p><%= f.label :password_confirmation %><br />
|
||||
<%= f.password_field :password_confirmation %></p>
|
||||
<div><%= f.label :password_confirmation %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
|
||||
<p><%= f.submit "Sign up" %></p>
|
||||
<div><%= f.submit "Sign up" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<h2>Sign in</h2>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></p>
|
||||
<div><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
|
||||
<% if devise_mapping.rememberable? -%>
|
||||
<p><%= f.check_box :remember_me %> <%= f.label :remember_me %></p>
|
||||
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
|
||||
<% end -%>
|
||||
|
||||
<p><%= f.submit "Sign in" %></p>
|
||||
<div><%= f.submit "Sign in" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -3,10 +3,10 @@
|
||||
<%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<p><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></p>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<p><%= f.submit "Resend unlock instructions" %></p>
|
||||
<div><%= f.submit "Resend unlock instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -3,6 +3,7 @@
|
||||
en:
|
||||
errors:
|
||||
messages:
|
||||
expired: "has expired, please request a new one"
|
||||
not_found: "not found"
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
not_locked: "was not locked"
|
||||
@@ -26,17 +27,25 @@ en:
|
||||
passwords:
|
||||
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
updated: 'Your password was changed successfully. You are now signed in.'
|
||||
updated_not_active: 'Your password was changed successfully.'
|
||||
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
||||
registrations:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.'
|
||||
updated: 'You updated your account successfully.'
|
||||
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
|
||||
reasons:
|
||||
inactive: 'inactive'
|
||||
unconfirmed: 'unconfirmed'
|
||||
locked: 'locked'
|
||||
unlocks:
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
unlocked: 'Your account was successfully unlocked. You are now signed in.'
|
||||
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
||||
omniauth_callbacks:
|
||||
success: 'Successfully authorized from %{kind} account.'
|
||||
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
||||
|
||||
@@ -21,5 +21,5 @@ Gem::Specification.new do |s|
|
||||
|
||||
s.add_dependency("warden", "~> 1.0.3")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.3")
|
||||
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
|
||||
s.add_dependency("bcrypt-ruby", "~> 3.0")
|
||||
end
|
||||
@@ -3,6 +3,7 @@ require 'active_support/core_ext/numeric/time'
|
||||
require 'active_support/dependencies'
|
||||
require 'orm_adapter'
|
||||
require 'set'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
@@ -29,6 +30,10 @@ module Devise
|
||||
autoload :Sha1, 'devise/encryptors/sha1'
|
||||
end
|
||||
|
||||
module Mailers
|
||||
autoload :Helpers, 'devise/mailers/helpers'
|
||||
end
|
||||
|
||||
module Strategies
|
||||
autoload :Base, 'devise/strategies/base'
|
||||
autoload :Authenticatable, 'devise/strategies/authenticatable'
|
||||
@@ -42,6 +47,9 @@ module Devise
|
||||
STRATEGIES = ActiveSupport::OrderedHash.new
|
||||
URL_HELPERS = ActiveSupport::OrderedHash.new
|
||||
|
||||
# Strategies that do not require user input.
|
||||
NO_INPUT = []
|
||||
|
||||
# True values used to check params
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
@@ -74,6 +82,11 @@ module Devise
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :case_insensitive_keys
|
||||
@@case_insensitive_keys = false
|
||||
|
||||
# Keys that should have whitespace stripped.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :strip_whitespace_keys
|
||||
@@strip_whitespace_keys = false
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -91,9 +104,11 @@ module Devise
|
||||
mattr_accessor :http_authentication_realm
|
||||
@@http_authentication_realm = "Application"
|
||||
|
||||
# Email regex used to validate email formats. Adapted from authlogic.
|
||||
# Email regex used to validate email formats. It simply asserts that
|
||||
# an one (and only one) @ exists in the given string. This is mainly
|
||||
# to give user feedback and not to assert the e-mail validity.
|
||||
mattr_accessor :email_regexp
|
||||
@@email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
@@email_regexp = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
|
||||
|
||||
# Range validation for password length
|
||||
mattr_accessor :password_length
|
||||
@@ -172,7 +187,7 @@ module Devise
|
||||
mattr_accessor :reset_password_keys
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key
|
||||
# Time interval you can reset your password with a reset password key
|
||||
mattr_accessor :reset_password_within
|
||||
@@reset_password_within = nil
|
||||
|
||||
@@ -225,15 +240,30 @@ module Devise
|
||||
@@warden_config = nil
|
||||
@@warden_config_block = nil
|
||||
|
||||
# When true, enter in paranoid mode to avoid user enumeration.
|
||||
mattr_accessor :paranoid
|
||||
@@paranoid = false
|
||||
|
||||
# Default way to setup Devise. Run rails generate devise_install to create
|
||||
# a fresh initializer with all configuration values.
|
||||
def self.setup
|
||||
yield self
|
||||
end
|
||||
|
||||
class Getter
|
||||
def initialize name
|
||||
@name = name
|
||||
end
|
||||
|
||||
def get
|
||||
ActiveSupport::Dependencies.constantize(@name)
|
||||
end
|
||||
end
|
||||
|
||||
def self.ref(arg)
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
ActiveSupport::Dependencies::Reference.store(arg)
|
||||
ActiveSupport::Dependencies::reference(arg)
|
||||
Getter.new(arg)
|
||||
else
|
||||
ActiveSupport::Dependencies.ref(arg)
|
||||
end
|
||||
@@ -245,11 +275,7 @@ module Devise
|
||||
|
||||
# Get the mailer class from the mailer reference object.
|
||||
def self.mailer
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@@mailer_ref.get "Devise::Mailer"
|
||||
else
|
||||
@@mailer_ref.get
|
||||
end
|
||||
@@mailer_ref.get
|
||||
end
|
||||
|
||||
# Set the mailer reference object to access the mailer.
|
||||
@@ -290,13 +316,17 @@ module Devise
|
||||
options.assert_valid_keys(:strategy, :model, :controller, :route)
|
||||
|
||||
if strategy = options[:strategy]
|
||||
STRATEGIES[module_name] = (strategy == true ? module_name : strategy)
|
||||
strategy = (strategy == true ? module_name : strategy)
|
||||
STRATEGIES[module_name] = strategy
|
||||
end
|
||||
|
||||
if controller = options[:controller]
|
||||
CONTROLLERS[module_name] = (controller == true ? module_name : controller)
|
||||
controller = (controller == true ? module_name : controller)
|
||||
CONTROLLERS[module_name] = controller
|
||||
end
|
||||
|
||||
NO_INPUT << strategy if strategy && controller != :sessions
|
||||
|
||||
if route = options[:route]
|
||||
case route
|
||||
when TrueClass
|
||||
@@ -346,7 +376,8 @@ module Devise
|
||||
#
|
||||
def self.omniauth(provider, *args)
|
||||
@@helpers << Devise::OmniAuth::UrlHelpers
|
||||
@@omniauth_configs[provider] = Devise::OmniAuth::Config.new(provider, args)
|
||||
config = Devise::OmniAuth::Config.new(provider, args)
|
||||
@@omniauth_configs[config.strategy_name.to_sym] = config
|
||||
end
|
||||
|
||||
# Include helpers in the given scope to AC and AV.
|
||||
@@ -366,6 +397,12 @@ module Devise
|
||||
Rails::VERSION::STRING[0,3] != "3.0"
|
||||
end
|
||||
|
||||
# Regenerates url helpers considering Devise.mapping
|
||||
def self.regenerate_helpers!
|
||||
Devise::Controllers::UrlHelpers.remove_helpers!
|
||||
Devise::Controllers::UrlHelpers.generate_helpers!
|
||||
end
|
||||
|
||||
# A method used internally to setup warden manager from the Rails initialize
|
||||
# block.
|
||||
def self.configure_warden! #:nodoc:
|
||||
@@ -385,7 +422,7 @@ module Devise
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
def self.friendly_token
|
||||
ActiveSupport::SecureRandom.base64(15).tr('+/=', 'xyz')
|
||||
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
|
||||
end
|
||||
|
||||
# constant-time comparison algorithm to prevent timing attacks
|
||||
|
||||
@@ -5,7 +5,7 @@ module Devise
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
helper_method :warden, :signed_in?, :devise_controller?, :anybody_signed_in?
|
||||
helper_method :warden, :signed_in?, :devise_controller?
|
||||
end
|
||||
|
||||
# Define authentication filters and accessor helpers based on mappings.
|
||||
@@ -36,8 +36,14 @@ module Devise
|
||||
mapping = mapping.name
|
||||
|
||||
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
||||
def authenticate_#{mapping}!(force = false)
|
||||
warden.authenticate!(:scope => :#{mapping}) if !devise_controller? || force
|
||||
def authenticate_#{mapping}!(opts={})
|
||||
if !opts.is_a?(Hash)
|
||||
opts = { :force => opts }
|
||||
ActiveSupport::Deprecation.warn "Passing a boolean to authenticate_#{mapping}! " \
|
||||
"is deprecated, please use :force => \#{opts[:force]} instead", caller
|
||||
end
|
||||
opts[:scope] = :#{mapping}
|
||||
warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
|
||||
end
|
||||
|
||||
def #{mapping}_signed_in?
|
||||
@@ -72,6 +78,11 @@ module Devise
|
||||
false
|
||||
end
|
||||
|
||||
# Tell warden that params authentication is allowed for that specific page.
|
||||
def allow_params_authentication!
|
||||
request.env["devise.allow_params_authentication"] = true
|
||||
end
|
||||
|
||||
# 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)
|
||||
@@ -106,6 +117,7 @@ module Devise
|
||||
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.
|
||||
true
|
||||
else
|
||||
warden.set_user(resource, options.merge!(:scope => scope))
|
||||
end
|
||||
@@ -218,9 +230,12 @@ module Devise
|
||||
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
||||
end
|
||||
|
||||
# Overwrite Rails' handle unverified request to sign out all scopes.
|
||||
# Overwrite Rails' handle unverified request to sign out all scopes,
|
||||
# clear run strategies and remove cached variables.
|
||||
def handle_unverified_request
|
||||
sign_out_all_scopes
|
||||
warden.clear_strategies_cache!
|
||||
Devise.mappings.each { |_,m| instance_variable_set("@current_#{m.name}", nil) }
|
||||
super # call the default behaviour which resets the session
|
||||
end
|
||||
end
|
||||
|
||||
@@ -91,13 +91,27 @@ MESSAGE
|
||||
# Example:
|
||||
# before_filter :require_no_authentication, :only => :new
|
||||
def require_no_authentication
|
||||
if warden.authenticated?(resource_name)
|
||||
no_input = devise_mapping.no_input_strategies
|
||||
args = no_input.dup.push :scope => resource_name
|
||||
if no_input.present? && warden.authenticate?(*args)
|
||||
resource = warden.user(resource_name)
|
||||
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper for use to validate if an resource is errorless. If we are on paranoid mode, we always should assume it is
|
||||
# and return false.
|
||||
def successful_and_sane?(resource)
|
||||
if Devise.paranoid
|
||||
set_flash_message :notice, :send_paranoid_instructions if is_navigational_format?
|
||||
resource.errors.clear
|
||||
false
|
||||
else
|
||||
resource.errors.empty?
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the flash message with :key, using I18n. By default you are able
|
||||
# to setup your messages using specific resource scope, and if no one is
|
||||
# found we look to default scope.
|
||||
|
||||
@@ -29,7 +29,7 @@ module Devise
|
||||
# Forgets the given resource by deleting a cookie
|
||||
def forget_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.forget_me! unless resource.frozen?
|
||||
resource.forget_me!
|
||||
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
||||
end
|
||||
|
||||
|
||||
@@ -18,22 +18,31 @@ module Devise
|
||||
#
|
||||
# Those helpers are added to your ApplicationController.
|
||||
module UrlHelpers
|
||||
|
||||
Devise::URL_HELPERS.each do |module_name, actions|
|
||||
[:path, :url].each do |path_or_url|
|
||||
actions.each do |action|
|
||||
action = action ? "#{action}_" : ""
|
||||
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args)
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
|
||||
end
|
||||
URL_HELPERS
|
||||
end
|
||||
def self.remove_helpers!
|
||||
self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
|
||||
remove_method method
|
||||
end
|
||||
end
|
||||
|
||||
def self.generate_helpers!
|
||||
mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
|
||||
routes = Devise::URL_HELPERS.slice(*mappings)
|
||||
|
||||
routes.each do |module_name, actions|
|
||||
[:path, :url].each do |path_or_url|
|
||||
actions.each do |action|
|
||||
action = action ? "#{action}_" : ""
|
||||
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args)
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
|
||||
end
|
||||
URL_HELPERS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,13 +65,21 @@ module Devise
|
||||
end
|
||||
|
||||
def redirect_url
|
||||
if request_format == :html
|
||||
send(:"new_#{scope}_session_path")
|
||||
opts = {}
|
||||
route = :"new_#{scope}_session_path"
|
||||
opts[:format] = request_format unless skip_format?
|
||||
|
||||
if respond_to?(route)
|
||||
send(route, opts)
|
||||
else
|
||||
send(:"new_#{scope}_session_path", :format => request_format)
|
||||
root_path(opts)
|
||||
end
|
||||
end
|
||||
|
||||
def skip_format?
|
||||
%w(html */*).include? request_format.to_s
|
||||
end
|
||||
|
||||
# Choose whether we should respond in a http authentication fashion,
|
||||
# including 401 and optional headers.
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Before logout hook to forget the user in the given scope, if it responds
|
||||
# to forget_me! Also clear remember token to ensure the user won't be
|
||||
# remembered again. Notice that we forget the user unless the record is frozen.
|
||||
# remembered again. Notice that we forget the user unless the record is not persisted.
|
||||
# This avoids forgetting deleted users.
|
||||
Warden::Manager.before_logout do |record, warden, options|
|
||||
if record.respond_to?(:forget_me!)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Each time a record is set we check whether its session has already timed out
|
||||
# or not, based on last request time. If so, the record is logged out and
|
||||
# redirected to the sign in page. Also, each time the request comes and the
|
||||
# record is set, we set the last request time inside it's scoped session to
|
||||
# record is set, we set the last request time inside its scoped session to
|
||||
# verify timeout in the following request.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# and on authentication. Retrieving the user from session (:fetch) does
|
||||
# not trigger it.
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope])
|
||||
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
|
||||
record.update_tracked_fields!(warden.request)
|
||||
end
|
||||
end
|
||||
|
||||
91
lib/devise/mailers/helpers.rb
Normal file
91
lib/devise/mailers/helpers.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
module Devise
|
||||
module Mailers
|
||||
module Helpers
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include Devise::Controllers::ScopedViews
|
||||
attr_reader :scope_name, :resource
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def setup_mail(*args)
|
||||
ActiveSupport::Deprecation.warn "setup_mail is deprecated, please use devise_mail instead", caller
|
||||
devise_mail(*args)
|
||||
end
|
||||
|
||||
# Configure default email options
|
||||
def devise_mail(record, action)
|
||||
initialize_from_record(record)
|
||||
mail headers_for(action)
|
||||
end
|
||||
|
||||
def initialize_from_record(record)
|
||||
@scope_name = Devise::Mapping.find_scope!(record)
|
||||
@resource = instance_variable_set("@#{devise_mapping.name}", record)
|
||||
end
|
||||
|
||||
def devise_mapping
|
||||
@devise_mapping ||= Devise.mappings[scope_name]
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
headers = {
|
||||
:subject => translate(devise_mapping, action),
|
||||
:from => mailer_sender(devise_mapping),
|
||||
:to => resource.email,
|
||||
:template_path => template_paths
|
||||
}
|
||||
|
||||
if resource.respond_to?(:headers_for)
|
||||
headers.merge!(resource.headers_for(action))
|
||||
end
|
||||
|
||||
unless headers.key?(:reply_to)
|
||||
headers[:reply_to] = headers[:from]
|
||||
end
|
||||
|
||||
headers
|
||||
end
|
||||
|
||||
def mailer_sender(mapping)
|
||||
if default_params[:from].present?
|
||||
default_params[:from]
|
||||
elsif Devise.mailer_sender.is_a?(Proc)
|
||||
Devise.mailer_sender.call(mapping.name)
|
||||
else
|
||||
Devise.mailer_sender
|
||||
end
|
||||
end
|
||||
|
||||
def template_paths
|
||||
template_path = [self.class.mailer_name]
|
||||
template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
|
||||
template_path
|
||||
end
|
||||
|
||||
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
|
||||
# based on the current mapping:
|
||||
#
|
||||
# en:
|
||||
# devise:
|
||||
# mailer:
|
||||
# confirmation_instructions:
|
||||
# user_subject: '...'
|
||||
#
|
||||
# If one does not exist, it fallbacks to ActionMailer default:
|
||||
#
|
||||
# en:
|
||||
# devise:
|
||||
# mailer:
|
||||
# confirmation_instructions:
|
||||
# subject: '...'
|
||||
#
|
||||
def translate(mapping, key)
|
||||
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
|
||||
:default => [:subject, key.to_s.humanize])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -22,7 +22,8 @@ module Devise
|
||||
# # is the modules included in the class
|
||||
#
|
||||
class Mapping #:nodoc:
|
||||
attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via
|
||||
attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
|
||||
:class_name, :sign_out_via, :format, :used_routes, :used_helpers
|
||||
alias :name :singular
|
||||
|
||||
# Receives an object and find a scope for it. If a scope cannot be found,
|
||||
@@ -58,12 +59,38 @@ module Devise
|
||||
mod = options[:module] || "devise"
|
||||
@controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
|
||||
@controllers.merge!(options[:controllers] || {})
|
||||
@controllers.each { |k,v| @controllers[k] = v.to_s }
|
||||
|
||||
@path_names = Hash.new { |h,k| h[k] = k.to_s }
|
||||
@path_names.merge!(:registration => "")
|
||||
@path_names.merge!(options[:path_names] || {})
|
||||
|
||||
@constraints = Hash.new { |h,k| h[k] = k.to_s }
|
||||
@constraints.merge!(options[:constraints] || {})
|
||||
|
||||
@defaults = Hash.new { |h,k| h[k] = k.to_s }
|
||||
@defaults.merge!(options[:defaults] || {})
|
||||
|
||||
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
|
||||
@format = options[:format]
|
||||
|
||||
singularizer = lambda { |s| s.to_s.singularize.to_sym }
|
||||
|
||||
if options.has_key?(:only)
|
||||
@used_routes = self.routes & Array(options[:only]).map(&singularizer)
|
||||
elsif options[:skip] == :all
|
||||
@used_routes = []
|
||||
else
|
||||
@used_routes = self.routes - Array(options[:skip]).map(&singularizer)
|
||||
end
|
||||
|
||||
if options[:skip_helpers] == true
|
||||
@used_helpers = @used_routes
|
||||
elsif skip = options[:skip_helpers]
|
||||
@used_helpers = self.routes - Array(skip).map(&singularizer)
|
||||
else
|
||||
@used_helpers = self.routes
|
||||
end
|
||||
end
|
||||
|
||||
# Return modules for the mapping.
|
||||
@@ -73,17 +100,17 @@ module Devise
|
||||
|
||||
# Gives the class the mapping points to.
|
||||
def to
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@ref.get @class_name
|
||||
else
|
||||
@ref.get
|
||||
end
|
||||
@ref.get
|
||||
end
|
||||
|
||||
def strategies
|
||||
@strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
|
||||
end
|
||||
|
||||
def no_input_strategies
|
||||
self.strategies & Devise::NO_INPUT
|
||||
end
|
||||
|
||||
def routes
|
||||
@routes ||= ROUTES.values_at(*self.modules).compact.uniq
|
||||
end
|
||||
@@ -95,7 +122,15 @@ module Devise
|
||||
def fullpath
|
||||
"/#{@path_prefix}/#{@path}".squeeze("/")
|
||||
end
|
||||
|
||||
|
||||
def constraints
|
||||
@constraints
|
||||
end
|
||||
|
||||
def defaults
|
||||
@defaults
|
||||
end
|
||||
|
||||
# Create magic predicates for verifying what module is activated by this map.
|
||||
# Example:
|
||||
#
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'devise/hooks/activatable'
|
||||
require 'devise/models/serializable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
@@ -46,6 +47,8 @@ module Devise
|
||||
module Authenticatable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Devise::Models::Serializable
|
||||
|
||||
included do
|
||||
class_attribute :devise_modules, :instance_writer => false
|
||||
self.devise_modules ||= []
|
||||
@@ -76,21 +79,17 @@ 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)
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
||||
|
||||
def serialize_into_session(record)
|
||||
[record.to_key, record.authenticatable_salt]
|
||||
end
|
||||
|
||||
def serialize_from_session(key, salt)
|
||||
record = to_adapter.get(key)
|
||||
record if record && record.authenticatable_salt == salt
|
||||
end
|
||||
|
||||
def params_authenticatable?(strategy)
|
||||
params_authenticatable.is_a?(Array) ?
|
||||
@@ -113,8 +112,9 @@ module Devise
|
||||
# end
|
||||
#
|
||||
def find_for_authentication(conditions)
|
||||
filter_auth_params(conditions)
|
||||
conditions = filter_auth_params(conditions.dup)
|
||||
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
||||
(strip_whitespace_keys || []).each { |k| conditions[k].try(:strip!) }
|
||||
to_adapter.find_first(conditions)
|
||||
end
|
||||
|
||||
@@ -126,14 +126,15 @@ module Devise
|
||||
# Find an initialize a group of attributes based on a list of required attributes.
|
||||
def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
|
||||
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
||||
|
||||
(strip_whitespace_keys || []).each { |k| attributes[k].try(:strip!) }
|
||||
|
||||
attributes = attributes.slice(*required_attributes)
|
||||
attributes.delete_if { |key, value| value.blank? }
|
||||
|
||||
if attributes.size == required_attributes.size
|
||||
record = to_adapter.find_first(filter_auth_params(attributes))
|
||||
end
|
||||
|
||||
|
||||
unless record
|
||||
record = new
|
||||
|
||||
@@ -152,9 +153,14 @@ module Devise
|
||||
# Force keys to be string to avoid injection on mongoid related database.
|
||||
def filter_auth_params(conditions)
|
||||
conditions.each do |k, v|
|
||||
conditions[k] = v.to_s
|
||||
conditions[k] = v.to_s if auth_param_requires_string_conversion?(v)
|
||||
end if conditions.is_a?(Hash)
|
||||
end
|
||||
|
||||
# Determine which values should be transformed to string or passed as-is to the query builder underneath
|
||||
def auth_param_requires_string_conversion?(value)
|
||||
true unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Fixnum)
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def generate_token(column)
|
||||
|
||||
@@ -29,7 +29,7 @@ module Devise
|
||||
after_create :send_confirmation_instructions, :if => :confirmation_required?
|
||||
end
|
||||
|
||||
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
||||
# Confirm a user by setting its confirmed_at to actual time. If the user
|
||||
# is already confirmed, add en error to email field
|
||||
def confirm!
|
||||
unless_confirmed do
|
||||
@@ -127,8 +127,13 @@ module Devise
|
||||
generate_confirmation_token && save(:validate => false)
|
||||
end
|
||||
|
||||
def after_password_reset
|
||||
super
|
||||
confirm! unless confirmed?
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Attempt to find a user by it's email. If a record is found, send new
|
||||
# Attempt to find a user by its email. If a record is found, send new
|
||||
# confirmation instructions to it. If not user is found, returns a new user
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
@@ -138,7 +143,7 @@ module Devise
|
||||
confirmable
|
||||
end
|
||||
|
||||
# Find a user by it's confirmation token and try to confirm it.
|
||||
# Find a user by its confirmation token and try to confirm it.
|
||||
# If no user is found, returns a new user with an error.
|
||||
# If the user is already confirmed, create an error for the user
|
||||
# Options must have the confirmation_token
|
||||
|
||||
@@ -10,6 +10,9 @@ module Devise
|
||||
#
|
||||
# DatabaseAuthenticable adds the following options to devise_for:
|
||||
#
|
||||
# * +pepper+: a random string used to provide a more secure hash. Use
|
||||
# `rake secret` to generate new keys.
|
||||
#
|
||||
# * +stretches+: the cost given to bcrypt.
|
||||
#
|
||||
# == Examples
|
||||
@@ -23,6 +26,7 @@ module Devise
|
||||
attr_reader :password, :current_password
|
||||
attr_accessor :password_confirmation
|
||||
before_validation :downcase_keys
|
||||
before_validation :strip_whitespace
|
||||
end
|
||||
|
||||
# Generates password encryption based on the given value.
|
||||
@@ -41,7 +45,7 @@ module Devise
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
def clean_up_passwords
|
||||
self.password = self.password_confirmation = ""
|
||||
self.password = self.password_confirmation = nil
|
||||
end
|
||||
|
||||
# Update record attributes when :current_password matches, otherwise returns
|
||||
@@ -58,8 +62,9 @@ module Devise
|
||||
result = if valid_password?(current_password)
|
||||
update_attributes(params)
|
||||
else
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
self.attributes = params
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
end
|
||||
|
||||
@@ -67,6 +72,17 @@ module Devise
|
||||
result
|
||||
end
|
||||
|
||||
# Updates record attributes without asking for the current password.
|
||||
# Never allows to change the current password
|
||||
def update_without_password(params={})
|
||||
params.delete(:password)
|
||||
params.delete(:password_confirmation)
|
||||
|
||||
result = update_attributes(params)
|
||||
clean_up_passwords
|
||||
result
|
||||
end
|
||||
|
||||
def after_database_authentication
|
||||
end
|
||||
|
||||
@@ -81,6 +97,10 @@ module Devise
|
||||
def downcase_keys
|
||||
(self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
(self.class.strip_whitespace_keys || []).each { |k| self[k].try(:strip!) }
|
||||
end
|
||||
|
||||
# Digests the password using bcrypt.
|
||||
def password_digest(password)
|
||||
|
||||
@@ -3,13 +3,13 @@ module Devise
|
||||
# Handles blocking a user access after a certain number of attempts.
|
||||
# Lockable accepts two different strategies to unlock a user after it's
|
||||
# blocked: email and time. The former will send an email to the user when
|
||||
# the lock happens, containing a link to unlock it's account. The second
|
||||
# the lock happens, containing a link to unlock its account. The second
|
||||
# will unlock the user automatically after some configured time (ie 2.hours).
|
||||
# It's also possible to setup lockable to use both email and time strategies.
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# Lockable adds the following options to devise_for:
|
||||
# Lockable adds the following options to +devise+:
|
||||
#
|
||||
# * +maximum_attempts+: how many attempts should be accepted before blocking the user.
|
||||
# * +lock_strategy+: lock the user account by :failed_attempts or :none.
|
||||
@@ -22,7 +22,7 @@ module Devise
|
||||
|
||||
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
|
||||
|
||||
# Lock a user setting it's locked_at to actual time.
|
||||
# Lock a user setting its locked_at to actual time.
|
||||
def lock_access!
|
||||
self.locked_at = Time.now
|
||||
|
||||
@@ -132,7 +132,7 @@ module Devise
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Attempt to find a user by it's email. If a record is found, send new
|
||||
# Attempt to find a user by its email. If a record is found, send new
|
||||
# unlock instructions to it. If not user is found, returns a new user
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
@@ -142,7 +142,7 @@ module Devise
|
||||
lockable
|
||||
end
|
||||
|
||||
# Find a user by it's unlock token and try to unlock it.
|
||||
# Find a user by its unlock token and try to unlock it.
|
||||
# If no user is found, returns a new user with an error.
|
||||
# If the user is not locked, creates an error for the user
|
||||
# Options must have the unlock_token
|
||||
|
||||
@@ -29,7 +29,11 @@ module Devise
|
||||
def reset_password!(new_password, new_password_confirmation)
|
||||
self.password = new_password
|
||||
self.password_confirmation = new_password_confirmation
|
||||
clear_reset_password_token if valid?
|
||||
if valid?
|
||||
clear_reset_password_token
|
||||
after_password_reset
|
||||
end
|
||||
|
||||
save
|
||||
end
|
||||
|
||||
@@ -42,6 +46,7 @@ module Devise
|
||||
# Checks if the reset password token sent is within the limit time.
|
||||
# We do this by calculating if the difference between today and the
|
||||
# sending date does not exceed the confirm in time configured.
|
||||
# Returns true if the resource is not responding to reset_password_sent_at at all.
|
||||
# reset_password_within is a model configuration, must always be an integer value.
|
||||
#
|
||||
# Example:
|
||||
@@ -59,8 +64,8 @@ module Devise
|
||||
# reset_password_period_valid? # will always return false
|
||||
#
|
||||
def reset_password_period_valid?
|
||||
respond_to?(:reset_password_sent_at) && reset_password_sent_at &&
|
||||
reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
||||
return true unless respond_to?(:reset_password_sent_at)
|
||||
reset_password_sent_at && reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -88,8 +93,11 @@ module Devise
|
||||
self.reset_password_sent_at = nil if respond_to?(:reset_password_sent_at=)
|
||||
end
|
||||
|
||||
def after_password_reset
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Attempt to find a user by it's email. If a record is found, send new
|
||||
# Attempt to find a user by its email. If a record is found, send new
|
||||
# password instructions to it. If not user is found, returns a new user
|
||||
# with an email not found error.
|
||||
# Attributes must contain the user email
|
||||
@@ -104,7 +112,7 @@ module Devise
|
||||
generate_token(:reset_password_token)
|
||||
end
|
||||
|
||||
# Attempt to find a user by it's reset_password_token to reset its
|
||||
# Attempt to find a user by its 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.
|
||||
@@ -115,7 +123,7 @@ module Devise
|
||||
if recoverable.reset_password_period_valid?
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
||||
else
|
||||
recoverable.errors.add(:reset_password_token, :invalid)
|
||||
recoverable.errors.add(:reset_password_token, :expired)
|
||||
end
|
||||
end
|
||||
recoverable
|
||||
|
||||
@@ -54,12 +54,14 @@ module Devise
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Removes the remember token only if it exists, and save the record
|
||||
# without validations.
|
||||
# If the record is persisted, remove the remember token (but only if
|
||||
# it exists), and save the record without validations.
|
||||
def forget_me!
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
if persisted?
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
# Remember token should be expired if expiration time not overpass now.
|
||||
|
||||
43
lib/devise/models/serializable.rb
Normal file
43
lib/devise/models/serializable.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
module Devise
|
||||
module Models
|
||||
# This module redefine to_xml and serializable_hash in models for more
|
||||
# secure defaults. By default, it removes from the serializable model
|
||||
# all attributes that are *not* accessible. You can remove this default
|
||||
# by using :force_except and passing a new list of attributes you want
|
||||
# to exempt. All attributes given to :except will simply add names to
|
||||
# exempt to Devise internal list.
|
||||
module Serializable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
|
||||
%w(to_xml serializable_hash).each do |method|
|
||||
class_eval <<-RUBY, __FILE__, __LINE__
|
||||
def #{method}(options=nil)
|
||||
options ||= {}
|
||||
if options.key?(:force_except)
|
||||
options[:except] = options.delete(:force_except)
|
||||
super(options)
|
||||
elsif self.class.blacklist_keys?
|
||||
except = Array(options[:except])
|
||||
super(options.merge(:except => except + self.class.blacklist_keys))
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Return true if we can retrieve blacklist keys from the record.
|
||||
def blacklist_keys?
|
||||
@has_except_keys ||= respond_to?(:accessible_attributes) && !accessible_attributes.to_a.empty?
|
||||
end
|
||||
|
||||
# Returns keys that should be removed when serializing the record.
|
||||
def blacklist_keys
|
||||
@blacklist_keys ||= to_adapter.column_names.map(&:to_s) - accessible_attributes.to_a.map(&:to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,10 +5,10 @@ module Devise
|
||||
# Track information about your user sign in. It tracks the following columns:
|
||||
#
|
||||
# * sign_in_count - Increased every time a sign in is made (by form, openid, oauth)
|
||||
# * current_sign_in_at - A tiemstamp updated when the user signs in
|
||||
# * current_sign_in_at - A timestamp updated when the user signs in
|
||||
# * last_sign_in_at - Holds the timestamp of the previous sign in
|
||||
# * current_sign_in_ip - The remote ip updated when the user sign in
|
||||
# * last_sign_in_at - Holds the remote ip of the previous sign in
|
||||
# * last_sign_in_ip - Holds the remote ip of the previous sign in
|
||||
#
|
||||
module Trackable
|
||||
def update_tracked_fields!(request)
|
||||
|
||||
@@ -2,7 +2,7 @@ module Devise
|
||||
module Models
|
||||
# Validatable creates all needed validations for a user email and password.
|
||||
# It's optional, given you may want to create the validations by yourself.
|
||||
# Automatically validate if the email is present, unique and it's format is
|
||||
# Automatically validate if the email is present, unique and its format is
|
||||
# valid. Also tests presence of password, confirmation and length.
|
||||
#
|
||||
# == Options
|
||||
@@ -23,14 +23,12 @@ module Devise
|
||||
|
||||
base.class_eval do
|
||||
validates_presence_of :email, :if => :email_required?
|
||||
validates_uniqueness_of :email, :case_sensitive => (case_insensitive_keys != false), :allow_blank => true
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true
|
||||
validates_uniqueness_of :email, :case_sensitive => (case_insensitive_keys != false), :allow_blank => true, :if => :email_changed?
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true, :if => :email_changed?
|
||||
|
||||
with_options :if => :password_required? do |v|
|
||||
v.validates_presence_of :password
|
||||
v.validates_confirmation_of :password
|
||||
v.validates_length_of :password, :within => password_length, :allow_blank => true
|
||||
end
|
||||
validates_presence_of :password, :if => :password_required?
|
||||
validates_confirmation_of :password, :if => :password_required?
|
||||
validates_length_of :password, :within => password_length, :allow_blank => true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Devise.with_options :model => true do |d|
|
||||
d.with_options :strategy => true do |s|
|
||||
routes = [nil, :new, :destroy]
|
||||
s.add_module :database_authenticatable, :controller => :sessions, :route => { :session => routes }
|
||||
s.add_module :token_authenticatable, :controller => :sessions, :route => { :session => routes }
|
||||
s.add_module :token_authenticatable
|
||||
s.add_module :rememberable
|
||||
end
|
||||
|
||||
|
||||
@@ -23,10 +23,5 @@ module Devise
|
||||
module OmniAuth
|
||||
autoload :Config, "devise/omniauth/config"
|
||||
autoload :UrlHelpers, "devise/omniauth/url_helpers"
|
||||
|
||||
class << self
|
||||
delegate :short_circuit_authorizers!, :unshort_circuit_authorizers!,
|
||||
:test_mode!, :stub!, :reset_stubs!, :to => "Devise::OmniAuth::TestHelpers"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,12 @@ module Devise
|
||||
@strategy = nil
|
||||
end
|
||||
|
||||
# open_id strategy can have configurable name
|
||||
def strategy_name
|
||||
options = @args.last.is_a?(Hash) && @args.last
|
||||
options && options[:name] ? options[:name] : @provider
|
||||
end
|
||||
|
||||
def strategy_class
|
||||
::OmniAuth::Strategies.const_get("#{::OmniAuth::Utils.camelize(@provider.to_s)}")
|
||||
end
|
||||
|
||||
@@ -39,5 +39,18 @@ module Devise
|
||||
Devise.include_helpers(Devise::OmniAuth)
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.mongoid_version_warning" do
|
||||
if defined?(Mongoid)
|
||||
require 'mongoid/version'
|
||||
if Mongoid::VERSION.to_f < 2.1
|
||||
puts "\n[DEVISE] Please note that Mongoid versions prior to 2.1 handle dirty model " \
|
||||
"object attributes in such a way that the Devise `validatable` module will not apply " \
|
||||
"its usual uniqueness and format validations for the email field. It is recommended " \
|
||||
"that you upgrade to Mongoid 2.1+ for this and other fixes, but if for some reason you " \
|
||||
"are unable to do so, you should add these validations manually.\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,12 @@ module ActionDispatch::Routing
|
||||
# need devise_for mappings already declared to create filters and helpers.
|
||||
def finalize_with_devise!
|
||||
finalize_without_devise!
|
||||
Devise.configure_warden!
|
||||
|
||||
@devise_finalized ||= begin
|
||||
Devise.configure_warden!
|
||||
Devise.regenerate_helpers!
|
||||
true
|
||||
end
|
||||
end
|
||||
alias_method_chain :finalize!, :devise
|
||||
end
|
||||
@@ -93,7 +98,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# Also pay attention that when you use a namespace it will affect all the helpers and methods for controllers
|
||||
# and views. For example, using the above setup you'll end with following methods:
|
||||
# current_publisher_account, authenticate_publisher_account!, pusblisher_account_signed_in, etc.
|
||||
# current_publisher_account, authenticate_publisher_account!, publisher_account_signed_in, etc.
|
||||
#
|
||||
# * :skip => tell which controller you want to skip routes from being created:
|
||||
#
|
||||
@@ -103,6 +108,21 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# devise_for :users, :only => :sessions
|
||||
#
|
||||
# * :skip_helpers => skip generating Devise url helpers like new_session_path(@user).
|
||||
# This is useful to avoid conflicts with previous routes and is false by default.
|
||||
# It accepts true as option, meaning it will skip all the helpers for the controllers
|
||||
# given in :skip but it also accepts specific helpers to be skipped:
|
||||
#
|
||||
# devise_for :users, :skip => [:registrations, :confirmations], :skip_helpers => true
|
||||
# devise_for :users, :skip_helpers => [:registrations, :confirmations]
|
||||
#
|
||||
# * :format => include "(.:format)" in the generated routes? true by default, set to false to disable:
|
||||
#
|
||||
# devise_for :users, :format => false
|
||||
#
|
||||
# * :constraints => works the same as Rails' contraints
|
||||
#
|
||||
# * :defaults => works the same as Rails' defaults
|
||||
#
|
||||
# ==== Scoping
|
||||
#
|
||||
@@ -129,9 +149,9 @@ module ActionDispatch::Routing
|
||||
# end
|
||||
#
|
||||
# ==== Adding custom actions to override controllers
|
||||
#
|
||||
# You can pass a block to devise_for that will add any routes defined in the block to Devise's
|
||||
# list of known actions. This is important if you add a custom action to a controller that
|
||||
#
|
||||
# You can pass a block to devise_for that will add any routes defined in the block to Devise's
|
||||
# list of known actions. This is important if you add a custom action to a controller that
|
||||
# overrides an out of the box Devise controller.
|
||||
# For example:
|
||||
#
|
||||
@@ -153,12 +173,16 @@ module ActionDispatch::Routing
|
||||
# end
|
||||
#
|
||||
def devise_for(*resources)
|
||||
@devise_finalized = false
|
||||
options = resources.extract_options!
|
||||
|
||||
options[:as] ||= @scope[:as] if @scope[:as].present?
|
||||
options[:module] ||= @scope[:module] if @scope[:module].present?
|
||||
options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
|
||||
options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
|
||||
options[:constraints] = (@scope[:constraints] || {}).merge(options[:constraints] || {})
|
||||
options[:defaults] = (@scope[:defaults] || {}).merge(options[:defaults] || {})
|
||||
@scope[:options] = (@scope[:options] || {}).merge({:format => false}) if options[:format] == false
|
||||
|
||||
resources.map!(&:to_sym)
|
||||
|
||||
@@ -177,15 +201,11 @@ module ActionDispatch::Routing
|
||||
raise_no_devise_method_error!(mapping.class_name)
|
||||
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 }
|
||||
routes = mapping.used_routes
|
||||
|
||||
devise_scope mapping.name do
|
||||
yield if block_given?
|
||||
with_devise_exclusive_scope mapping.fullpath, mapping.name do
|
||||
with_devise_exclusive_scope mapping.fullpath, mapping.name, mapping.constraints, mapping.defaults do
|
||||
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
|
||||
end
|
||||
end
|
||||
@@ -194,11 +214,15 @@ module ActionDispatch::Routing
|
||||
|
||||
# Allow you to add authentication request from the router:
|
||||
#
|
||||
# authenticate(:user) do
|
||||
# authenticate do
|
||||
# resources :post
|
||||
# end
|
||||
#
|
||||
def authenticate(scope)
|
||||
# authenticate(:admin) do
|
||||
# resources :users
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate!(:scope => scope)
|
||||
end
|
||||
@@ -208,6 +232,50 @@ module ActionDispatch::Routing
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is authenticated. You
|
||||
# can optionally specify which scope.
|
||||
#
|
||||
# authenticated :admin do
|
||||
# root :to => 'admin/dashboard#show'
|
||||
# end
|
||||
#
|
||||
# authenticated do
|
||||
# root :to => 'dashboard#show'
|
||||
# end
|
||||
#
|
||||
# root :to => 'landing#show'
|
||||
#
|
||||
def authenticated(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate? :scope => scope
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is *not* authenticated.
|
||||
# You can optionally specify which scope.
|
||||
#
|
||||
# unauthenticated do
|
||||
# as :user do
|
||||
# root :to => 'devise/registrations#new'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# root :to => 'dashboard#show'
|
||||
#
|
||||
def unauthenticated(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
not request.env["warden"].authenticate? :scope => scope
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the devise scope to be used in the controller. If you have custom routes,
|
||||
# you are required to call this method (also aliased as :as) in order to specify
|
||||
# to which controller it is targetted.
|
||||
@@ -219,6 +287,17 @@ module ActionDispatch::Routing
|
||||
# Notice you cannot have two scopes mapping to the same URL. And remember, if
|
||||
# you try to access a devise controller without specifying a scope, it will
|
||||
# raise ActionNotFound error.
|
||||
#
|
||||
# Also be aware of that 'devise_scope' and 'as' use the singular form of the
|
||||
# noun where other devise route commands expect the plural form. This would be a
|
||||
# good and working example.
|
||||
#
|
||||
# devise_scope :user do
|
||||
# match "/some/route" => "some_devise_controller"
|
||||
# end
|
||||
# devise_for :users
|
||||
#
|
||||
# Notice and be aware of the differences above between :user and :users
|
||||
def devise_scope(scope)
|
||||
constraint = lambda do |request|
|
||||
request.env["devise.mapping"] = Devise.mappings[scope]
|
||||
@@ -264,7 +343,7 @@ module ActionDispatch::Routing
|
||||
:cancel => mapping.path_names[:cancel]
|
||||
}
|
||||
|
||||
resource :registration, :except => :show, :path => mapping.path_names[:registration],
|
||||
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
|
||||
:path_names => path_names, :controller => controllers[:registrations] do
|
||||
get :cancel
|
||||
end
|
||||
@@ -280,23 +359,23 @@ module ActionDispatch::Routing
|
||||
::OmniAuth.config.path_prefix = path_prefix
|
||||
end
|
||||
|
||||
match "#{path_prefix}/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
|
||||
match "#{path_prefix}/:action/callback", :constraints => { :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:
|
||||
old_as, old_path, old_module = @scope[:as], @scope[:path], @scope[:module]
|
||||
@scope[:as], @scope[:path], @scope[:module] = new_as, new_path, nil
|
||||
def with_devise_exclusive_scope(new_path, new_as, new_constraints, new_defaults) #:nodoc:
|
||||
old_as, old_path, old_module, old_constraints, old_defaults = @scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults]
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults] = new_as, new_path, nil, new_constraints, new_defaults
|
||||
yield
|
||||
ensure
|
||||
@scope[:as], @scope[:path], @scope[:module] = old_as, old_path, old_module
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults] = old_as, old_path, old_module, old_constraints, old_defaults
|
||||
end
|
||||
|
||||
def raise_no_devise_method_error!(klass) #:nodoc:
|
||||
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " <<
|
||||
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
|
||||
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " \
|
||||
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " \
|
||||
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,21 +15,16 @@ end
|
||||
|
||||
class Warden::SessionSerializer
|
||||
def serialize(record)
|
||||
[record.class.name, record.to_key, record.authenticatable_salt]
|
||||
klass = record.class
|
||||
array = klass.serialize_into_session(record)
|
||||
array.unshift(klass.name)
|
||||
end
|
||||
|
||||
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 secret_token or cleaning up your " <<
|
||||
"database sessions if you are using a db store."
|
||||
end
|
||||
|
||||
klass, id, salt = keys
|
||||
klass, *args = keys
|
||||
|
||||
begin
|
||||
record = ActiveSupport::Inflector.constantize(klass).to_adapter.get(id)
|
||||
record if record && record.authenticatable_salt == salt
|
||||
ActiveSupport::Inflector.constantize(klass).serialize_from_session(*args)
|
||||
rescue NameError => e
|
||||
if e.message =~ /uninitialized constant/
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"
|
||||
|
||||
@@ -3,11 +3,12 @@ module Devise
|
||||
# and overwrite the apply_schema method.
|
||||
module Schema
|
||||
|
||||
# Creates email when enabled (on by default), encrypted_password and password_salt.
|
||||
# Creates encrypted_password, and email when it is used as an authentication
|
||||
# key (default).
|
||||
#
|
||||
# == Options
|
||||
# * :null - When true, allow columns to be null.
|
||||
# * :default - Should be set to "" when :null is false.
|
||||
# * :default - Set to "" when :null is false, unless overridden.
|
||||
#
|
||||
# == Notes
|
||||
# For Datamapper compatibility, we explicitly hardcode the limit for the
|
||||
@@ -21,7 +22,8 @@ module Devise
|
||||
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
||||
end
|
||||
|
||||
# Creates password salt for encryption support.
|
||||
# Creates password salt for encryption support when using encryptors other
|
||||
# than the database_authenticable default of bcrypt.
|
||||
def encryptable
|
||||
apply_devise_schema :password_salt, String
|
||||
end
|
||||
|
||||
@@ -85,17 +85,17 @@ module Devise
|
||||
|
||||
# By default, a request is valid if the controller is allowed and the VERB is POST.
|
||||
def valid_request?
|
||||
valid_controller? && valid_verb?
|
||||
end
|
||||
|
||||
# Check if the controller is the one registered for authentication.
|
||||
def valid_controller?
|
||||
mapping.controllers[:sessions] == params[:controller]
|
||||
end
|
||||
|
||||
# Check if it was a POST request.
|
||||
def valid_verb?
|
||||
request.post?
|
||||
if env["devise.allow_params_authentication"]
|
||||
true
|
||||
elsif request.post? && mapping.controllers[:sessions] == params[:controller]
|
||||
ActiveSupport::Deprecation.warn "It seems that you are using a custom SessionsController. " \
|
||||
"In order for it to work from Devise 1.4.6 forward, you need to add the following:" \
|
||||
"\n\n prepend_before_filter :allow_params_authentication!, :only => :create\n\n" \
|
||||
"This will ensure your controller can authenticate from params for the create action.", caller
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# If the request is valid, finally check if params_auth_hash returns a hash.
|
||||
|
||||
@@ -9,6 +9,7 @@ module Devise
|
||||
class Rememberable < Authenticatable
|
||||
# A valid strategy for rememberable needs a remember token in the cookies.
|
||||
def valid?
|
||||
@remember_cookie = nil
|
||||
remember_cookie.present?
|
||||
end
|
||||
|
||||
@@ -41,10 +42,10 @@ module Devise
|
||||
"remember_#{scope}_token"
|
||||
end
|
||||
|
||||
# Accessor for remember cookie
|
||||
def remember_cookie
|
||||
@remember_cookie ||= cookies.signed[remember_key]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,7 +39,11 @@ module Devise
|
||||
|
||||
# Try both scoped and non scoped keys.
|
||||
def params_auth_hash
|
||||
params[scope] || params
|
||||
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
|
||||
params[scope]
|
||||
else
|
||||
params
|
||||
end
|
||||
end
|
||||
|
||||
# Overwrite authentication keys to use token_authentication_key.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "1.3.1".freeze
|
||||
VERSION = "1.4.7".freeze
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require 'rails/generators/active_record'
|
||||
require 'generators/devise/orm_helpers'
|
||||
|
||||
|
||||
module ActiveRecord
|
||||
module Generators
|
||||
class DeviseGenerator < ActiveRecord::Generators::Base
|
||||
@@ -9,14 +10,18 @@ module ActiveRecord
|
||||
include Devise::Generators::OrmHelpers
|
||||
source_root File.expand_path("../templates", __FILE__)
|
||||
|
||||
def copy_devise_migration
|
||||
if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
|
||||
migration_template "migration_existing.rb", "db/migrate/add_devise_to_#{table_name}"
|
||||
else
|
||||
migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
|
||||
end
|
||||
end
|
||||
|
||||
def generate_model
|
||||
invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
|
||||
end
|
||||
|
||||
def copy_devise_migration
|
||||
migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
|
||||
end
|
||||
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_class(model_path, class_name, model_contents + <<CONTENT) if model_exists?
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
|
||||
34
lib/generators/active_record/templates/migration_existing.rb
Normal file
34
lib/generators/active_record/templates/migration_existing.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
|
||||
def self.up
|
||||
change_table(:<%= table_name %>) do |t|
|
||||
t.database_authenticatable :null => false
|
||||
t.recoverable
|
||||
t.rememberable
|
||||
t.trackable
|
||||
|
||||
# t.encryptable
|
||||
# t.confirmable
|
||||
# t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %>
|
||||
# t.token_authenticatable
|
||||
|
||||
<% for attribute in attributes -%>
|
||||
t.<%= attribute.type %> :<%= attribute.name %>
|
||||
<% end -%>
|
||||
|
||||
# Uncomment below if timestamps were not included in your original model.
|
||||
# t.timestamps
|
||||
end
|
||||
|
||||
add_index :<%= table_name %>, :email, :unique => true
|
||||
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
|
||||
# By default, we don't want to make any assumption about how to roll back a migration when your
|
||||
# model already existed. Please edit below which fields you would like to remove in this migration.
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -9,9 +9,12 @@ module Devise
|
||||
|
||||
hook_for :orm
|
||||
|
||||
class_option :routes, :desc => "Generate routes", :type => :boolean, :default => true
|
||||
|
||||
def add_devise_routes
|
||||
devise_route = "devise_for :#{plural_name}"
|
||||
devise_route += %Q(, :class_name => "#{class_name}") if class_name.include?("::")
|
||||
devise_route << %Q(, :class_name => "#{class_name}") if class_name.include?("::")
|
||||
devise_route << %Q(, :skip => :all) unless options.routes?
|
||||
route devise_route
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'active_support/secure_random'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
module Generators
|
||||
@@ -21,4 +21,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,14 @@ CONTENT
|
||||
def model_exists?
|
||||
File.exists?(File.join(destination_root, model_path))
|
||||
end
|
||||
|
||||
def migration_exists?(table_name)
|
||||
Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
|
||||
end
|
||||
|
||||
def migration_path
|
||||
@migration_path ||= File.join("db", "migrate")
|
||||
end
|
||||
|
||||
def model_path
|
||||
@model_path ||= File.join("app", "models", "#{file_path}.rb")
|
||||
|
||||
@@ -1,20 +1,72 @@
|
||||
require 'tmpdir'
|
||||
|
||||
module Devise
|
||||
module Generators
|
||||
# Include this module in your generator to generate Devise views.
|
||||
# `copy_views` is the main method and by default copies all views
|
||||
# with forms.
|
||||
module ViewPathTemplates #:nodoc:
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
argument :scope, :required => false, :default => nil,
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
public_task :copy_views
|
||||
end
|
||||
|
||||
def copy_views
|
||||
view_directory :confirmations
|
||||
view_directory :passwords
|
||||
view_directory :registrations
|
||||
view_directory :sessions
|
||||
view_directory :unlocks
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def view_directory(name)
|
||||
directory name.to_s, "#{target_path}/#{name}"
|
||||
end
|
||||
|
||||
def target_path
|
||||
@target_path ||= "app/views/#{scope || :devise}"
|
||||
end
|
||||
end
|
||||
|
||||
class SharedViewsGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
desc "Copies shared Devise views to your application."
|
||||
|
||||
# Override copy_views to just copy mailer and shared.
|
||||
def copy_views
|
||||
view_directory :mailer
|
||||
view_directory :shared
|
||||
end
|
||||
end
|
||||
|
||||
class FormForGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
desc "Copies default Devise views to your application."
|
||||
end
|
||||
|
||||
class SimpleFormForGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../templates/simple_form_for", __FILE__)
|
||||
desc "Copies simple form enabled views to your application."
|
||||
end
|
||||
|
||||
class ViewsGenerator < Rails::Generators::Base
|
||||
source_root File.expand_path("../../../../app/views", __FILE__)
|
||||
desc "Copies all Devise views to your application."
|
||||
desc "Copies Devise views to your application."
|
||||
|
||||
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', 'haml' and 'slim'."
|
||||
invoke SharedViewsGenerator
|
||||
|
||||
def copy_views
|
||||
directory "devise", "app/views/#{scope || :devise}"
|
||||
end
|
||||
hook_for :form_builder, :aliases => "-b",
|
||||
:desc => "Form builder to be used",
|
||||
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# four configuration values can also be set straight in your models.
|
||||
Devise.setup do |config|
|
||||
# ==> Mailer Configuration
|
||||
# Configure the e-mail address which will be shown in DeviseMailer.
|
||||
# Configure the e-mail address which will be shown in Devise::Mailer,
|
||||
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
|
||||
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
|
||||
|
||||
# Configure the class responsible to send e-mails.
|
||||
@@ -36,6 +37,11 @@ Devise.setup do |config|
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Configure which authentication keys should have whitespace stripped.
|
||||
# These keys will have whitespace before and after removed upon creating or
|
||||
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||
config.strip_whitespace_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
@@ -48,21 +54,29 @@ Devise.setup do |config|
|
||||
# The realm used in Http Basic Authentication. "Application" by default.
|
||||
# config.http_authentication_realm = "Application"
|
||||
|
||||
# It will change confirmation, password recovery and other workflows
|
||||
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||
# Does not affect registerable.
|
||||
# config.paranoid = true
|
||||
|
||||
# ==> Configuration for :database_authenticatable
|
||||
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
||||
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||
config.stretches = 10
|
||||
#
|
||||
# Limiting the stretches to just one in testing will increase the performance of
|
||||
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
|
||||
# a value less than 10 in other environments.
|
||||
config.stretches = Rails.env.test? ? 1 : 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
# config.pepper = <%= SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
# he will be able to access your application without confirming. Default is 0.days
|
||||
# When confirm_within is zero, the user won't be able to sign in without confirming.
|
||||
# You can use this to let your user access some features of your application
|
||||
# without confirming the account, but blocking it after a certain period
|
||||
# (ie 2 days).
|
||||
# A period that the user is allowed to access the website even without
|
||||
# confirming his account. For instance, if set to 2.days, the user will be
|
||||
# able to access the website for two days without confirming his account,
|
||||
# access will be blocked just in the third day. Default is 0.days, meaning
|
||||
# the user cannot access the website without confirming his account.
|
||||
# config.confirm_within = 2.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
@@ -90,8 +104,10 @@ Devise.setup do |config|
|
||||
# Range for password length. Default is 6..128.
|
||||
# config.password_length = 6..128
|
||||
|
||||
# Regex to use to validate the email address
|
||||
# config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
# Email regex used to validate email formats. It simply asserts that
|
||||
# an one (and only one) @ exists in the given string. This is mainly
|
||||
# to give user feedback and not to assert the e-mail validity.
|
||||
# config.email_regexp = /\A[^@]+@[^@]+\z/
|
||||
|
||||
# ==> Configuration for :timeoutable
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
@@ -174,8 +190,8 @@ Devise.setup do |config|
|
||||
# Explorer requests.
|
||||
# config.navigational_formats = [:"*/*", "*/*", :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :get.
|
||||
# config.sign_out_via = :get
|
||||
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||
config.sign_out_via = :delete
|
||||
|
||||
# ==> OmniAuth
|
||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<h2>Resend confirmation instructions</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Resend confirmation instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -0,0 +1,19 @@
|
||||
<h2>Change your password</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<%= f.input :reset_password_token, :as => :hidden %>
|
||||
<%= f.full_error :reset_password_token %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :password, :label => "New password", :required => true %>
|
||||
<%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Change my password" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -0,0 +1,15 @@
|
||||
<h2>Forgot your password?</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Send me reset password instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -0,0 +1,22 @@
|
||||
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
<%= f.input :password, :hint => "leave it blank if you don't want to change it", :required => false %>
|
||||
<%= f.input :password_confirmation, :required => false %>
|
||||
<%= f.input :current_password, :hint => "we need your current password to confirm your changes", :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Update" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h3>Cancel my account</h3>
|
||||
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
|
||||
|
||||
<%= link_to "Back", :back %>
|
||||
@@ -0,0 +1,17 @@
|
||||
<h2>Sign up</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
<%= f.input :password, :required => true %>
|
||||
<%= f.input :password_confirmation, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Sign up" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -0,0 +1,15 @@
|
||||
<h2>Sign in</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => false, :autofocus => true %>
|
||||
<%= f.input :password, :required => false %>
|
||||
<%= f.input :remember_me, :as => :boolean if devise_mapping.rememberable? %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Sign in" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -0,0 +1,15 @@
|
||||
<h2>Resend unlock instructions</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.button :submit, "Resend unlock instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
@@ -45,6 +45,11 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
@controller.authenticate_user!
|
||||
end
|
||||
|
||||
test 'proxy authenticate_user! options to authenticate with user scope' do
|
||||
@mock_warden.expects(:authenticate!).with(:scope => :user, :recall => "foo")
|
||||
@controller.authenticate_user!(:recall => "foo")
|
||||
end
|
||||
|
||||
test 'proxy authenticate_admin! to authenticate with admin scope' do
|
||||
@mock_warden.expects(:authenticate!).with(:scope => :admin)
|
||||
@controller.authenticate_admin!
|
||||
@@ -106,7 +111,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(user)
|
||||
@mock_warden.expects(:set_user).never
|
||||
@controller.sign_in(user)
|
||||
assert @controller.sign_in(user)
|
||||
end
|
||||
|
||||
test 'sign in again when the user is already in only if force is given' do
|
||||
|
||||
@@ -39,14 +39,21 @@ class HelpersTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
test 'require no authentication tests current mapping' do
|
||||
@mock_warden.expects(:authenticated?).with(:user).returns(true)
|
||||
@mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
|
||||
@mock_warden.expects(:user).with(:user).returns(User.new)
|
||||
@controller.expects(:redirect_to).with(root_path)
|
||||
@controller.send :require_no_authentication
|
||||
end
|
||||
|
||||
test 'require no authentication skips if no inputs are available' do
|
||||
Devise.mappings[:user].expects(:no_input_strategies).returns([])
|
||||
@mock_warden.expects(:authenticate?).never
|
||||
@controller.expects(:redirect_to).never
|
||||
@controller.send :require_no_authentication
|
||||
end
|
||||
|
||||
test 'require no authentication sets a flash message' do
|
||||
@mock_warden.expects(:authenticated?).with(:user).returns(true)
|
||||
@mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
|
||||
@mock_warden.expects(:user).with(:user).returns(User.new)
|
||||
@controller.expects(:redirect_to).with(root_path)
|
||||
@controller.send :require_no_authentication
|
||||
|
||||
@@ -2,6 +2,10 @@ require 'test_helper'
|
||||
require 'ostruct'
|
||||
|
||||
class FailureTest < ActiveSupport::TestCase
|
||||
class RootFailureApp < Devise::FailureApp
|
||||
undef_method :new_user_session_path
|
||||
end
|
||||
|
||||
def self.context(name, &block)
|
||||
instance_eval(&block)
|
||||
end
|
||||
@@ -18,27 +22,31 @@ class FailureTest < ActiveSupport::TestCase
|
||||
'warden' => OpenStruct.new(:message => nil)
|
||||
}.merge!(env_params)
|
||||
|
||||
@response = Devise::FailureApp.call(env).to_a
|
||||
@response = (env.delete(:app) || Devise::FailureApp).call(env).to_a
|
||||
@request = ActionDispatch::Request.new(env)
|
||||
end
|
||||
|
||||
context 'When redirecting' do
|
||||
test 'return 302 status' do
|
||||
call_failure
|
||||
assert_equal 302, @response.first
|
||||
end
|
||||
|
||||
test 'return 302 status for wildcard requests' do
|
||||
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
|
||||
assert_equal 302, @response.first
|
||||
end
|
||||
|
||||
test 'return to the default redirect location' do
|
||||
call_failure
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'return to the default redirect location for wildcard requests' do
|
||||
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'return to the root path if no session path is available' do
|
||||
call_failure :app => RootFailureApp
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
|
||||
assert_equal 'http://test.host/', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'uses the proxy failure message as symbol' do
|
||||
call_failure('warden' => OpenStruct.new(:message => :test))
|
||||
assert_equal 'test', @request.flash[:alert]
|
||||
@@ -69,7 +77,7 @@ 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)
|
||||
@@ -173,7 +181,7 @@ 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 },
|
||||
@@ -182,9 +190,9 @@ class FailureTest < ActiveSupport::TestCase
|
||||
}
|
||||
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.')
|
||||
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 },
|
||||
@@ -193,7 +201,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
}
|
||||
call_failure(env)
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('Your account was not activated yet.')
|
||||
assert @response.third.body.include?('Your account was not activated yet.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,9 +13,22 @@ if DEVISE_ORM == :active_record
|
||||
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
|
||||
assert_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
|
||||
test "update model migration when model exists" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb"
|
||||
run_generator %w(monster)
|
||||
assert_migration "db/migrate/add_devise_to_monsters.rb"
|
||||
end
|
||||
|
||||
test "all files are properly deleted" do
|
||||
run_generator %w(monster)
|
||||
run_generator %w(monster)
|
||||
assert_migration "db/migrate/devise_create_monsters.rb"
|
||||
assert_migration "db/migrate/add_devise_to_monsters.rb"
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_migration "db/migrate/add_devise_to_monsters.rb"
|
||||
assert_migration "db/migrate/devise_create_monsters.rb"
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_file "app/models/monster.rb"
|
||||
assert_no_migration "db/migrate/devise_create_monsters.rb"
|
||||
|
||||
@@ -22,6 +22,12 @@ class DeviseGeneratorTest < Rails::Generators::TestCase
|
||||
assert_file "config/routes.rb", match
|
||||
end
|
||||
|
||||
test "route generation with skip routes" do
|
||||
run_generator %w(monster name:string --skip-routes)
|
||||
match = /devise_for :monsters, :skip => :all/
|
||||
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")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require "test_helper"
|
||||
|
||||
if DEVISE_ORM == :mongo_id
|
||||
require "generators/mongo_id/devise_generator"
|
||||
if DEVISE_ORM == :mongoid
|
||||
require "generators/mongoid/devise_generator"
|
||||
|
||||
class MongoidGeneratorTest < Rails::Generators::TestCase
|
||||
tests Mongoid::Generators::DeviseGenerator
|
||||
@@ -19,4 +19,5 @@ if DEVISE_ORM == :mongo_id
|
||||
assert_no_file "app/models/monster.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,6 +18,16 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
assert_files "admins"
|
||||
end
|
||||
|
||||
test "Assert views with simple form" do
|
||||
run_generator %w(-b simple_form_for)
|
||||
assert_files
|
||||
assert_file "app/views/devise/confirmations/new.html.erb", /simple_form_for/
|
||||
|
||||
run_generator %w(users -b simple_form_for)
|
||||
assert_files "users"
|
||||
assert_file "app/views/users/confirmations/new.html.erb", /simple_form_for/
|
||||
end
|
||||
|
||||
def assert_files(scope = nil, template_engine = nil)
|
||||
scope = "devise" if scope.nil?
|
||||
assert_file "app/views/#{scope}/confirmations/new.html.erb"
|
||||
|
||||
51
test/helpers/devise_helper_test.rb
Normal file
51
test/helpers/devise_helper_test.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'test_helper'
|
||||
|
||||
class DeviseHelperTest < ActionController::IntegrationTest
|
||||
setup do
|
||||
model_labels = { :models => { :user => "utilisateur" } }
|
||||
|
||||
I18n.backend.store_translations :fr,
|
||||
{
|
||||
:errors => { :messages => { :not_saved => {
|
||||
:one => "Erreur lors de l'enregistrement de '%{resource}': 1 erreur.",
|
||||
:other => "Erreur lors de l'enregistrement de '%{resource}': %{count} erreurs."
|
||||
} } },
|
||||
:activerecord => model_labels,
|
||||
:mongoid => model_labels
|
||||
}
|
||||
|
||||
I18n.locale = 'fr'
|
||||
end
|
||||
|
||||
teardown do
|
||||
I18n.locale = 'en'
|
||||
end
|
||||
|
||||
test 'test errors.messages.not_saved with single error from i18n' do
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_have_selector '#error_explanation'
|
||||
assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 1 erreur"
|
||||
end
|
||||
|
||||
test 'test errors.messages.not_saved with multiple errors from i18n' do
|
||||
# Dirty tracking behavior prevents email validations from being applied:
|
||||
# https://github.com/mongoid/mongoid/issues/756
|
||||
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
|
||||
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'invalid_email'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user321'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_have_selector '#error_explanation'
|
||||
assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 2 erreurs"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -101,6 +101,54 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
|
||||
assert_contain 'Private!'
|
||||
end
|
||||
|
||||
test 'signed in as admin should get admin dashboard' do
|
||||
sign_in_as_admin
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get dashboard_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/admin'
|
||||
assert_contain 'Admin dashboard'
|
||||
end
|
||||
|
||||
test 'signed in as user should get user dashboard' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
|
||||
get dashboard_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/user'
|
||||
assert_contain 'User dashboard'
|
||||
end
|
||||
|
||||
test 'not signed in should get no dashboard' do
|
||||
assert_raises ActionController::RoutingError do
|
||||
get dashboard_path
|
||||
end
|
||||
end
|
||||
|
||||
test 'signed in user should not see join page' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
|
||||
assert_raises ActionController::RoutingError do
|
||||
get join_path
|
||||
end
|
||||
end
|
||||
|
||||
test 'not signed in should see join page' do
|
||||
get join_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/join'
|
||||
assert_contain 'Join'
|
||||
end
|
||||
|
||||
test 'signed in as user should not be able to access admins actions' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -306,6 +354,20 @@ class AuthenticationWithScopesTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
test 'handles unverified requests gets rid of caches' do
|
||||
swap UsersController, :allow_forgery_protection => true do
|
||||
post exhibit_user_url(1)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
|
||||
post exhibit_user_url(1)
|
||||
assert_not warden.authenticated?(:user)
|
||||
assert_equal "User is not authenticated", response.body
|
||||
end
|
||||
end
|
||||
|
||||
test 'uses the custom controller with the custom controller view' do
|
||||
get '/admin_area/sign_in'
|
||||
assert_contain 'Sign in'
|
||||
@@ -314,8 +376,9 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'render 404 on roles without routes' do
|
||||
get '/admin_area/password/new'
|
||||
assert_equal 404, response.status
|
||||
assert_raise ActionController::RoutingError do
|
||||
get '/admin_area/password/new'
|
||||
end
|
||||
end
|
||||
|
||||
test 'does not intercept Rails 401 responses' do
|
||||
@@ -338,14 +401,14 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
|
||||
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
|
||||
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>\n <email></email>\n <password nil=\"true\"></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
|
||||
assert_match '"password":null', response.body
|
||||
end
|
||||
|
||||
test 'sign in stub in json with non attribute key' do
|
||||
@@ -353,7 +416,7 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
get new_user_session_path(:format => 'json')
|
||||
assert_match '{"user":{', response.body
|
||||
assert_match '"other_key":null', response.body
|
||||
assert_match '"password":""', response.body
|
||||
assert_match '"password":null', response.body
|
||||
end
|
||||
end
|
||||
|
||||
@@ -391,6 +454,23 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationKeysTest < ActionController::IntegrationTest
|
||||
test 'missing authentication keys cause authentication to abort' do
|
||||
swap Devise, :authentication_keys => [:subdomain] do
|
||||
sign_in_as_user
|
||||
assert_contain "Invalid email or password."
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'missing authentication keys cause authentication to abort unless marked as not required' do
|
||||
swap Devise, :authentication_keys => { :email => true, :subdomain => false } do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationRequestKeysTest < ActionController::IntegrationTest
|
||||
test 'request keys are used on authentication' do
|
||||
host! 'foo.bar.baz'
|
||||
@@ -446,7 +526,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides only delete' do
|
||||
sign_in!(:sign_out_via_delete)
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_delete)
|
||||
end
|
||||
|
||||
@@ -458,7 +540,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides only post' do
|
||||
sign_in!(:sign_out_via_post)
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_post)
|
||||
end
|
||||
|
||||
@@ -476,7 +560,9 @@ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
|
||||
|
||||
test 'do not allow sign out via get when sign_out_via provides delete and post' do
|
||||
sign_in!(:sign_out_via_delete_or_post)
|
||||
get destroy_sign_out_via_delete_or_post_session_path
|
||||
assert_raise ActionController::RoutingError do
|
||||
get destroy_sign_out_via_delete_or_post_session_path
|
||||
end
|
||||
assert warden.authenticated?(:sign_out_via_delete_or_post)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,6 +37,15 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert user.reload.confirmed?
|
||||
end
|
||||
|
||||
test 'user should be redirected to a custom path after confirmation' do
|
||||
Devise::ConfirmationsController.any_instance.stubs(:after_confirmation_path_for).returns("/?custom=1")
|
||||
|
||||
user = create_user(:confirm => false)
|
||||
visit_user_confirmation_with_token(user.confirmation_token)
|
||||
|
||||
assert_current_url "/?custom=1"
|
||||
end
|
||||
|
||||
test 'already confirmed user should not be able to confirm the account again' do
|
||||
user = create_user(:confirm => false)
|
||||
user.confirmed_at = Time.now
|
||||
@@ -60,7 +69,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert_contain 'already confirmed'
|
||||
end
|
||||
|
||||
test 'sign in user automatically after confirming it\'s email' do
|
||||
test 'sign in user automatically after confirming its email' do
|
||||
user = create_user(:confirm => false)
|
||||
visit_user_confirmation_with_token(user.confirmation_token)
|
||||
|
||||
@@ -106,7 +115,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
user = create_user(:confirm => false)
|
||||
post user_confirmation_path(:format => 'xml'), :user => { :email => user.email }
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
assert_equal response.body, {}.to_xml
|
||||
end
|
||||
|
||||
test 'resent confirmation token with invalid E-Mail in XML format should return invalid response' do
|
||||
@@ -129,4 +138,42 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test 'request an account confirmation account with JSON, should return an empty JSON' do
|
||||
user = create_user(:confirm => false)
|
||||
|
||||
post user_confirmation_path, :user => { :email => user.email }, :format => :json
|
||||
assert_response :success
|
||||
assert_equal response.body, {}.to_json
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a valid e-mail, should not say that the e-mail is valid" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:confirm => false)
|
||||
visit new_user_session_path
|
||||
|
||||
click_link "Didn't receive confirmation instructions?"
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend confirmation instructions'
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/confirmation"
|
||||
end
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a invalid e-mail, should not say that the e-mail is invalid" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit new_user_session_path
|
||||
|
||||
click_link "Didn't receive confirmation instructions?"
|
||||
fill_in 'email', :with => "idonthavethisemail@gmail.com"
|
||||
click_button 'Resend confirmation instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/confirmation"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,6 +22,28 @@ class DatabaseAuthenticationTest < ActionController::IntegrationTest
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'sign in with email including extra spaces should succeed when email is in the list of strip whitespace keys' do
|
||||
create_user(:email => ' foo@bar.com ')
|
||||
|
||||
sign_in_as_user do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign in with email including extra spaces should fail when email is NOT the list of strip whitespace keys' do
|
||||
swap Devise, :strip_whitespace_keys => [] do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
sign_in_as_user do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'sign in should not authenticate if not using proper authentication keys' do
|
||||
swap Devise, :authentication_keys => [:username] do
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
require 'test_helper'
|
||||
|
||||
class HttpAuthenticationTest < ActionController::IntegrationTest
|
||||
test 'handles unverified requests gets rid of caches but continues signed in' do
|
||||
swap UsersController, :allow_forgery_protection => true do
|
||||
create_user
|
||||
post exhibit_user_url(1), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("user@test.com:123456")}"
|
||||
assert warden.authenticated?(:user)
|
||||
assert_equal "User is authenticated", response.body
|
||||
end
|
||||
end
|
||||
|
||||
test 'sign in should authenticate with http' do
|
||||
sign_in_as_new_user_with_http
|
||||
|
||||
@@ -37,7 +37,7 @@ class LockTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'unlocked pages should not be available if email strategy is disabled' do
|
||||
visit "/admins/sign_in"
|
||||
visit "/admin_area/sign_in"
|
||||
|
||||
assert_raise Webrat::NotFoundError do
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
@@ -47,8 +47,9 @@ class LockTest < ActionController::IntegrationTest
|
||||
visit new_admin_unlock_path
|
||||
end
|
||||
|
||||
visit "/admins/unlock/new"
|
||||
assert_response :not_found
|
||||
assert_raise ActionController::RoutingError do
|
||||
visit "/admin_area/unlock/new"
|
||||
end
|
||||
end
|
||||
|
||||
test 'user with invalid unlock token should not be able to unlock an account' do
|
||||
@@ -72,7 +73,7 @@ class LockTest < ActionController::IntegrationTest
|
||||
assert_not user.reload.access_locked?
|
||||
end
|
||||
|
||||
test "sign in user automatically after unlocking it's account" do
|
||||
test "sign in user automatically after unlocking its account" do
|
||||
user = create_user(:locked => true)
|
||||
visit_user_unlock_with_token(user.unlock_token)
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -112,7 +113,7 @@ class LockTest < ActionController::IntegrationTest
|
||||
|
||||
post user_unlock_path(:format => 'xml'), :user => {:email => user.email}
|
||||
assert_response :success
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
|
||||
assert_equal response.body, {}.to_xml
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
@@ -140,4 +141,61 @@ class LockTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test "when using json to ask a unlock request, should not return the user" do
|
||||
user = create_user(:locked => true)
|
||||
post user_unlock_path(:format => "json", :user => {:email => user.email})
|
||||
assert_response :success
|
||||
assert_equal response.body, {}.to_json
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that exists it should not say that it exists if it is locked" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:locked => true)
|
||||
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
end
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that exists it should not say that it exists if it is not locked" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user(:locked => false)
|
||||
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
end
|
||||
end
|
||||
|
||||
test "in paranoid mode, when trying to unlock an user that does not exists it should not say that it does not exists" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit new_user_session_path
|
||||
click_link "Didn't receive unlock instructions?"
|
||||
|
||||
fill_in 'email', :with => "arandomemail@hotmail.com"
|
||||
click_button 'Resend unlock instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
assert_current_url "/users/unlock"
|
||||
|
||||
assert_contain "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -114,9 +114,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
test "generates a proper link when SCRIPT_NAME is set" do
|
||||
header 'SCRIPT_NAME', '/q'
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
|
||||
assert_equal '/q/users/auth/facebook', current_url
|
||||
assert_select "a", :href => "/q/users/auth/facebook"
|
||||
end
|
||||
|
||||
test "handles callback error parameter according to the specification" do
|
||||
|
||||
@@ -17,7 +17,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
click_button 'Send me reset password instructions'
|
||||
end
|
||||
|
||||
def reset_password(options={}, &block)
|
||||
def reset_password(options={}, &block)
|
||||
visit edit_user_password_path(:reset_password_token => options[:reset_password_token]) unless options[:visit] == false
|
||||
assert_response :success
|
||||
|
||||
@@ -29,11 +29,11 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
|
||||
test 'reset password with email of different case should succeed when email is in the list of case insensitive keys' do
|
||||
create_user(:email => 'Foo@Bar.com')
|
||||
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
|
||||
assert_current_url '/users/sign_in'
|
||||
assert_contain 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
end
|
||||
@@ -41,11 +41,11 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
test 'reset password with email of different case should fail when email is NOT the list of case insensitive keys' do
|
||||
swap Devise, :case_insensitive_keys => [] do
|
||||
create_user(:email => 'Foo@Bar.com')
|
||||
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => 'foo@bar.com'
|
||||
end
|
||||
|
||||
|
||||
assert_response :success
|
||||
assert_current_url '/users/password'
|
||||
assert_have_selector "input[type=email][value='foo@bar.com']"
|
||||
@@ -53,6 +53,32 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'reset password with email with extra whitespace should succeed when email is in the list of strip whitespace keys' do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_current_url '/users/sign_in'
|
||||
assert_contain 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
end
|
||||
|
||||
test 'reset password with email with extra whitespace should fail when email is NOT the list of strip whitespace keys' do
|
||||
swap Devise, :strip_whitespace_keys => [] do
|
||||
create_user(:email => 'foo@bar.com')
|
||||
|
||||
request_forgot_password do
|
||||
fill_in 'email', :with => ' foo@bar.com '
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_current_url '/users/password'
|
||||
assert_have_selector "input[type=email][value=' foo@bar.com ']"
|
||||
assert_contain 'not found'
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticated user should not be able to visit forgot password page' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -121,7 +147,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert_current_url '/'
|
||||
assert_contain 'Your password was changed successfully.'
|
||||
assert_contain 'Your password was changed successfully. You are now signed in.'
|
||||
assert user.reload.valid_password?('987654321')
|
||||
end
|
||||
|
||||
@@ -140,7 +166,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert user.reload.valid_password?('987654321')
|
||||
end
|
||||
|
||||
test 'sign in user automatically after changing it\'s password' do
|
||||
test 'sign in user automatically after changing its password' do
|
||||
user = create_user
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
@@ -148,20 +174,31 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'does not sign in user automatically after changing it\'s password if it\'s not active' do
|
||||
test 'does not sign in user automatically after changing its password if it\'s locked' do
|
||||
user = create_user(:locked => true)
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert_contain 'Your password was changed successfully.'
|
||||
assert_not_contain 'You are now signed in.'
|
||||
assert_equal new_user_session_path, @request.path
|
||||
assert !warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign in user automatically and confirm after changing its password if it\'s not confirmed' do
|
||||
user = create_user(:confirm => false)
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert_equal new_user_session_path, @request.path
|
||||
assert !warden.authenticated?(:user)
|
||||
assert warden.authenticated?(:user)
|
||||
assert user.reload.confirmed?
|
||||
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>)
|
||||
assert_equal response.body, { }.to_xml
|
||||
end
|
||||
|
||||
test 'reset password request with invalid E-Mail in XML format should return valid response' do
|
||||
@@ -194,4 +231,38 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert_response :unprocessable_entity
|
||||
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>)
|
||||
end
|
||||
|
||||
test "when using json requests to ask a confirmable request, should not return the object" do
|
||||
user = create_user(:confirm => false)
|
||||
|
||||
post user_password_path(:format => :json), :user => { :email => user.email }
|
||||
|
||||
assert_response :success
|
||||
assert_equal response.body, "{}"
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with an invalid e-mail, asking to reset a password should display a message that does not indicates that the e-mail does not exists in the database" do
|
||||
swap Devise, :paranoid => true do
|
||||
visit_new_password_path
|
||||
fill_in "email", :with => "arandomemail@test.com"
|
||||
click_button 'Send me reset password instructions'
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/password"
|
||||
end
|
||||
end
|
||||
|
||||
test "when in paranoid mode and with a valid e-mail, asking to reset password should display a message that does not indicates that the email exists in the database and redirect to the failure route" do
|
||||
swap Devise, :paranoid => true do
|
||||
user = create_user
|
||||
visit_new_password_path
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Send me reset password instructions'
|
||||
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/password"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -69,6 +69,10 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'a guest user cannot sign up with invalid information' do
|
||||
# Dirty tracking behavior prevents email validations from being applied:
|
||||
# https://github.com/mongoid/mongoid/issues/756
|
||||
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
|
||||
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'invalid_email'
|
||||
@@ -87,6 +91,10 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'a guest should not sign up with email/password that already exists' do
|
||||
# Dirty tracking behavior prevents email validations from being applied:
|
||||
# https://github.com/mongoid/mongoid/issues/756
|
||||
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
|
||||
|
||||
user = create_user
|
||||
get new_user_registration_path
|
||||
|
||||
@@ -211,14 +219,14 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
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
|
||||
assert_no_match(/<confirmation-token/, response.body)
|
||||
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
|
||||
assert_no_match(/"confirmation_token"/, response.body)
|
||||
end
|
||||
|
||||
test 'an admin sign up with valid information in XML format should return valid response' do
|
||||
|
||||
@@ -38,6 +38,18 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
assert_nil request.cookies["remember_user_cookie"]
|
||||
end
|
||||
|
||||
test 'handles unverified requests gets rid of caches' do
|
||||
swap UsersController, :allow_forgery_protection => true do
|
||||
post exhibit_user_url(1)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
create_user_and_remember
|
||||
post exhibit_user_url(1)
|
||||
assert_equal "User is not authenticated", response.body
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'generate remember token after sign in' do
|
||||
user = sign_in_as_user :remember_me => true
|
||||
assert request.cookies["remember_user_token"]
|
||||
@@ -69,7 +81,14 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.user(:user) == user
|
||||
assert_match /remember_user_token[^\n]*HttpOnly\n/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
|
||||
assert_match /remember_user_token[^\n]*HttpOnly/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
|
||||
end
|
||||
|
||||
test 'remember the user before sign up and redirect him to his home' do
|
||||
user = create_user_and_remember
|
||||
get new_user_registration_path
|
||||
assert warden.authenticated?(:user)
|
||||
assert_redirected_to root_path
|
||||
end
|
||||
|
||||
test 'cookies are destroyed on unverified requests' do
|
||||
|
||||
@@ -13,6 +13,17 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and value through params, when params with the same key as scope exist' do
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
user = create_user_with_authentication_token
|
||||
post exhibit_user_path(user), Devise.token_authentication_key => user.authentication_token, :user => { :some => "data" }
|
||||
|
||||
assert_response :success
|
||||
assert_contain 'User is authenticated'
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key but does not store if stateless' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :stateless_token => true do
|
||||
sign_in_as_new_user_with_token
|
||||
|
||||
@@ -61,4 +61,21 @@ class TrackableHooksTest < ActionController::IntegrationTest
|
||||
assert_nil user.last_sign_in_at
|
||||
end
|
||||
end
|
||||
|
||||
test "do not track if devise.skip_trackable is set" do
|
||||
user = create_user
|
||||
sign_in_as_user do
|
||||
header 'devise.skip_trackable', '1'
|
||||
end
|
||||
user.reload
|
||||
assert_equal 0, user.sign_in_count
|
||||
visit destroy_user_session_path
|
||||
|
||||
sign_in_as_user do
|
||||
header 'devise.skip_trackable', false
|
||||
end
|
||||
user.reload
|
||||
assert_equal 1, user.sign_in_count
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
|
||||
|
||||
def setup
|
||||
setup_mailer
|
||||
Devise.mailer = 'Devise::Mailer'
|
||||
Devise.mailer_sender = 'test@example.com'
|
||||
end
|
||||
|
||||
@@ -35,6 +36,11 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
|
||||
assert_equal ['test@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup sender from custom mailer defaults' do
|
||||
Devise.mailer = 'Users::Mailer'
|
||||
assert_equal ['custom@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup reply to as copy from sender' do
|
||||
assert_equal ['test@example.com'], mail.reply_to
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
|
||||
|
||||
def setup
|
||||
setup_mailer
|
||||
Devise.mailer = 'Devise::Mailer'
|
||||
Devise.mailer_sender = 'test@example.com'
|
||||
end
|
||||
|
||||
@@ -38,6 +39,11 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
|
||||
assert_equal ['test@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup sender from custom mailer defaults' do
|
||||
Devise.mailer = 'Users::Mailer'
|
||||
assert_equal ['custom@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup reply to as copy from sender' do
|
||||
assert_equal ['test@example.com'], mail.reply_to
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ class UnlockInstructionsTest < ActionMailer::TestCase
|
||||
|
||||
def setup
|
||||
setup_mailer
|
||||
Devise.mailer = 'Devise::Mailer'
|
||||
Devise.mailer_sender = 'test@example.com'
|
||||
end
|
||||
|
||||
@@ -38,6 +39,11 @@ class UnlockInstructionsTest < ActionMailer::TestCase
|
||||
assert_equal ['test@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup sender from custom mailer defaults' do
|
||||
Devise.mailer = 'Users::Mailer'
|
||||
assert_equal ['custom@example.com'], mail.from
|
||||
end
|
||||
|
||||
test 'setup reply to as copy from sender' do
|
||||
assert_equal ['test@example.com'], mail.reply_to
|
||||
end
|
||||
|
||||
@@ -31,6 +31,10 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal "admin_area", Devise.mappings[:admin].path
|
||||
end
|
||||
|
||||
test 'allows to skip all routes' do
|
||||
assert_equal [], Devise.mappings[:skip_admin].used_routes
|
||||
end
|
||||
|
||||
test 'sign_out_via defaults to :get' do
|
||||
assert_equal :get, Devise.mappings[:user].sign_out_via
|
||||
end
|
||||
@@ -50,6 +54,11 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal [:rememberable, :database_authenticatable], Devise.mappings[:admin].strategies
|
||||
end
|
||||
|
||||
test 'has no input strategies depending on the model declaration' do
|
||||
assert_equal [:rememberable, :token_authenticatable], Devise.mappings[:user].no_input_strategies
|
||||
assert_equal [:rememberable], Devise.mappings[:admin].no_input_strategies
|
||||
end
|
||||
|
||||
test 'find scope for a given object' do
|
||||
assert_equal :user, Devise::Mapping.find_scope!(User)
|
||||
assert_equal :user, Devise::Mapping.find_scope!(:user)
|
||||
|
||||
@@ -121,7 +121,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
assert_equal "not found", confirmation_user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should send email instructions for the user confirm it\'s email' do
|
||||
test 'should send email instructions for the user confirm its email' do
|
||||
user = create_user
|
||||
assert_email_sent do
|
||||
User.send_confirmation_instructions(:email => user.email)
|
||||
@@ -219,7 +219,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
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
|
||||
test 'should find a user to send email instructions for the user confirm its 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)
|
||||
|
||||
@@ -11,6 +11,39 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
user.save!
|
||||
assert_equal email.downcase, user.email
|
||||
end
|
||||
|
||||
test 'should remove whitespace from strip whitespace keys when saving' do
|
||||
# strip_whitespace_keys is set to :email by default.
|
||||
email = ' foo@bar.com '
|
||||
user = new_user(:email => email)
|
||||
|
||||
assert_equal email, user.email
|
||||
user.save!
|
||||
assert_equal email.strip, user.email
|
||||
end
|
||||
|
||||
test 'find_for_authentication and filter_auth_params should not modify the conditions hash' do
|
||||
FilterAuthUser = Class.new(User) do
|
||||
def self.filter_auth_params(conditions)
|
||||
if conditions.is_a?(Hash) && login = conditions.delete('login')
|
||||
key = login.include?('@') ? :email : :username
|
||||
conditions[key] = login
|
||||
end
|
||||
super(conditions)
|
||||
end
|
||||
end
|
||||
|
||||
conditions = { 'login' => 'foo@bar.com' }
|
||||
FilterAuthUser.find_for_authentication(conditions)
|
||||
|
||||
assert_equal({ 'login' => 'foo@bar.com' }, conditions)
|
||||
end
|
||||
|
||||
test "filter_auth_params should not convert booleans and integer to strings" do
|
||||
conditions = { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => (1..10) }
|
||||
conditions = User.__send__(:filter_auth_params, conditions)
|
||||
assert_equal( { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => "1..10" }, conditions)
|
||||
end
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
user = new_user
|
||||
@@ -70,7 +103,7 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
:password => 'pass321', :password_confirmation => 'pass321')
|
||||
assert user.reload.valid_password?('pass321')
|
||||
end
|
||||
|
||||
|
||||
test 'should add an error to current password when it is invalid' do
|
||||
user = create_user
|
||||
assert_not user.update_with_password(:current_password => 'other',
|
||||
@@ -87,6 +120,15 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert_match "can't be blank", user.errors[:current_password].join
|
||||
end
|
||||
|
||||
test 'should run validations even when current password is invalid or blank' do
|
||||
user = UserWithValidation.create!(valid_attributes)
|
||||
user.save
|
||||
assert user.persisted?
|
||||
assert_not user.update_with_password(:username => "")
|
||||
assert_match "usertest", user.reload.username
|
||||
assert_match "can't be blank", user.errors[:username].join
|
||||
end
|
||||
|
||||
test 'should ignore password and its confirmation if they are blank' do
|
||||
user = create_user
|
||||
assert user.update_with_password(:current_password => '123456', :email => "new@example.com")
|
||||
@@ -108,6 +150,19 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert user.password_confirmation.blank?
|
||||
end
|
||||
|
||||
test 'should update the user without password' do
|
||||
user = create_user
|
||||
user.update_without_password(:email => 'new@example.com')
|
||||
assert_equal 'new@example.com', user.email
|
||||
end
|
||||
|
||||
test 'should not update password without password' do
|
||||
user = create_user
|
||||
user.update_without_password(:password => 'pass321', :password_confirmation => 'pass321')
|
||||
assert !user.reload.valid_password?('pass321')
|
||||
assert user.valid_password?('123456')
|
||||
end
|
||||
|
||||
test 'downcase_keys with validation' do
|
||||
user = User.create(:email => "HEllO@example.com", :password => "123456")
|
||||
user = User.create(:email => "HEllO@example.com", :password => "123456")
|
||||
|
||||
@@ -31,8 +31,10 @@ class EncryptableTest < ActiveSupport::TestCase
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor Admin, :sha1 do
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
|
||||
assert_equal 'friendly_token', create_admin.password_salt
|
||||
SecureRandom.expects(:base64).with(15).returns('01lI')
|
||||
salt = create_admin.password_salt
|
||||
assert_not_equal '01lI', salt
|
||||
assert_equal 4, salt.size
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -192,16 +192,34 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
|
||||
assert user.valid_password?(old_password)
|
||||
assert_not user.valid_password?('new_password')
|
||||
assert_equal "is invalid", reset_password_user.errors[:reset_password_token].join
|
||||
assert_equal "has expired, please request a new one", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should save the model when the reset_password_sent_at doesnt exist' do
|
||||
user = create_user
|
||||
user.stubs(:respond_to?).with(:reset_password_sent_at=).returns(false)
|
||||
user.stubs(:respond_to?).with(:headers_for).returns(false)
|
||||
def user.respond_to?(meth, *)
|
||||
if meth == :reset_password_sent_at=
|
||||
false
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
user.send_reset_password_instructions
|
||||
user.reload
|
||||
assert_not_nil user.reset_password_token
|
||||
end
|
||||
|
||||
test 'should have valid period if does not respond to reset_password_sent_at' do
|
||||
user = create_user
|
||||
def user.respond_to?(meth, *)
|
||||
if meth == :reset_password_sent_at
|
||||
false
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
assert user.reset_password_period_valid?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,6 +15,14 @@ module SharedRememberableTest
|
||||
resource.forget_me!
|
||||
assert resource.remember_created_at.nil?
|
||||
end
|
||||
|
||||
test 'forget_me should not try to update resource if it has been destroyed' do
|
||||
resource = create_resource
|
||||
resource.destroy
|
||||
resource.expects(:remember_created_at).never
|
||||
resource.expects(:save).never
|
||||
resource.forget_me!
|
||||
end
|
||||
|
||||
test 'remember is expired if not created at timestamp is set' do
|
||||
assert create_resource.remember_expired?
|
||||
|
||||
38
test/models/serializable_test.rb
Normal file
38
test/models/serializable_test.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SerializableTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@user = create_user
|
||||
end
|
||||
|
||||
test 'should not include unsafe keys on XML' do
|
||||
assert_match /email/, @user.to_xml
|
||||
assert_no_match /confirmation-token/, @user.to_xml
|
||||
end
|
||||
|
||||
test 'should not include unsafe keys on XML even if a new except is provided' do
|
||||
assert_no_match /email/, @user.to_xml(:except => :email)
|
||||
assert_no_match /confirmation-token/, @user.to_xml(:except => :email)
|
||||
end
|
||||
|
||||
test 'should include unsafe keys on XML if a force_except is provided' do
|
||||
assert_no_match /email/, @user.to_xml(:force_except => :email)
|
||||
assert_match /confirmation-token/, @user.to_xml(:force_except => :email)
|
||||
end
|
||||
|
||||
test 'should not include unsafe keys on JSON' do
|
||||
assert_match /"email":/, @user.to_json
|
||||
assert_no_match /"confirmation_token":/, @user.to_json
|
||||
end
|
||||
|
||||
test 'should not include unsafe keys on JSON even if a new except is provided' do
|
||||
assert_no_match /"email":/, @user.to_json(:except => :email)
|
||||
assert_no_match /"confirmation_token":/, @user.to_json(:except => :email)
|
||||
end
|
||||
|
||||
test 'should include unsafe keys on JSON if a force_except is provided' do
|
||||
assert_no_match /"email":/, @user.to_json(:force_except => :email)
|
||||
assert_match /"confirmation_token":/, @user.to_json(:force_except => :email)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -27,12 +27,6 @@ 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!
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
require 'test_helper'
|
||||
|
||||
class ValidatableTest < ActiveSupport::TestCase
|
||||
@@ -8,7 +9,7 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
assert_equal 'can\'t be blank', user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should require uniqueness of email, allowing blank' do
|
||||
test 'should require uniqueness of email if email has changed, allowing blank' do
|
||||
existing_user = create_user
|
||||
|
||||
user = new_user(:email => '')
|
||||
@@ -18,22 +19,28 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
user.email = existing_user.email
|
||||
assert user.invalid?
|
||||
assert_match(/taken/, user.errors[:email].join)
|
||||
|
||||
user.save(:validate => false)
|
||||
assert user.valid?
|
||||
end
|
||||
|
||||
test 'should require correct email format, allowing blank' do
|
||||
test 'should require correct email format if email has changed, allowing blank' do
|
||||
user = new_user(:email => '')
|
||||
assert user.invalid?
|
||||
assert_not_equal 'is invalid', user.errors[:email].join
|
||||
|
||||
%w(invalid_email_format email@invalid invalid$character@mail.com other@not 123).each do |email|
|
||||
%w{invalid_email_format 123 $$$ () ☃ bla@bla.}.each do |email|
|
||||
user.email = email
|
||||
assert user.invalid?, 'should be invalid with email ' << email
|
||||
assert_equal 'is invalid', user.errors[:email].join
|
||||
end
|
||||
|
||||
user.save(:validate => false)
|
||||
assert user.valid?
|
||||
end
|
||||
|
||||
test 'should accept valid emails' do
|
||||
%w(a.b.c@example.com test_mail@gmail.com any@any.net email@test.br 123@mail.test).each do |email|
|
||||
%w(a.b.c@example.com test_mail@gmail.com any@any.net email@test.br 123@mail.test 1☃3@mail.test).each do |email|
|
||||
user = new_user(:email => email)
|
||||
assert user.valid?, 'should be valid with email ' << email
|
||||
assert_blank user.errors[:email]
|
||||
@@ -85,12 +92,19 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
user = create_user.reload
|
||||
user.password = user.password_confirmation = nil
|
||||
assert user.valid?
|
||||
|
||||
|
||||
user.password_confirmation = 'confirmation'
|
||||
assert user.invalid?
|
||||
assert_not (user.errors[:password].join =~ /is too long/)
|
||||
end
|
||||
|
||||
test 'should complain about length even if possword is not required' do
|
||||
user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129)
|
||||
user.stubs(:password_required?).returns(false)
|
||||
assert user.invalid?
|
||||
assert_equal 'is too long (maximum is 128 characters)', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'shuold not be included in objects with invalid API' do
|
||||
assert_raise RuntimeError do
|
||||
Class.new.send :include, Devise::Models::Validatable
|
||||
|
||||
@@ -10,6 +10,10 @@ class WithValidation < Admin
|
||||
devise :database_authenticatable, :validatable, :password_length => 2..6
|
||||
end
|
||||
|
||||
class UserWithValidation < User
|
||||
validates_presence_of :username
|
||||
end
|
||||
|
||||
class Several < Admin
|
||||
devise :validatable
|
||||
devise :lockable
|
||||
@@ -38,18 +42,16 @@ 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 options are not applied too 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
|
||||
test 'validations are applied just once' do
|
||||
validators = Several.validators_on :password
|
||||
assert_equal 1, validators.select{ |v| v.kind == :length }.length
|
||||
end
|
||||
|
||||
test 'chosen modules are inheritable' do
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user