mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
273 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba2e44c6a4 | ||
|
|
4f07ed42e3 | ||
|
|
66716023e4 | ||
|
|
4bc2ff997a | ||
|
|
b1633f2454 | ||
|
|
41a91188f5 | ||
|
|
4def600076 | ||
|
|
18a18e4c72 | ||
|
|
85c90671bc | ||
|
|
16b688eced | ||
|
|
37c55eb192 | ||
|
|
2d7dc3e82d | ||
|
|
e7a8a7247c | ||
|
|
c4818a9fb2 | ||
|
|
8c2a7146df | ||
|
|
311e3206c9 | ||
|
|
6ad6b3d2a6 | ||
|
|
471a05fd59 | ||
|
|
7a12655111 | ||
|
|
1b26869b74 | ||
|
|
13f35d80a9 | ||
|
|
1c4faa7d8a | ||
|
|
c26ed53927 | ||
|
|
fe0f6e96b3 | ||
|
|
6dd7ccee68 | ||
|
|
9327cf8af5 | ||
|
|
512b52e23a | ||
|
|
5df7105301 | ||
|
|
a84fdb771f | ||
|
|
ff75341c75 | ||
|
|
f0d48a96ca | ||
|
|
215fdf119e | ||
|
|
985b646ee1 | ||
|
|
622e480c4b | ||
|
|
2e78a46c52 | ||
|
|
b1b6e53d6f | ||
|
|
65325f7f81 | ||
|
|
9bd82e5a24 | ||
|
|
0689b4558e | ||
|
|
dbea934701 | ||
|
|
8e4d5fb38f | ||
|
|
e324ee9823 | ||
|
|
54e9cabf5d | ||
|
|
7a3f6fb53d | ||
|
|
59a9576498 | ||
|
|
57eb3886ba | ||
|
|
fe9e6db0e2 | ||
|
|
db8eeb6c6e | ||
|
|
2b7328535d | ||
|
|
d4e5424360 | ||
|
|
d67d992749 | ||
|
|
b6c7aafe55 | ||
|
|
9829384829 | ||
|
|
1d79c1982a | ||
|
|
f6259531c3 | ||
|
|
ed03039d19 | ||
|
|
b6abc4623b | ||
|
|
d1949b7b42 | ||
|
|
b6e30427a3 | ||
|
|
96e0dcf5d5 | ||
|
|
ab48435211 | ||
|
|
8bcb05d6c0 | ||
|
|
6b363d6af9 | ||
|
|
2fd2a8662d | ||
|
|
f1db0809b1 | ||
|
|
30ca072f50 | ||
|
|
85ea53198a | ||
|
|
7ec4c1424d | ||
|
|
f95513e86b | ||
|
|
8baacecdcf | ||
|
|
ff6e30cec4 | ||
|
|
308275c8a8 | ||
|
|
5ed6534aa3 | ||
|
|
120ca0e3a5 | ||
|
|
d193802613 | ||
|
|
50b4d2eb6b | ||
|
|
36db032ca0 | ||
|
|
afbcc31c6a | ||
|
|
52c35b18da | ||
|
|
454a5ad1ec | ||
|
|
1698f0f57c | ||
|
|
bb6d7334d0 | ||
|
|
659ec4d6ea | ||
|
|
2e50204700 | ||
|
|
39dc9a7ba6 | ||
|
|
65ef2592f6 | ||
|
|
ad0aed3ba5 | ||
|
|
0d868b9ec1 | ||
|
|
5f440dfe13 | ||
|
|
768f8832b9 | ||
|
|
32f20dddd6 | ||
|
|
7aa93a3ecb | ||
|
|
b07dd76453 | ||
|
|
4600b4ab22 | ||
|
|
a8d2dce563 | ||
|
|
5e845ee265 | ||
|
|
a9b7a4a1de | ||
|
|
32d2f78239 | ||
|
|
2a3a8b8008 | ||
|
|
90a63d4d89 | ||
|
|
66f74ed579 | ||
|
|
d376d11d42 | ||
|
|
6664acd27f | ||
|
|
525bcd4e2d | ||
|
|
34a64070ca | ||
|
|
67f2074c81 | ||
|
|
e6717e3d68 | ||
|
|
271eac7381 | ||
|
|
4bf4036bf7 | ||
|
|
22c210c8b9 | ||
|
|
afc3888391 | ||
|
|
411b565cca | ||
|
|
f6c06ac786 | ||
|
|
852a6ff175 | ||
|
|
d6f4d936ee | ||
|
|
cba1820168 | ||
|
|
0cfc88d2ee | ||
|
|
ec3eed5d2a | ||
|
|
49873f4fea | ||
|
|
ee29bf8d42 | ||
|
|
0e0bfe6686 | ||
|
|
fafea15fa8 | ||
|
|
3752981cfa | ||
|
|
9ec1003f1e | ||
|
|
64c99bcfd4 | ||
|
|
d4351183d9 | ||
|
|
cef5c93bca | ||
|
|
eb4e23274d | ||
|
|
dacdc72581 | ||
|
|
6846014def | ||
|
|
07ef99a8f0 | ||
|
|
857af600f7 | ||
|
|
3cbced4e4e | ||
|
|
85e4a0e6ec | ||
|
|
45aca40f6c | ||
|
|
7ecbba089f | ||
|
|
205ddfb7c9 | ||
|
|
8a50b207eb | ||
|
|
9f99ccdca3 | ||
|
|
f49b605514 | ||
|
|
52b4bab461 | ||
|
|
f1ccaf86a4 | ||
|
|
b59ce51760 | ||
|
|
60d2c6fddb | ||
|
|
25a563119b | ||
|
|
a4c9d5826d | ||
|
|
1d3b89458e | ||
|
|
f94b71038e | ||
|
|
076f4b4db1 | ||
|
|
18829a56e4 | ||
|
|
ac7b1b3c1f | ||
|
|
b74f71fbed | ||
|
|
c3c0f4bd89 | ||
|
|
e860ade718 | ||
|
|
e9a8c6cb62 | ||
|
|
473a68dbf9 | ||
|
|
885d8836d1 | ||
|
|
e92ae37dc3 | ||
|
|
e6af9763fd | ||
|
|
ca73dae1f0 | ||
|
|
3623215b8c | ||
|
|
a1376ac8ea | ||
|
|
9d724cb72a | ||
|
|
91ba14e77e | ||
|
|
2cab75d72b | ||
|
|
b37a74533d | ||
|
|
939d0f25c5 | ||
|
|
61929d2e2f | ||
|
|
a7658f9d75 | ||
|
|
033e91b7b9 | ||
|
|
68de34c03e | ||
|
|
94c05e346d | ||
|
|
45298c0a37 | ||
|
|
c12fc1afea | ||
|
|
136b5b0be9 | ||
|
|
9203651110 | ||
|
|
a394ceaef1 | ||
|
|
0ab28ef8ee | ||
|
|
b928b8b3a2 | ||
|
|
075fc96f10 | ||
|
|
15f6255c7c | ||
|
|
2b79519ad1 | ||
|
|
617a8876a6 | ||
|
|
7b7af57813 | ||
|
|
a12f6ec70c | ||
|
|
fffc3b1e0e | ||
|
|
af12ec2b01 | ||
|
|
ecfc7d752a | ||
|
|
bc096994b0 | ||
|
|
ba80074b7b | ||
|
|
f04d883ac1 | ||
|
|
9bf718dd82 | ||
|
|
643d5600b2 | ||
|
|
1edae9c6c1 | ||
|
|
b41e5f5bf6 | ||
|
|
2f6ecc1328 | ||
|
|
b93288875f | ||
|
|
bb4f699d03 | ||
|
|
f1d991fa8b | ||
|
|
4ce7854f44 | ||
|
|
5ef35ee1bd | ||
|
|
6d5bccc050 | ||
|
|
3ac2c1dd18 | ||
|
|
07a41ecf6f | ||
|
|
61e85a578e | ||
|
|
88d68587e1 | ||
|
|
23ae04e6cb | ||
|
|
64c05f2ce9 | ||
|
|
c5cb60a752 | ||
|
|
803e4f5524 | ||
|
|
a909bfaf85 | ||
|
|
bc11e9f300 | ||
|
|
e3412d4207 | ||
|
|
faf8b01ecc | ||
|
|
d7337c5b26 | ||
|
|
2ab1086b80 | ||
|
|
85f2f88c59 | ||
|
|
ce3422e75a | ||
|
|
bee87843b4 | ||
|
|
18aef6ac33 | ||
|
|
890f6031c3 | ||
|
|
f3bace570d | ||
|
|
533511f8c3 | ||
|
|
6489354b0e | ||
|
|
1bbae013cc | ||
|
|
8ac8129fe7 | ||
|
|
9667a38bc9 | ||
|
|
e3df7f033e | ||
|
|
989fd92b84 | ||
|
|
de24170a79 | ||
|
|
5a0548621f | ||
|
|
0f8e472dab | ||
|
|
b190fa38c7 | ||
|
|
b0b01dae81 | ||
|
|
f2b4ba6110 | ||
|
|
d15d0ba6a5 | ||
|
|
fc3af50b55 | ||
|
|
a0a141b457 | ||
|
|
0315ca2701 | ||
|
|
9f4f973277 | ||
|
|
b825e16e36 | ||
|
|
24b4db4352 | ||
|
|
06941ac7a2 | ||
|
|
91d0360a11 | ||
|
|
17bae5bba2 | ||
|
|
1a41fff009 | ||
|
|
7739c495e7 | ||
|
|
5607f7a2c8 | ||
|
|
2a74416d68 | ||
|
|
65f08ea175 | ||
|
|
70b9bdcc9a | ||
|
|
584d5d1a81 | ||
|
|
9e7ab38bce | ||
|
|
71f5a01b83 | ||
|
|
df8ac1cfe6 | ||
|
|
72b6a0a0c9 | ||
|
|
93cf836564 | ||
|
|
d2223ee5e3 | ||
|
|
b6ab8d6776 | ||
|
|
456989ca8d | ||
|
|
2e27d1f763 | ||
|
|
27a83f3dd3 | ||
|
|
79aadb4bc9 | ||
|
|
43d0715238 | ||
|
|
fb8e093389 | ||
|
|
4b47c3ab73 | ||
|
|
a0eff85d73 | ||
|
|
aa36719bd9 | ||
|
|
33aa71c38f | ||
|
|
1f20d7da25 | ||
|
|
dfcf825721 | ||
|
|
eaae041b4c | ||
|
|
dbd79746b1 |
@@ -1,5 +1,4 @@
|
||||
script: "bundle exec rake test"
|
||||
before_install: gem update --system
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
|
||||
@@ -1,7 +1,78 @@
|
||||
== 2.0.1
|
||||
== 2.1.1
|
||||
|
||||
Notes: https://github.com/plataformatec/devise/wiki/How-to:-upgrade-to-devise-2.1
|
||||
|
||||
* enhancements
|
||||
* `sign_out_all_scopes` now locks warden and does not allow new logins in the same action
|
||||
* `Devise.omniauth_path_prefix` is available to configure omniauth path prefix
|
||||
* Redirect to sign in page when trying to access password#edit without a token (by @gbataille)
|
||||
* Allow a lambda in authenticate(d) routes helpers to further select the scope
|
||||
* Removed warnings on Rails 3.2.6 (by @nashby)
|
||||
|
||||
* bug fix
|
||||
* `update_with_password` now relies on assign_attributes and forwards the :as option (by @wtn)
|
||||
* Do not trigger timeout on sign in related actions
|
||||
* Timeout does not explode when reset_authentication_token! is accidentally defined by Active Model (by @remomueller)
|
||||
|
||||
* deprecations
|
||||
* Strategy#validate() no longer validates nil resources
|
||||
|
||||
== 2.1.0
|
||||
|
||||
* enhancements
|
||||
* Add `check_fields!(model_class)` method on Devise::Models to check if the model includes the fields that Devise uses
|
||||
* Add `skip_reconfirmation!` to skip reconfirmation
|
||||
* Devise model generator now works with engines
|
||||
* Devise encryptable was moved to its new gem (http://github.com/plataformatec/devise-encryptable)
|
||||
|
||||
* deprecations
|
||||
* Deprecations warnings added on Devise 2.0 are now removed with their features
|
||||
* All devise modules should now have a `required_fields(klass)` module method to help gathering missing attributes
|
||||
* `use_salt_as_remember_token` and `apply_schema` does not have any effect since 2.0 and are now deprecated
|
||||
* `valid_for_authentication?` must now return a boolean
|
||||
|
||||
* bug fix
|
||||
* Ensure after sign in hook is not called without a resource
|
||||
* Fix a term: now on Omniauth related flash messages, we say that we're authenticating from an omniauth provider instead of authorizing
|
||||
* Fixed redirect when authenticated mounted apps (by @hakanensari)
|
||||
* Ensure the failure app still respects config.relative_url_root
|
||||
* `/users/sign_in` doesn't choke on protected attributes used to select sign in scope (by @Paymium)
|
||||
* `failed_attempts` is set to zero after any sign in (including via reset password) (by @rodrigoflores)
|
||||
* Added token expiration on timeout (by @antiarchitect)
|
||||
* Do not accidentally mark `_prefixes` as private
|
||||
* Better support for custom strategies on test helpers (by @mattconnolly)
|
||||
* Return `head :no_content` in SessionsController now that most JS libraries handle it (by @julianvargasalvarez)
|
||||
|
||||
== 2.0.4
|
||||
|
||||
Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
|
||||
* bug fix
|
||||
* Fix when :host is used with devise_for (by @mreinsch)
|
||||
* Fix a regression that caused Warden to be initialized too late
|
||||
|
||||
== 2.0.3 (yanked)
|
||||
|
||||
* bug fix
|
||||
* Ensure warning is not shown by mistake on apps with mounted engines
|
||||
* Fixes related to remember_token and rememberable_options
|
||||
* Ensure serializable_hash does not depend on accessible attributes
|
||||
* Ensure that timeout callback does not run on sign out action
|
||||
|
||||
== 2.0.2
|
||||
|
||||
* enhancements
|
||||
* Add devise_i18n_options to customize I18n message
|
||||
|
||||
* bug fix
|
||||
* Ensure Devise.available_router_name defaults to :main_app
|
||||
* Set autocomplete to off for password on edit forms
|
||||
* Better error messages in case a trackable model can't be saved
|
||||
* Show a warning in case someone gives a pluralized name to devise generator
|
||||
* Fix test behavior for rspec subject requests (by @sj26)
|
||||
|
||||
== 2.0.1
|
||||
|
||||
* enhancements
|
||||
* Improved error messages on deprecation warnings
|
||||
* Hide Devise's internal generators from `rails g` command
|
||||
@@ -33,6 +104,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Move devise/shared/_links.erb to devise/_links.erb
|
||||
* Deprecated support of nested devise_for blocks
|
||||
* Deprecated support to devise.registrations.reasons and devise.registrations.inactive_signed_up in favor of devise.registrations.signed_up_but_*
|
||||
* Protected method render_with_scope was removed.
|
||||
|
||||
== 1.5.3
|
||||
|
||||
@@ -94,7 +166,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* bug fix
|
||||
* Fix backward incompatible change from 1.4.6 for those using custom controllers
|
||||
|
||||
== 1.4.6
|
||||
== 1.4.6 (yanked)
|
||||
|
||||
* enhancements
|
||||
* Allow devise_for :skip => :all
|
||||
|
||||
4
Gemfile
4
Gemfile
@@ -2,7 +2,7 @@ source "http://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.2.0"
|
||||
gem "rails", "~> 3.2.3"
|
||||
gem "omniauth", "~> 1.0.0"
|
||||
gem "omniauth-oauth2", "~> 1.0.0"
|
||||
gem "rdoc"
|
||||
@@ -25,7 +25,7 @@ platforms :jruby do
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3-ruby"
|
||||
gem "sqlite3"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
|
||||
88
Gemfile.lock
88
Gemfile.lock
@@ -1,44 +1,44 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (2.0.0)
|
||||
devise (2.1.0)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.3)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1)
|
||||
warden (~> 1.2.1)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
mail (~> 2.4.0)
|
||||
actionpack (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
actionmailer (3.2.3)
|
||||
actionpack (= 3.2.3)
|
||||
mail (~> 2.4.4)
|
||||
actionpack (3.2.3)
|
||||
activemodel (= 3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.0)
|
||||
journey (~> 1.0.1)
|
||||
rack (~> 1.4.0)
|
||||
rack-cache (~> 1.1)
|
||||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.1.2)
|
||||
activemodel (3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
activemodel (3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
arel (~> 3.0.0)
|
||||
activerecord (3.2.3)
|
||||
activemodel (= 3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
activesupport (3.2.0)
|
||||
activeresource (3.2.3)
|
||||
activemodel (= 3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
activesupport (3.2.3)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.6)
|
||||
arel (3.0.0)
|
||||
arel (3.0.2)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bson (1.5.1)
|
||||
bson_ext (1.3.1)
|
||||
@@ -52,16 +52,16 @@ GEM
|
||||
hashie (1.2.0)
|
||||
hike (1.2.1)
|
||||
i18n (0.6.0)
|
||||
journey (1.0.0)
|
||||
json (1.6.5)
|
||||
journey (1.0.3)
|
||||
json (1.7.3)
|
||||
linecache (0.46)
|
||||
rbx-require-relative (> 0.0.4)
|
||||
mail (2.4.1)
|
||||
mail (2.4.4)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.17.2)
|
||||
mime-types (1.18)
|
||||
mocha (0.10.0)
|
||||
metaclass (~> 0.0.1)
|
||||
mongo (1.3.1)
|
||||
@@ -87,10 +87,10 @@ GEM
|
||||
omniauth-openid (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
orm_adapter (0.0.6)
|
||||
orm_adapter (0.1.0)
|
||||
polyglot (0.3.3)
|
||||
rack (1.4.1)
|
||||
rack-cache (1.1)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
@@ -99,17 +99,17 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.1)
|
||||
rack (>= 1.0)
|
||||
rails (3.2.0)
|
||||
actionmailer (= 3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
activerecord (= 3.2.0)
|
||||
activeresource (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
rails (3.2.3)
|
||||
actionmailer (= 3.2.3)
|
||||
actionpack (= 3.2.3)
|
||||
activerecord (= 3.2.3)
|
||||
activeresource (= 3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.0)
|
||||
railties (3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
railties (= 3.2.3)
|
||||
railties (3.2.3)
|
||||
actionpack (= 3.2.3)
|
||||
activesupport (= 3.2.3)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
@@ -124,20 +124,18 @@ GEM
|
||||
ruby-debug-base (0.10.4)
|
||||
linecache (>= 0.3)
|
||||
ruby-openid (2.1.8)
|
||||
sprockets (2.1.2)
|
||||
sprockets (2.1.3)
|
||||
hike (~> 1.2)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.31)
|
||||
warden (1.1.0)
|
||||
tzinfo (0.3.33)
|
||||
warden (1.2.1)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
nokogiri (>= 1.2.0)
|
||||
@@ -160,8 +158,8 @@ DEPENDENCIES
|
||||
omniauth-facebook
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-openid (~> 1.0.1)
|
||||
rails (~> 3.2.0)
|
||||
rails (~> 3.2.3)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3-ruby
|
||||
sqlite3
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2012 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
Copyright 2009-2012 Plataformatec. http://plataformatec.com.br
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
98
README.md
98
README.md
@@ -1,10 +1,10 @@
|
||||
*IMPORTANT:* Devise 2.0.0 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
*IMPORTANT:* Devise 2.1 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.1
|
||||
|
||||
## Devise
|
||||
|
||||
INFO: This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
|
||||
|
||||
[](http://travis-ci.org/plataformatec/devise)
|
||||
[](http://travis-ci.org/plataformatec/devise) [](https://codeclimate.com/github/plataformatec/devise)
|
||||
|
||||
Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
|
||||
@@ -13,20 +13,19 @@ 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 comprised of 12 modules:
|
||||
It's composed 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.
|
||||
* Omniauthable: adds Omniauth (github.com/intridea/omniauth) support;
|
||||
* Confirmable: sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
* Recoverable: resets the user password and sends reset instructions.
|
||||
* Registerable: handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
||||
* Rememberable: manages generating and clearing a token for remembering the user from a saved cookie.
|
||||
* Trackable: tracks sign in count, timestamps and IP address.
|
||||
* Timeoutable: expires sessions that have no activity in a specified period of time.
|
||||
* Validatable: provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* Lockable: locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
* Encryptable: adds support of other authentication mechanisms besides the built-in Bcrypt (the default).
|
||||
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): 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](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable): signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://github.com/intridea/omniauth) support;
|
||||
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
|
||||
* [Registerable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
||||
* [Rememberable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie.
|
||||
* [Trackable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable): tracks sign in count, timestamps and IP address.
|
||||
* [Timeoutable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Timeoutable): expires sessions that have no activity in a specified period of time.
|
||||
* [Validatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* [Lockable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
|
||||
## Information
|
||||
|
||||
@@ -42,7 +41,7 @@ If you discover a problem with Devise, we would like to know about it. However,
|
||||
|
||||
https://github.com/plataformatec/devise/wiki/Bug-reports
|
||||
|
||||
If you found a security bug, do *NOT* use the GitHub issue tracker. Send email or a private GitHub message to the maintainers listed at the bottom of the README.
|
||||
If you found a security bug, do *NOT* use the GitHub issue tracker. Send an email to the maintainers listed at the bottom of the README.
|
||||
|
||||
### Mailing list
|
||||
|
||||
@@ -89,12 +88,14 @@ Once you have solidified your understanding of Rails and authentication mechanis
|
||||
|
||||
## Getting started
|
||||
|
||||
Devise 2.0 works with Rails 3.1 onwards. You can install it with:
|
||||
Devise 2.0 works with Rails 3.1 onwards. You can add it to your Gemfile with:
|
||||
|
||||
```console
|
||||
gem install devise
|
||||
```ruby
|
||||
gem 'devise'
|
||||
```
|
||||
|
||||
Run the bundle command to install it.
|
||||
|
||||
After you install Devise and add it to your Gemfile, you need to run the generator:
|
||||
|
||||
```console
|
||||
@@ -109,6 +110,8 @@ rails generate devise MODEL
|
||||
|
||||
Replace MODEL by the class name used for the applications users, it's frequently 'User' but could also be 'Admin'. This will create a model (if one does not exist) and configure it with default Devise modules. Next, you'll usually run "rake db:migrate" as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file to point to Devise controller.
|
||||
|
||||
Note that you should re-start your app here if you've already started it. Otherwise you'll run into strange errors like users being unable to login and the route helpers being undefined.
|
||||
|
||||
### Controller filters and helpers
|
||||
|
||||
Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_filter:
|
||||
@@ -135,13 +138,13 @@ You can access the session for this scope:
|
||||
user_session
|
||||
```
|
||||
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use +user_root_path+ if it exists, otherwise default +root_path+ will be used. This means that you need to set the root inside your routes:
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use `user_root_path` if it exists, otherwise default `root_path` will be used. This means that you need to set the root inside your routes:
|
||||
|
||||
```ruby
|
||||
root :to => "home#index"
|
||||
```
|
||||
|
||||
You can also overwrite +after_sign_in_path_for+ and +after_sign_out_path_for+ to customize your redirect hooks.
|
||||
You can also overwrite `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
|
||||
|
||||
Finally, you need to set up default url options for the mailer in each environment. Here is the configuration for "config/environments/development.rb":
|
||||
|
||||
@@ -247,9 +250,9 @@ Devise also ships with default routes. If you need to customize them, you should
|
||||
devise_for :users, :path => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
|
||||
```
|
||||
|
||||
Be sure to check +devise_for+ documentation for details.
|
||||
Be sure to check `devise_for` documentation for details.
|
||||
|
||||
If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is to create your routes normally and wrap them in a +devise_scope+ block in the router:
|
||||
If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is to create your routes normally and wrap them in a `devise_scope` block in the router:
|
||||
|
||||
```ruby
|
||||
devise_scope :user do
|
||||
@@ -257,15 +260,7 @@ devise_scope :user do
|
||||
end
|
||||
```
|
||||
|
||||
This way you tell devise to use the scope :user when "/sign_in" is accessed. Notice +devise_scope+ is also aliased as +as+ and you can also give a block to +devise_for+, resulting in the same behavior:
|
||||
|
||||
```ruby
|
||||
devise_for :users do
|
||||
get "sign_in", :to => "devise/sessions#new"
|
||||
end
|
||||
```
|
||||
|
||||
Feel free to choose the one you prefer!
|
||||
This way you tell devise to use the scope :user when "/sign_in" is accessed. Notice `devise_scope` is also aliased as `as` in your router.
|
||||
|
||||
### I18n
|
||||
|
||||
@@ -309,7 +304,23 @@ https://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
### Test helpers
|
||||
|
||||
Devise includes some tests helpers for functional specs. To use them, you just need to include Devise::TestHelpers in your test class and use the sign_in and sign_out method. Such methods have the same signature as in controllers:
|
||||
Devise includes some tests helpers for functional specs. In other to use them, you need to include Devise in your functional tests by adding the following to the bottom of your `test/test_helper.rb` file:
|
||||
|
||||
```ruby
|
||||
class ActionController::TestCase
|
||||
include Devise::TestHelpers
|
||||
end
|
||||
```
|
||||
|
||||
If you're using RSpec, you can put the following inside a file named `spec/support/devise.rb`:
|
||||
|
||||
```ruby
|
||||
RSpec.configure do |config|
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
end
|
||||
```
|
||||
|
||||
Now you are ready to use the `sign_in` and `sign_out` methods. Such methods have the same signature as in controllers:
|
||||
|
||||
```ruby
|
||||
sign_in :user, @user # sign_in(scope, resource)
|
||||
@@ -319,23 +330,14 @@ sign_out :user # sign_out(scope)
|
||||
sign_out @user # sign_out(resource)
|
||||
```
|
||||
|
||||
You can include the Devise Test Helpers in all of your tests by adding the following to the bottom of your test/test_helper.rb file:
|
||||
There are two things that is important to keep in mind:
|
||||
|
||||
```ruby
|
||||
class ActionController::TestCase
|
||||
include Devise::TestHelpers
|
||||
end
|
||||
```
|
||||
1) These helpers are not going to work for integration tests driven by Capybara or Webrat. They are meant to be used with functional tests only. Instead, fill in the form or explicitly set the user in session;
|
||||
|
||||
If you're using RSpec and want the helpers automatically included within all +describe+ blocks, add a file called spec/support/devise.rb with the following contents:
|
||||
2) If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from router, but since functional tests do not pass through the router, it needs to be told explicitly. For example, if you are testing the user scope, simply do:
|
||||
|
||||
```ruby
|
||||
RSpec.configure do |config|
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
end
|
||||
```
|
||||
|
||||
Do not use such helpers for integration tests such as Cucumber or Webrat. Instead, fill in the form or explicitly set the user in session. For more tips, check the wiki (https://wiki.github.com/plataformatec/devise).
|
||||
@request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
get :new
|
||||
|
||||
### Omniauth
|
||||
|
||||
@@ -385,4 +387,4 @@ https://github.com/plataformatec/devise/contributors
|
||||
|
||||
## License
|
||||
|
||||
MIT License. Copyright 2012 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
MIT License. Copyright 2012 Plataformatec. http://plataformatec.com.br
|
||||
|
||||
4
Rakefile
4
Rakefile
@@ -1,5 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require "bundler/gem_tasks"
|
||||
require 'rake/testtask'
|
||||
require 'rdoc/task'
|
||||
|
||||
@@ -29,6 +29,6 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'Devise'
|
||||
rdoc.options << '--line-numbers' << '--inline-source'
|
||||
rdoc.rdoc_files.include('README.rdoc')
|
||||
rdoc.rdoc_files.include('README.md')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class Devise::ConfirmationsController < DeviseController
|
||||
|
||||
# POST /resource/confirmation
|
||||
def create
|
||||
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
||||
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
class Devise::OmniauthCallbacksController < DeviseController
|
||||
prepend_before_filter { request.env["devise.skip_timeout"] = true }
|
||||
|
||||
def passthru
|
||||
render :status => 404, :text => "Not found. Authentication passthru."
|
||||
end
|
||||
|
||||
def failure
|
||||
set_flash_message :alert, :failure, :kind => failed_strategy.name.to_s.humanize, :reason => failure_message
|
||||
redirect_to after_omniauth_failure_path_for(resource_name)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
class Devise::PasswordsController < DeviseController
|
||||
prepend_before_filter :require_no_authentication
|
||||
# Render the #edit only if coming from a reset password email link
|
||||
append_before_filter :assert_reset_token_passed, :only => :edit
|
||||
|
||||
# GET /resource/password/new
|
||||
def new
|
||||
@@ -8,7 +10,7 @@ class Devise::PasswordsController < DeviseController
|
||||
|
||||
# POST /resource/password
|
||||
def create
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
||||
@@ -25,7 +27,7 @@ class Devise::PasswordsController < DeviseController
|
||||
|
||||
# PUT /resource/password
|
||||
def update
|
||||
self.resource = resource_class.reset_password_by_token(params[resource_name])
|
||||
self.resource = resource_class.reset_password_by_token(resource_params)
|
||||
|
||||
if resource.errors.empty?
|
||||
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
|
||||
@@ -44,4 +46,11 @@ class Devise::PasswordsController < DeviseController
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
|
||||
# Check if a reset_password_token is provided in the request
|
||||
def assert_reset_token_passed
|
||||
if params[:reset_password_token].blank?
|
||||
set_flash_message(:error, :no_token)
|
||||
redirect_to new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,7 +39,7 @@ class Devise::RegistrationsController < DeviseController
|
||||
def update
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
|
||||
if resource.update_with_password(params[resource_name])
|
||||
if resource.update_with_password(resource_params)
|
||||
if is_navigational_format?
|
||||
if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation?
|
||||
flash_key = :update_needs_confirmation
|
||||
@@ -77,7 +77,7 @@ class Devise::RegistrationsController < DeviseController
|
||||
# Build a devise resource passing in the session. Useful to move
|
||||
# temporary session data to the newly created user.
|
||||
def build_resource(hash=nil)
|
||||
hash ||= params[resource_name] || {}
|
||||
hash ||= resource_params || {}
|
||||
self.resource = resource_class.new_with_session(hash, session)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class Devise::SessionsController < DeviseController
|
||||
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
|
||||
prepend_before_filter :allow_params_authentication!, :only => :create
|
||||
prepend_before_filter { request.env["devise.skip_timeout"] = true }
|
||||
|
||||
# GET /resource/sign_in
|
||||
def new
|
||||
resource = build_resource
|
||||
resource = build_resource(nil, :unsafe => true)
|
||||
clean_up_passwords(resource)
|
||||
respond_with(resource, serialize_options(resource))
|
||||
end
|
||||
@@ -19,19 +20,16 @@ class Devise::SessionsController < DeviseController
|
||||
|
||||
# DELETE /resource/sign_out
|
||||
def destroy
|
||||
signed_in = signed_in?(resource_name)
|
||||
redirect_path = after_sign_out_path_for(resource_name)
|
||||
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
||||
set_flash_message :notice, :signed_out if signed_in
|
||||
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
||||
set_flash_message :notice, :signed_out if signed_out
|
||||
|
||||
# We actually need to hardcode this as Rails default responder doesn't
|
||||
# support returning empty response on GET request
|
||||
respond_to do |format|
|
||||
format.any(*navigational_formats) { redirect_to redirect_path }
|
||||
format.all do
|
||||
method = "to_#{request_format}"
|
||||
text = {}.respond_to?(method) ? {}.send(method) : ""
|
||||
render :text => text, :status => :ok
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,10 +8,10 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
# POST /resource/unlock
|
||||
def create
|
||||
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
||||
self.resource = resource_class.send_unlock_instructions(resource_params)
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => new_session_path(resource_name))
|
||||
respond_with({}, :location => after_sending_unlock_instructions_path_for(resource))
|
||||
else
|
||||
respond_with(resource)
|
||||
end
|
||||
@@ -23,9 +23,22 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :unlocked if is_navigational_format?
|
||||
respond_with_navigational(resource){ redirect_to new_session_path(resource) }
|
||||
respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
|
||||
else
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The path used after sending unlock password instructions
|
||||
def after_sending_unlock_instructions_path_for(resource)
|
||||
new_session_path(resource)
|
||||
end
|
||||
|
||||
# The path used after unlocking the resource
|
||||
def after_unlock_path_for(resource)
|
||||
new_session_path(resource)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
helper DeviseHelper
|
||||
|
||||
helpers = %w(resource scope_name resource_name signed_in_resource
|
||||
resource_class devise_mapping devise_controller?)
|
||||
resource_class resource_params devise_mapping)
|
||||
hide_action *helpers
|
||||
helper_method *helpers
|
||||
|
||||
@@ -28,6 +28,10 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
devise_mapping.to
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params[resource_name]
|
||||
end
|
||||
|
||||
# Returns a signed in resource from session (if one exists)
|
||||
def signed_in_resource
|
||||
warden.authenticate(:scope => resource_name)
|
||||
@@ -38,22 +42,39 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
@devise_mapping ||= request.env["devise.mapping"]
|
||||
end
|
||||
|
||||
# Overwrites devise_controller? to return true
|
||||
def devise_controller?
|
||||
true
|
||||
# Override prefixes to consider the scoped view.
|
||||
# Notice we need to check for the request due to a bug in
|
||||
# Action Controller tests that forces _prefixes to be
|
||||
# loaded before even having a request object.
|
||||
def _prefixes #:nodoc:
|
||||
@_prefixes ||= if self.class.scoped_views? && request && devise_mapping
|
||||
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
hide_action :_prefixes
|
||||
|
||||
protected
|
||||
|
||||
# Checks whether it's a devise mapped resource or not.
|
||||
def assert_is_devise_resource! #:nodoc:
|
||||
unknown_action! <<-MESSAGE unless devise_mapping
|
||||
Could not find devise mapping for path #{request.fullpath.inspect}.
|
||||
Maybe you forgot to wrap your route inside the scope block? For example:
|
||||
This may happen for two reasons:
|
||||
|
||||
1) You forgot to wrap your route inside the scope block. For example:
|
||||
|
||||
devise_scope :user do
|
||||
match "/some/route" => "some_devise_controller"
|
||||
end
|
||||
|
||||
2) You are testing a Devise controller bypassing the router.
|
||||
If so, you can explicitly tell Devise which mapping to use:
|
||||
|
||||
@request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
devise_scope :user do
|
||||
match "/some/route" => "some_devise_controller"
|
||||
end
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
@@ -73,9 +94,20 @@ MESSAGE
|
||||
end
|
||||
|
||||
# Build a devise resource.
|
||||
def build_resource(hash=nil)
|
||||
hash ||= params[resource_name] || {}
|
||||
self.resource = resource_class.new(hash)
|
||||
# Assignment bypasses attribute protection when :unsafe option is passed
|
||||
def build_resource(hash = nil, options = {})
|
||||
hash ||= resource_params || {}
|
||||
|
||||
if options[:unsafe]
|
||||
self.resource = resource_class.new.tap do |resource|
|
||||
hash.each do |key, value|
|
||||
setter = :"#{key}="
|
||||
resource.send(setter, value) if resource.respond_to?(setter)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.resource = resource_class.new(hash)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper for use in before_filters where no authentication is required.
|
||||
@@ -94,8 +126,7 @@ MESSAGE
|
||||
warden.authenticated?(resource_name)
|
||||
end
|
||||
|
||||
if authenticated
|
||||
resource = warden.user(resource_name)
|
||||
if authenticated && resource = warden.user(resource_name)
|
||||
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
@@ -136,6 +167,7 @@ MESSAGE
|
||||
options[:scope] = "devise.#{controller_name}"
|
||||
options[:default] = Array(options[:default]).unshift(kind.to_sym)
|
||||
options[:resource_name] = resource_name
|
||||
options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
|
||||
message = I18n.t("#{resource_name}.#{kind}", options)
|
||||
flash[key] = message if message.present?
|
||||
end
|
||||
@@ -157,13 +189,4 @@ MESSAGE
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request.format.try(:ref))
|
||||
end
|
||||
|
||||
# Override prefixes to consider the scoped view.
|
||||
def _prefixes #:nodoc:
|
||||
@_prefixes ||= if self.class.scoped_views?
|
||||
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,25 +1,3 @@
|
||||
<%- if controller_name != 'sessions' %>
|
||||
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
||||
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% ActiveSupport::Deprecation.warn "Rendering partials devise/_links.erb is deprecated" \
|
||||
"please use devise/shared/_links.erb instead."%>
|
||||
<%= render "shared/links" %>
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Resend confirmation instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
<div><%= f.submit "Change my password" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Send me reset password instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<%= f.email_field :email %></div>
|
||||
|
||||
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
||||
<%= f.password_field :password %></div>
|
||||
<%= f.password_field :password, :autocomplete => "off" %></div>
|
||||
|
||||
<div><%= f.label :password_confirmation %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
@@ -20,6 +20,6 @@
|
||||
|
||||
<h3>Cancel my account</h3>
|
||||
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %>.</p>
|
||||
|
||||
<%= link_to "Back", :back %>
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
<div><%= f.submit "Sign up" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
<div><%= f.submit "Sign in" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
<% ActiveSupport::Deprecation.warn "Rendering partials devise/shared/_links.erb is deprecated" \
|
||||
"please use devise/_links.erb instead." %>
|
||||
<%= render "links" %>
|
||||
<%- if controller_name != 'sessions' %>
|
||||
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
||||
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Resend unlock instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -28,10 +28,11 @@ en:
|
||||
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"
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
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.'
|
||||
send_paranoid_instructions: 'If your email address exists in 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.'
|
||||
@@ -46,8 +47,8 @@ en:
|
||||
unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
|
||||
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}".'
|
||||
success: 'Successfully authenticated from %{kind} account.'
|
||||
failure: 'Could not authenticate you from %{kind} because "%{reason}".'
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Confirmation instructions'
|
||||
|
||||
@@ -18,8 +18,8 @@ Gem::Specification.new do |s|
|
||||
s.test_files = `git ls-files -- test/*`.split("\n")
|
||||
s.require_paths = ["lib"]
|
||||
|
||||
s.add_dependency("warden", "~> 1.1")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.3")
|
||||
s.add_dependency("warden", "~> 1.2.1")
|
||||
s.add_dependency("orm_adapter", "~> 0.1")
|
||||
s.add_dependency("bcrypt-ruby", "~> 3.0")
|
||||
s.add_dependency("railties", "~> 3.1")
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ platforms :jruby do
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3-ruby"
|
||||
gem "sqlite3"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
|
||||
167
gemfiles/Gemfile.rails-3.1.x.lock
Normal file
167
gemfiles/Gemfile.rails-3.1.x.lock
Normal file
@@ -0,0 +1,167 @@
|
||||
PATH
|
||||
remote: ..
|
||||
specs:
|
||||
devise (2.1.0.rc2)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.7)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1.1)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
mail (~> 2.3.0)
|
||||
actionpack (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
i18n (~> 0.6)
|
||||
rack (~> 1.3.6)
|
||||
rack-cache (~> 1.1)
|
||||
rack-mount (~> 0.8.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.0.3)
|
||||
activemodel (3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
builder (~> 3.0.0)
|
||||
i18n (~> 0.6)
|
||||
activerecord (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
arel (~> 2.2.3)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
activesupport (3.1.4)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.7)
|
||||
arel (2.2.3)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bson (1.5.2)
|
||||
bson_ext (1.3.1)
|
||||
builder (3.0.0)
|
||||
columnize (0.3.6)
|
||||
erubis (2.7.0)
|
||||
faraday (0.7.6)
|
||||
addressable (~> 2.2)
|
||||
multipart-post (~> 1.1)
|
||||
rack (~> 1.1)
|
||||
hashie (1.2.0)
|
||||
hike (1.2.1)
|
||||
i18n (0.6.0)
|
||||
json (1.7.0)
|
||||
linecache (0.46)
|
||||
rbx-require-relative (> 0.0.4)
|
||||
mail (2.3.3)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.18)
|
||||
mocha (0.10.4)
|
||||
metaclass (~> 0.0.1)
|
||||
mongo (1.3.1)
|
||||
bson (>= 1.3.1)
|
||||
mongoid (2.4.4)
|
||||
activemodel (~> 3.1)
|
||||
mongo (~> 1.3)
|
||||
tzinfo (~> 0.3.22)
|
||||
multi_json (1.3.4)
|
||||
multipart-post (1.1.5)
|
||||
nokogiri (1.5.0)
|
||||
oauth2 (0.5.2)
|
||||
faraday (~> 0.7)
|
||||
multi_json (~> 1.0)
|
||||
omniauth (1.0.2)
|
||||
hashie (~> 1.2)
|
||||
rack
|
||||
omniauth-facebook (1.2.0)
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-oauth2 (1.0.0)
|
||||
oauth2 (~> 0.5.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-openid (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
orm_adapter (0.0.7)
|
||||
polyglot (0.3.3)
|
||||
rack (1.3.6)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-ssl (1.3.2)
|
||||
rack
|
||||
rack-test (0.6.1)
|
||||
rack (>= 1.0)
|
||||
rails (3.1.4)
|
||||
actionmailer (= 3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activerecord (= 3.1.4)
|
||||
activeresource (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.1.4)
|
||||
railties (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (~> 0.14.6)
|
||||
rake (0.9.2.2)
|
||||
rbx-require-relative (0.0.5)
|
||||
rdoc (3.12)
|
||||
json (~> 1.4)
|
||||
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)
|
||||
sprockets (2.0.4)
|
||||
hike (~> 1.2)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.33)
|
||||
warden (1.1.1)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbc-adapter
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bson_ext (~> 1.3.0)
|
||||
devise!
|
||||
jruby-openssl
|
||||
mocha
|
||||
mongo (~> 1.3.0)
|
||||
mongoid (~> 2.0)
|
||||
omniauth (~> 1.0.0)
|
||||
omniauth-facebook
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-openid (~> 1.0.1)
|
||||
rails (~> 3.1.0)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3
|
||||
webrat (= 0.7.2)
|
||||
@@ -10,8 +10,6 @@ module Devise
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
autoload :OmniAuth, 'devise/omniauth'
|
||||
autoload :ParamFilter, 'devise/param_filter'
|
||||
autoload :PathChecker, 'devise/path_checker'
|
||||
autoload :Schema, 'devise/schema'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
|
||||
module Controllers
|
||||
@@ -21,15 +19,6 @@ module Devise
|
||||
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
||||
end
|
||||
|
||||
module Encryptors
|
||||
autoload :Base, 'devise/encryptors/base'
|
||||
autoload :AuthlogicSha512, 'devise/encryptors/authlogic_sha512'
|
||||
autoload :ClearanceSha1, 'devise/encryptors/clearance_sha1'
|
||||
autoload :RestfulAuthenticationSha1, 'devise/encryptors/restful_authentication_sha1'
|
||||
autoload :Sha512, 'devise/encryptors/sha512'
|
||||
autoload :Sha1, 'devise/encryptors/sha1'
|
||||
end
|
||||
|
||||
module Mailers
|
||||
autoload :Helpers, 'devise/mailers/helpers'
|
||||
end
|
||||
@@ -53,18 +42,9 @@ module Devise
|
||||
# True values used to check params
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
# Declare encryptors length which are used in migrations.
|
||||
ENCRYPTORS_LENGTH = {
|
||||
:sha1 => 40,
|
||||
:sha512 => 128,
|
||||
:clearance_sha1 => 40,
|
||||
:restful_authentication_sha1 => 40,
|
||||
:authlogic_sha512 => 128
|
||||
}
|
||||
|
||||
# Custom domain for cookies. Not set by default
|
||||
mattr_accessor :cookie_options
|
||||
@@cookie_options = {}
|
||||
mattr_accessor :rememberable_options
|
||||
@@rememberable_options = {}
|
||||
|
||||
# The number of times to encrypt password.
|
||||
mattr_accessor :stretches
|
||||
@@ -79,14 +59,12 @@ module Devise
|
||||
@@request_keys = []
|
||||
|
||||
# Keys that should be case-insensitive.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :case_insensitive_keys
|
||||
@@case_insensitive_keys = false
|
||||
@@case_insensitive_keys = [ :email ]
|
||||
|
||||
# Keys that should have whitespace stripped.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :strip_whitespace_keys
|
||||
@@strip_whitespace_keys = false
|
||||
@@strip_whitespace_keys = []
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -139,14 +117,14 @@ module Devise
|
||||
mattr_accessor :timeout_in
|
||||
@@timeout_in = 30.minutes
|
||||
|
||||
# Authentication token expiration on timeout
|
||||
mattr_accessor :expire_auth_token_on_timeout
|
||||
@@expire_auth_token_on_timeout = false
|
||||
|
||||
# Used to encrypt password. Please generate one with rake secret.
|
||||
mattr_accessor :pepper
|
||||
@@pepper = nil
|
||||
|
||||
# Used to define the password encryption algorithm.
|
||||
mattr_accessor :encryptor
|
||||
@@encryptor = nil
|
||||
|
||||
# Scoped views. Since it relies on fallbacks to render default views, it's
|
||||
# turned off by default.
|
||||
mattr_accessor :scoped_views
|
||||
@@ -179,9 +157,8 @@ module Devise
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key
|
||||
# Nil by default for backwards compatibility.
|
||||
mattr_accessor :reset_password_within
|
||||
@@reset_password_within = nil
|
||||
@@reset_password_within = 6.hours
|
||||
|
||||
# The default scope which is used by warden.
|
||||
mattr_accessor :default_scope
|
||||
@@ -222,32 +199,22 @@ module Devise
|
||||
# to provide custom routes.
|
||||
mattr_accessor :router_name
|
||||
@@router_name = nil
|
||||
|
||||
# Set the omniauth path prefix so it can be overriden when
|
||||
# Devise is used in a mountable engine
|
||||
mattr_accessor :omniauth_path_prefix
|
||||
@@omniauth_path_prefix = nil
|
||||
|
||||
# DEPRECATED CONFIG
|
||||
|
||||
# If true, uses salt as remember token and does not create it in the database.
|
||||
# By default is false for backwards compatibility.
|
||||
mattr_accessor :use_salt_as_remember_token
|
||||
@@use_salt_as_remember_token = false
|
||||
|
||||
# Tells if devise should apply the schema in ORMs where devise declaration
|
||||
# and schema belongs to the same class (as Datamapper and Mongoid).
|
||||
mattr_accessor :apply_schema
|
||||
@@apply_schema = true
|
||||
|
||||
def self.remember_across_browsers=(value)
|
||||
warn "\n[DEVISE] Devise.remember_across_browsers is deprecated and has no effect. Please remove it.\n"
|
||||
def self.encryptor=(value)
|
||||
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
|
||||
end
|
||||
|
||||
def self.confirm_within=(value)
|
||||
warn "\n[DEVISE] Devise.confirm_within= is deprecated. Please set Devise.allow_unconfirmed_access_for= instead.\n"
|
||||
Devise.allow_unconfirmed_access_for = value
|
||||
def self.use_salt_as_remember_token=(value)
|
||||
warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
|
||||
end
|
||||
|
||||
def self.stateless_token=(value)
|
||||
warn "\n[DEVISE] Devise.stateless_token= is deprecated. Please append :token_auth to Devise.skip_session_storage " \
|
||||
"instead, for example: Devise.skip_session_storage << :token_auth\n"
|
||||
Devise.skip_session_storage << :token_auth
|
||||
def self.apply_schema=(value)
|
||||
warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
|
||||
end
|
||||
|
||||
# PRIVATE CONFIGURATION
|
||||
@@ -299,6 +266,10 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
def self.available_router_name
|
||||
router_name || :main_app
|
||||
end
|
||||
|
||||
def self.omniauth_providers
|
||||
omniauth_configs.keys
|
||||
end
|
||||
|
||||
@@ -75,9 +75,9 @@ module Devise
|
||||
# the controllers defined inside devise. Useful if you want to apply a before
|
||||
# filter to all controllers, except the ones in devise:
|
||||
#
|
||||
# before_filter :my_filter, :unless => { |c| c.devise_controller? }
|
||||
# before_filter :my_filter, :unless => :devise_controller?
|
||||
def devise_controller?
|
||||
false
|
||||
is_a?(DeviseController)
|
||||
end
|
||||
|
||||
# Tell warden that params authentication is allowed for that specific page.
|
||||
@@ -88,8 +88,8 @@ module Devise
|
||||
# Return true if the given scope is signed in session. If no scope given, return
|
||||
# true if any scope is signed in. Does not run authentication hooks.
|
||||
def signed_in?(scope=nil)
|
||||
[ scope || Devise.mappings.keys ].flatten.any? do |scope|
|
||||
warden.authenticate?(:scope => scope)
|
||||
[ scope || Devise.mappings.keys ].flatten.any? do |_scope|
|
||||
warden.authenticate?(:scope => _scope)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,7 +126,8 @@ module Devise
|
||||
end
|
||||
|
||||
# Sign out a given user or scope. This helper is useful for signing out a user
|
||||
# after deleting accounts.
|
||||
# after deleting accounts. Returns true if there was a logout and false if there
|
||||
# is no user logged in on the referred scope
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
@@ -136,19 +137,29 @@ module Devise
|
||||
def sign_out(resource_or_scope=nil)
|
||||
return sign_out_all_scopes unless resource_or_scope
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
warden.user(scope) # Without loading user here, before_logout hook is not called
|
||||
user = warden.user(:scope => scope, :run_callbacks => false) # If there is no user
|
||||
|
||||
warden.raw_session.inspect # Without this inspect here. The session does not clear.
|
||||
warden.logout(scope)
|
||||
warden.clear_strategies_cache!(:scope => scope)
|
||||
instance_variable_set(:"@current_#{scope}", nil)
|
||||
|
||||
!!user
|
||||
end
|
||||
|
||||
# Sign out all active users or scopes. This helper is useful for signing out all roles
|
||||
# in one click. This signs out ALL scopes in warden.
|
||||
def sign_out_all_scopes
|
||||
Devise.mappings.keys.each { |s| warden.user(s) }
|
||||
# in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
|
||||
# and false if there was no user logged in on all scopes.
|
||||
def sign_out_all_scopes(lock=true)
|
||||
users = Devise.mappings.keys.map { |s| warden.user(:scope => s, :run_callbacks => false) }
|
||||
|
||||
warden.raw_session.inspect
|
||||
warden.logout
|
||||
expire_devise_cached_variables!
|
||||
warden.clear_strategies_cache!
|
||||
warden.lock! if lock
|
||||
|
||||
users.any?
|
||||
end
|
||||
|
||||
# Returns and delete the url stored in the session for the given scope. Useful
|
||||
@@ -200,7 +211,7 @@ module Devise
|
||||
# if resource.is_a?(User) && resource.can_publish?
|
||||
# publisher_url
|
||||
# else
|
||||
# signed_in_root_path(resource)
|
||||
# super
|
||||
# end
|
||||
# end
|
||||
#
|
||||
@@ -229,11 +240,6 @@ module Devise
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
ActiveSupport::Deprecation.warn "redirect_location in Devise is deprecated. Please use after_sign_in_path_for instead.", caller
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
def expire_session_data_after_sign_in!
|
||||
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
||||
end
|
||||
@@ -250,8 +256,8 @@ module Devise
|
||||
# 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!
|
||||
sign_out_all_scopes(false)
|
||||
request.env["devise.skip_storage"] = true
|
||||
expire_devise_cached_variables!
|
||||
super # call the default behaviour which resets the session
|
||||
end
|
||||
|
||||
@@ -36,7 +36,7 @@ module Devise
|
||||
protected
|
||||
|
||||
def forget_cookie_values(resource)
|
||||
Devise::Controllers::Rememberable.cookie_values.merge!(resource.cookie_options)
|
||||
Devise::Controllers::Rememberable.cookie_values.merge!(resource.rememberable_options)
|
||||
end
|
||||
|
||||
def remember_cookie_values(resource)
|
||||
|
||||
@@ -60,7 +60,7 @@ module Devise
|
||||
private
|
||||
|
||||
def _devise_route_context
|
||||
@_devise_route_context ||= send(Devise.router_name)
|
||||
@_devise_route_context ||= send(Devise.available_router_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
require "digest/sha2"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = AuthlogicSha512
|
||||
# Simulates Authlogic's default encryption mechanism.
|
||||
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to simulate
|
||||
# the default behavior.
|
||||
class AuthlogicSha512 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = [password, salt].flatten.join('')
|
||||
stretches.times { digest = Digest::SHA512.hexdigest(digest) }
|
||||
digest
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
module Devise
|
||||
# Implements a way of adding different encryptions.
|
||||
# The class should implement a self.digest method that taks the following params:
|
||||
# - password
|
||||
# - stretches: the number of times the encryption will be applied
|
||||
# - salt: the password salt as defined by devise
|
||||
# - pepper: Devise config option
|
||||
#
|
||||
module Encryptors
|
||||
class Base
|
||||
def self.digest
|
||||
raise NotImplemented
|
||||
end
|
||||
|
||||
def self.salt(stretches)
|
||||
Devise.friendly_token[0,20]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,17 +0,0 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = ClearanceSha1
|
||||
# Simulates Clearance's default encryption mechanism.
|
||||
# Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
|
||||
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES
|
||||
class ClearanceSha1 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = RestfulAuthenticationSha1
|
||||
# Simulates Restful Authentication's default encryption mechanism.
|
||||
# Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
|
||||
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
|
||||
# the initializer to simulate the default behavior.
|
||||
class RestfulAuthenticationSha1 < Base
|
||||
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = Digest::SHA1.hexdigest([digest, salt, password, pepper].flatten.join('--')) }
|
||||
digest
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,25 +0,0 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = Sha1
|
||||
# Uses the Sha1 hash algorithm to encrypt passwords.
|
||||
class Sha1 < Base
|
||||
# Generates a default password digest based on stretches, salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
|
||||
digest
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generate a SHA1 digest joining args. Generated token is something like
|
||||
# --arg1--arg2--arg3--argN--
|
||||
def self.secure_digest(*tokens)
|
||||
::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,25 +0,0 @@
|
||||
require "digest/sha2"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = Sha512
|
||||
# Uses the Sha512 hash algorithm to encrypt passwords.
|
||||
class Sha512 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
|
||||
digest
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generate a Sha512 digest joining args. Generated token is something like
|
||||
# --arg1--arg2--arg3--argN--
|
||||
def self.secure_digest(*tokens)
|
||||
::Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -89,7 +89,10 @@ module Devise
|
||||
route = :"new_#{scope}_session_path"
|
||||
opts[:format] = request_format unless skip_format?
|
||||
|
||||
context = send(Devise.router_name)
|
||||
config = Rails.application.config
|
||||
opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
|
||||
|
||||
context = send(Devise.available_router_name)
|
||||
|
||||
if context.respond_to?(route)
|
||||
context.send(route, opts)
|
||||
|
||||
7
lib/devise/hooks/lockable.rb
Normal file
7
lib/devise/hooks/lockable.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# After each sign in, if resource responds to failed_attempts, sets it to 0
|
||||
# This is only triggered when the user is explicitly set (with set_user)
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
|
||||
record.update_attribute(:failed_attempts, 0)
|
||||
end
|
||||
end
|
||||
@@ -5,19 +5,20 @@
|
||||
# verify timeout in the following request.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
env = warden.request.env
|
||||
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
|
||||
last_request_at = warden.session(scope)['last_request_at']
|
||||
|
||||
if record.timedout?(last_request_at)
|
||||
path_checker = Devise::PathChecker.new(warden.env, scope)
|
||||
unless path_checker.signing_out?
|
||||
warden.logout(scope)
|
||||
throw :warden, :scope => scope, :message => :timeout
|
||||
if record.timedout?(last_request_at) && !env['devise.skip_timeout']
|
||||
warden.logout(scope)
|
||||
if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
|
||||
record.reset_authentication_token!
|
||||
end
|
||||
throw :warden, :scope => scope, :message => :timeout
|
||||
end
|
||||
|
||||
unless warden.request.env['devise.skip_trackable']
|
||||
unless env['devise.skip_trackable']
|
||||
warden.session(scope)['last_request_at'] = Time.now.utc
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
module Devise
|
||||
module Models
|
||||
class MissingAttribute < StandardError
|
||||
def initialize(attributes)
|
||||
@attributes = attributes
|
||||
end
|
||||
|
||||
def message
|
||||
"The following attribute(s) is (are) missing on your model: #{@attributes.join(", ")}"
|
||||
end
|
||||
end
|
||||
|
||||
# Creates configuration values for Devise and for the given module.
|
||||
#
|
||||
# Devise::Models.config(Devise::Authenticatable, :stretches, 10)
|
||||
@@ -17,7 +27,7 @@ module Devise
|
||||
# inside the given class.
|
||||
#
|
||||
def self.config(mod, *accessors) #:nodoc:
|
||||
(class << mod; self; end).send :attr_accessor, :available_configs
|
||||
class << mod; attr_accessor :available_configs; end
|
||||
mod.available_configs = accessors
|
||||
|
||||
accessors.each do |accessor|
|
||||
@@ -39,6 +49,29 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
def self.check_fields!(klass)
|
||||
failed_attributes = []
|
||||
instance = klass.new
|
||||
|
||||
klass.devise_modules.each do |mod|
|
||||
constant = const_get(mod.to_s.classify)
|
||||
|
||||
if constant.respond_to?(:required_fields)
|
||||
constant.required_fields(klass).each do |field|
|
||||
failed_attributes << field unless instance.respond_to?(field)
|
||||
end
|
||||
else
|
||||
ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
|
||||
"Devise uses required_fields to warn developers of any missing fields in their models. " \
|
||||
"Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
|
||||
end
|
||||
end
|
||||
|
||||
if failed_attributes.any?
|
||||
fail Devise::Models::MissingAttribute.new(failed_attributes)
|
||||
end
|
||||
end
|
||||
|
||||
# Include the chosen devise modules in your model:
|
||||
#
|
||||
# devise :database_authenticatable, :confirmable, :recoverable
|
||||
@@ -57,6 +90,10 @@ module Devise
|
||||
devise_modules_hook! do
|
||||
include Devise::Models::Authenticatable
|
||||
selected_modules.each do |m|
|
||||
if m == :encryptable && !(defined?(Devise::Models::Encryptable))
|
||||
warn "[DEVISE] You're trying to include :encryptable in your model but it is not bundled with the Devise gem anymore. Please add `devise-encryptable` to your Gemfile to proceed.\n"
|
||||
end
|
||||
|
||||
mod = Devise::Models.const_get(m.to_s.classify)
|
||||
|
||||
if mod.const_defined?("ClassMethods")
|
||||
@@ -66,7 +103,7 @@ module Devise
|
||||
if class_mod.respond_to?(:available_configs)
|
||||
available_configs = class_mod.available_configs
|
||||
available_configs.each do |config|
|
||||
next unless options.key?(config)
|
||||
next unless options.key?(config)
|
||||
send(:"#{config}=", options.delete(config))
|
||||
end
|
||||
end
|
||||
@@ -80,12 +117,12 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
# The hook which is called inside devise. So your ORM can include devise
|
||||
# compatibility stuff.
|
||||
# The hook which is called inside devise.
|
||||
# So your ORM can include devise compatibility stuff.
|
||||
def devise_modules_hook!
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'devise/models/authenticatable'
|
||||
require 'devise/models/authenticatable'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
require 'devise/hooks/activatable'
|
||||
require 'devise/models/serializable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
@@ -52,7 +51,10 @@ module Devise
|
||||
module Authenticatable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Devise::Models::Serializable
|
||||
BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
|
||||
:remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
|
||||
:last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
|
||||
:remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]
|
||||
|
||||
included do
|
||||
class_attribute :devise_modules, :instance_writer => false
|
||||
@@ -62,6 +64,10 @@ module Devise
|
||||
before_validation :strip_whitespace
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
# Check if the current object is valid for authentication. This method and
|
||||
# find_for_authentication are the methods used in a Warden::Strategy to check
|
||||
# if a model should be signed in or not.
|
||||
@@ -72,6 +78,10 @@ module Devise
|
||||
block_given? ? yield : true
|
||||
end
|
||||
|
||||
def unauthenticated_message
|
||||
:invalid
|
||||
end
|
||||
|
||||
def active_for_authentication?
|
||||
true
|
||||
end
|
||||
@@ -83,20 +93,82 @@ module Devise
|
||||
def authenticatable_salt
|
||||
end
|
||||
|
||||
def devise_mailer
|
||||
Devise.mailer
|
||||
end
|
||||
|
||||
def headers_for(name)
|
||||
{}
|
||||
end
|
||||
|
||||
array = %w(serializable_hash)
|
||||
# to_xml does not call serializable_hash on 3.1
|
||||
array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
|
||||
|
||||
array.each do |method|
|
||||
class_eval <<-RUBY, __FILE__, __LINE__
|
||||
# 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.
|
||||
def #{method}(options=nil)
|
||||
options ||= {}
|
||||
options[:except] = Array(options[:except])
|
||||
|
||||
if options[:force_except]
|
||||
options[:except].concat Array(options[:force_except])
|
||||
else
|
||||
options[:except].concat BLACKLIST_FOR_SERIALIZATION
|
||||
end
|
||||
super(options)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def devise_mailer
|
||||
Devise.mailer
|
||||
end
|
||||
|
||||
# This is an internal method called every time Devise needs
|
||||
# to send a notification/mail. This can be overriden if you
|
||||
# need to customize the e-mail delivery logic. For instance,
|
||||
# if you are using a queue to deliver e-mails (delayed job,
|
||||
# sidekiq, resque, etc), you must add the delivery to the queue
|
||||
# just after the transaction was committed. To achieve this,
|
||||
# you can override send_devise_notification to store the
|
||||
# deliveries until the after_commit callback is triggered:
|
||||
#
|
||||
# class User
|
||||
# devise :database_authenticatable, :confirmable
|
||||
#
|
||||
# after_commit :send_pending_notifications
|
||||
#
|
||||
# protected
|
||||
#
|
||||
# def send_devise_notification(notification)
|
||||
# pending_notifications << notification
|
||||
# end
|
||||
#
|
||||
# def send_pending_notifications
|
||||
# pending_notifications.each do |n|
|
||||
# devise_mailer.send(n, self).deliver
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def pending_notifications
|
||||
# @pending_notifications ||= []
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def send_devise_notification(notification)
|
||||
devise_mailer.send(notification, self).deliver
|
||||
end
|
||||
|
||||
def downcase_keys
|
||||
(self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
|
||||
self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
(self.class.strip_whitespace_keys || []).each { |k| self[k].try(:strip!) }
|
||||
self.class.strip_whitespace_keys.each { |k| self[k].try(:strip!) }
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
@@ -123,6 +195,12 @@ module Devise
|
||||
end
|
||||
|
||||
# Find first record based on conditions given (ie by the sign in form).
|
||||
# This method is always called during an authentication process but
|
||||
# it may be wrapped as well. For instance, database authenticatable
|
||||
# provides a `find_for_database_authentication` that wraps a call to
|
||||
# this method. This allows you to customize both database authenticatable
|
||||
# or the whole authenticate stack by customize `find_for_authentication.`
|
||||
#
|
||||
# Overwrite to add customized conditions, create a join, or maybe use a
|
||||
# namedscope to filter records while authenticating.
|
||||
# Example:
|
||||
@@ -132,6 +210,10 @@ module Devise
|
||||
# super
|
||||
# end
|
||||
#
|
||||
# Finally, notice that Devise also queries for users in other scenarios
|
||||
# besides authentication, for example when retrieving an user to send
|
||||
# an e-mail for password reset. In such cases, find_for_authentication
|
||||
# is not called.
|
||||
def find_for_authentication(conditions)
|
||||
find_first_by_auth_conditions(conditions)
|
||||
end
|
||||
@@ -183,4 +265,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,13 @@ module Devise
|
||||
before_create :generate_confirmation_token, :if => :confirmation_required?
|
||||
after_create :send_on_create_confirmation_instructions, :if => :confirmation_required?
|
||||
before_update :postpone_email_change_until_confirmation, :if => :postpone_email_change?
|
||||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
|
||||
required_methods << :unconfirmed_email if klass.reconfirmable
|
||||
required_methods
|
||||
end
|
||||
|
||||
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
||||
@@ -45,7 +51,7 @@ module Devise
|
||||
self.confirmed_at = Time.now.utc
|
||||
|
||||
if self.class.reconfirmable && unconfirmed_email.present?
|
||||
@bypass_postpone = true
|
||||
skip_reconfirmation!
|
||||
self.email = unconfirmed_email
|
||||
self.unconfirmed_email = nil
|
||||
|
||||
@@ -72,7 +78,7 @@ module Devise
|
||||
@reconfirmation_required = false
|
||||
|
||||
generate_confirmation_token! if self.confirmation_token.blank?
|
||||
self.devise_mailer.confirmation_instructions(self).deliver
|
||||
send_devise_notification(:confirmation_instructions)
|
||||
end
|
||||
|
||||
# Resend confirmation token. This method does not need to generate a new token.
|
||||
@@ -99,6 +105,12 @@ module Devise
|
||||
self.confirmed_at = Time.now.utc
|
||||
end
|
||||
|
||||
# If you don't want reconfirmation to be sent, neither a code
|
||||
# to be generated, call skip_reconfirmation!
|
||||
def skip_reconfirmation!
|
||||
@bypass_postpone = true
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
headers = super
|
||||
if action == :confirmation_instructions && pending_reconfirmation?
|
||||
@@ -113,7 +125,7 @@ module Devise
|
||||
# instructions on creation. This can be overriden
|
||||
# in models to map to a nice sign up e-mail.
|
||||
def send_on_create_confirmation_instructions
|
||||
self.devise_mailer.confirmation_instructions(self).deliver
|
||||
send_devise_notification(:confirmation_instructions)
|
||||
end
|
||||
|
||||
# Callback to overwrite if confirmation is required or not.
|
||||
|
||||
@@ -27,6 +27,10 @@ module Devise
|
||||
attr_accessor :password_confirmation
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:encrypted_password] + klass.authentication_keys
|
||||
end
|
||||
|
||||
# Generates password encryption based on the given value.
|
||||
def password=(new_password)
|
||||
@password = new_password
|
||||
@@ -36,9 +40,9 @@ module Devise
|
||||
# Verifies whether an password (ie from sign in) is the user password.
|
||||
def valid_password?(password)
|
||||
return false if encrypted_password.blank?
|
||||
bcrypt = ::BCrypt::Password.new(self.encrypted_password)
|
||||
bcrypt = ::BCrypt::Password.new(encrypted_password)
|
||||
password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
|
||||
Devise.secure_compare(password, self.encrypted_password)
|
||||
Devise.secure_compare(password, encrypted_password)
|
||||
end
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
@@ -60,7 +64,7 @@ module Devise
|
||||
result = if valid_password?(current_password)
|
||||
update_attributes(params, *options)
|
||||
else
|
||||
self.attributes = params
|
||||
self.assign_attributes(params, *options)
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
@@ -96,7 +100,7 @@ module Devise
|
||||
|
||||
# A reliable way to expose the salt regardless of the implementation.
|
||||
def authenticatable_salt
|
||||
self.encrypted_password[0,29] if self.encrypted_password
|
||||
encrypted_password[0,29] if encrypted_password
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
require 'devise/strategies/database_authenticatable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Encryptable Module adds support to several encryptors.
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# Encryptable adds the following options to devise_for:
|
||||
#
|
||||
# * +pepper+: a random string used to provide a more secure hash.
|
||||
#
|
||||
# * +encryptor+: the encryptor going to be used. By default is nil.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# User.find(1).valid_password?('password123') # returns true/false
|
||||
#
|
||||
module Encryptable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attr_reader :password, :current_password
|
||||
attr_accessor :password_confirmation
|
||||
end
|
||||
|
||||
# Generates password salt.
|
||||
def password=(new_password)
|
||||
self.password_salt = self.class.password_salt if new_password.present?
|
||||
super
|
||||
end
|
||||
|
||||
def authenticatable_salt
|
||||
self.password_salt
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
Devise.secure_compare(password_digest(incoming_password), self.encrypted_password)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Digests the password using the configured encryptor.
|
||||
def password_digest(password)
|
||||
if self.password_salt.present?
|
||||
self.class.encryptor_class.digest(password, self.class.stretches, self.password_salt, self.class.pepper)
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :encryptor)
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= case encryptor
|
||||
when :bcrypt
|
||||
raise "In order to use bcrypt as encryptor, simply remove :encryptable from your devise model"
|
||||
when nil
|
||||
raise "You need to give an :encryptor as option in order to use :encryptable"
|
||||
else
|
||||
::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
end
|
||||
end
|
||||
|
||||
def password_salt
|
||||
self.encryptor_class.salt(self.stretches)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,5 @@
|
||||
require "devise/hooks/lockable"
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Handles blocking a user access after a certain number of attempts.
|
||||
@@ -22,19 +24,28 @@ module Devise
|
||||
|
||||
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
|
||||
|
||||
def self.required_fields(klass)
|
||||
attributes = []
|
||||
attributes << :failed_attempts if klass.lock_strategy_enabled?(:failed_attempts)
|
||||
attributes << :unlock_at if klass.unlock_strategy_enabled?(:time)
|
||||
attributes << :unlock_token if klass.unlock_strategy_enabled?(:email)
|
||||
|
||||
attributes
|
||||
end
|
||||
|
||||
# Lock a user setting its locked_at to actual time.
|
||||
def lock_access!
|
||||
self.locked_at = Time.now.utc
|
||||
|
||||
if unlock_strategy_enabled?(:email)
|
||||
generate_unlock_token
|
||||
generate_unlock_token!
|
||||
send_unlock_instructions
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Unlock a user by cleaning locket_at and failed_attempts.
|
||||
# Unlock a user by cleaning locked_at and failed_attempts.
|
||||
def unlock_access!
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
@@ -49,7 +60,7 @@ module Devise
|
||||
|
||||
# Send unlock instructions by email
|
||||
def send_unlock_instructions
|
||||
self.devise_mailer.unlock_instructions(self).deliver
|
||||
send_devise_notification(:unlock_instructions)
|
||||
end
|
||||
|
||||
# Resend the unlock instructions if the user is locked.
|
||||
@@ -80,15 +91,12 @@ module Devise
|
||||
unlock_access! if lock_expired?
|
||||
|
||||
if super && !access_locked?
|
||||
self.failed_attempts = 0
|
||||
save(:validate => false)
|
||||
true
|
||||
else
|
||||
self.failed_attempts ||= 0
|
||||
self.failed_attempts += 1
|
||||
if attempts_exceeded?
|
||||
lock_access! unless access_locked?
|
||||
return :locked
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
@@ -96,6 +104,14 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
def unauthenticated_message
|
||||
if lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
|
||||
:locked
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def attempts_exceeded?
|
||||
@@ -107,6 +123,10 @@ module Devise
|
||||
self.unlock_token = self.class.unlock_token
|
||||
end
|
||||
|
||||
def generate_unlock_token!
|
||||
generate_unlock_token && save(:validate => false)
|
||||
end
|
||||
|
||||
# Tells if the lock is expired if :time unlock strategy is active
|
||||
def lock_expired?
|
||||
if unlock_strategy_enabled?(:time)
|
||||
@@ -133,9 +153,9 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
def send_unlock_instructions(attributes={})
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
end
|
||||
|
||||
# Find a user by its unlock token and try to unlock it.
|
||||
|
||||
@@ -15,6 +15,10 @@ module Devise
|
||||
module Omniauthable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :omniauth_providers)
|
||||
end
|
||||
|
||||
@@ -24,6 +24,10 @@ module Devise
|
||||
module Recoverable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:reset_password_sent_at, :reset_password_token]
|
||||
end
|
||||
|
||||
# Update password saving the record and clearing token. Returns true if
|
||||
# the passwords are valid and the record was saved, false otherwise.
|
||||
def reset_password!(new_password, new_password_confirmation)
|
||||
@@ -41,7 +45,7 @@ module Devise
|
||||
# Resets reset password token and send reset password instructions by email
|
||||
def send_reset_password_instructions
|
||||
generate_reset_password_token! if should_generate_reset_token?
|
||||
self.devise_mailer.reset_password_instructions(self).deliver
|
||||
send_devise_notification(:reset_password_instructions)
|
||||
end
|
||||
|
||||
# Checks if the reset password token sent is within the limit time.
|
||||
|
||||
@@ -5,6 +5,10 @@ module Devise
|
||||
module Registerable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# A convenience method that receives both parameters and session to
|
||||
# initialize a user. This can be used by OAuth, for example, to send
|
||||
|
||||
@@ -24,7 +24,7 @@ module Devise
|
||||
# * +extend_remember_period+: if true, extends the user's remember period
|
||||
# when remembered via cookie. False by default.
|
||||
#
|
||||
# * +cookie_options+: configuration options passed to the created cookie.
|
||||
# * +rememberable_options+: configuration options passed to the created cookie.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
@@ -41,9 +41,14 @@ module Devise
|
||||
|
||||
attr_accessor :remember_me, :extend_remember_period
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:remember_created_at]
|
||||
end
|
||||
|
||||
# Generate a new remember token and save the record without validations
|
||||
# unless remember_across_browsers is true and the user already has a valid token.
|
||||
def remember_me!(extend_period=false)
|
||||
self.remember_token = self.class.remember_token if generate_remember_token?
|
||||
self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period)
|
||||
save(:validate => false)
|
||||
end
|
||||
@@ -51,11 +56,10 @@ module Devise
|
||||
# If the record is persisted, remove the remember token (but only if
|
||||
# it exists), and save the record without validations.
|
||||
def forget_me!
|
||||
if persisted?
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
return unless persisted?
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Remember token should be expired if expiration time not overpass now.
|
||||
@@ -69,21 +73,28 @@ module Devise
|
||||
end
|
||||
|
||||
def rememberable_value
|
||||
if salt = authenticatable_salt
|
||||
if respond_to?(:remember_token)
|
||||
remember_token
|
||||
elsif respond_to?(:authenticatable_salt) && (salt = authenticatable_salt)
|
||||
salt
|
||||
else
|
||||
raise "authenticable_salt returned nil for the #{self.class.name} model. " \
|
||||
"In order to use rememberable, you must ensure a password is always set " \
|
||||
"or implement rememberable_value in your model with your own logic."
|
||||
"or have a remember_token column in your model or implement your own " \
|
||||
"rememberable_value in the model with custom logic."
|
||||
end
|
||||
end
|
||||
|
||||
def cookie_options
|
||||
self.class.cookie_options
|
||||
def rememberable_options
|
||||
self.class.rememberable_options
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def generate_remember_token? #:nodoc:
|
||||
respond_to?(:remember_token) && remember_expired?
|
||||
end
|
||||
|
||||
# Generate a timestamp if extend_remember_period is true, if no remember_token
|
||||
# exists, or if an existing remember token has expired.
|
||||
def generate_remember_timestamp?(extend_period) #:nodoc:
|
||||
@@ -103,11 +114,11 @@ module Devise
|
||||
end
|
||||
|
||||
# Generate a token checking if one does not already exist in the database.
|
||||
def remember_token
|
||||
def remember_token #:nodoc:
|
||||
generate_token(:remember_token)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :remember_for, :extend_remember_period, :cookie_options)
|
||||
Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
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
|
||||
|
||||
array = %w(serializable_hash)
|
||||
# to_xml does not call serializable_hash on 3.1
|
||||
array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
|
||||
|
||||
array.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
|
||||
@@ -20,6 +20,10 @@ module Devise
|
||||
module Timeoutable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
# Checks whether the user session has expired based on configured time.
|
||||
def timedout?(last_access)
|
||||
return false if remember_exists_and_not_expired?
|
||||
|
||||
@@ -27,6 +27,10 @@ module Devise
|
||||
module TokenAuthenticatable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:authentication_token]
|
||||
end
|
||||
|
||||
# Generate new authentication token (a.k.a. "single access token").
|
||||
def reset_authentication_token
|
||||
self.authentication_token = self.class.authentication_token
|
||||
@@ -52,6 +56,10 @@ module Devise
|
||||
def after_token_authentication
|
||||
end
|
||||
|
||||
def expire_auth_token_on_timeout
|
||||
self.class.expire_auth_token_on_timeout
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def find_for_token_authentication(conditions)
|
||||
find_for_authentication(:authentication_token => conditions[token_authentication_key])
|
||||
@@ -62,7 +70,7 @@ module Devise
|
||||
generate_token(:authentication_token)
|
||||
end
|
||||
|
||||
::Devise::Models.config(self, :token_authentication_key)
|
||||
Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,6 +11,10 @@ module Devise
|
||||
# * last_sign_in_ip - Holds the remote ip of the previous sign in
|
||||
#
|
||||
module Trackable
|
||||
def self.required_fields(klass)
|
||||
[:current_sign_in_at, :current_sign_in_ip, :last_sign_in_at, :last_sign_in_ip, :sign_in_count]
|
||||
end
|
||||
|
||||
def update_tracked_fields!(request)
|
||||
old_current, new_current = self.current_sign_in_at, Time.now.utc
|
||||
self.last_sign_in_at = old_current || new_current
|
||||
@@ -23,7 +27,8 @@ module Devise
|
||||
self.sign_in_count ||= 0
|
||||
self.sign_in_count += 1
|
||||
|
||||
save(:validate => false)
|
||||
save(:validate => false) or raise "Devise trackable could not save #{inspect}." \
|
||||
"Please make sure a model using trackable can be saved at sign in."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,10 @@ module Devise
|
||||
VALIDATIONS = [ :validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
||||
:validates_confirmation_of, :validates_length_of ].freeze
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
base.extend ClassMethods
|
||||
assert_validations_api!(base)
|
||||
|
||||
@@ -10,7 +10,6 @@ Devise.with_options :model => true do |d|
|
||||
end
|
||||
|
||||
# Other authentications
|
||||
d.add_module :encryptable
|
||||
d.add_module :omniauthable, :controller => :omniauth_callbacks, :route => :omniauth_callback
|
||||
|
||||
# Misc after
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
begin
|
||||
require "omniauth"
|
||||
require "omniauth/version"
|
||||
rescue LoadError => e
|
||||
rescue LoadError
|
||||
warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
|
||||
raise
|
||||
end
|
||||
|
||||
@@ -2,21 +2,6 @@ module Devise
|
||||
module OmniAuth
|
||||
module UrlHelpers
|
||||
def self.define_helpers(mapping)
|
||||
return unless mapping.omniauthable?
|
||||
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
|
||||
if Devise.omniauth_configs[provider.to_sym]
|
||||
script_name = request.env["SCRIPT_NAME"]
|
||||
|
||||
path = "\#{script_name}/#{mapping.path}/auth/\#{provider}\".squeeze("/")
|
||||
path << '?' + params.to_param if params.present?
|
||||
path
|
||||
else
|
||||
raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
|
||||
end
|
||||
end
|
||||
URL_HELPERS
|
||||
end
|
||||
|
||||
def omniauth_authorize_path(resource_or_scope, *args)
|
||||
|
||||
@@ -1,44 +1,3 @@
|
||||
require 'orm_adapter/adapters/active_record'
|
||||
|
||||
module Devise
|
||||
module Orm
|
||||
# This module contains some helpers and handle schema (migrations):
|
||||
#
|
||||
# create_table :accounts do |t|
|
||||
# t.database_authenticatable
|
||||
# t.confirmable
|
||||
# t.recoverable
|
||||
# t.rememberable
|
||||
# t.trackable
|
||||
# t.lockable
|
||||
# t.timestamps
|
||||
# end
|
||||
#
|
||||
# However this method does not add indexes. If you need them, here is the declaration:
|
||||
#
|
||||
# add_index "accounts", ["email"], :name => "email", :unique => true
|
||||
# add_index "accounts", ["confirmation_token"], :name => "confirmation_token", :unique => true
|
||||
# add_index "accounts", ["reset_password_token"], :name => "reset_password_token", :unique => true
|
||||
#
|
||||
module ActiveRecord
|
||||
module Schema
|
||||
include Devise::Schema
|
||||
|
||||
# Tell how to apply schema methods.
|
||||
def apply_devise_schema(name, type, options={})
|
||||
@__devise_warning_raised ||= begin
|
||||
$stderr.puts "\n[DEVISE] You are using t.database_authenticatable and others in your migration " \
|
||||
"and this feature is deprecated. Please simply use Rails helpers instead as mentioned here:\n" \
|
||||
"https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n\n"
|
||||
true
|
||||
end
|
||||
column name, type.to_s.downcase.to_sym, options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.extend Devise::Models
|
||||
ActiveRecord::ConnectionAdapters::Table.send :include, Devise::Orm::ActiveRecord::Schema
|
||||
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Orm::ActiveRecord::Schema
|
||||
ActiveRecord::Base.extend Devise::Models
|
||||
@@ -1,31 +1,3 @@
|
||||
require 'orm_adapter/adapters/mongoid'
|
||||
|
||||
module Devise
|
||||
module Orm
|
||||
module Mongoid
|
||||
module Hook
|
||||
def devise_modules_hook!
|
||||
extend Schema
|
||||
yield
|
||||
return unless Devise.apply_schema
|
||||
devise_modules.each { |m| send(m) if respond_to?(m, true) }
|
||||
end
|
||||
end
|
||||
|
||||
module Schema
|
||||
include Devise::Schema
|
||||
|
||||
# Tell how to apply schema methods
|
||||
def apply_devise_schema(name, type, options={})
|
||||
type = Time if type == DateTime
|
||||
field name, { :type => type }.merge!(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Mongoid::Document::ClassMethods.class_eval do
|
||||
include Devise::Models
|
||||
include Devise::Orm::Mongoid::Hook
|
||||
end
|
||||
Mongoid::Document::ClassMethods.send :include, Devise::Models
|
||||
@@ -1,23 +0,0 @@
|
||||
module Devise
|
||||
class PathChecker
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
def self.default_url_options(*args)
|
||||
if defined?(ApplicationController)
|
||||
ApplicationController.default_url_options(*args)
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(env, scope)
|
||||
@current_path = "/#{env["SCRIPT_NAME"]}/#{env["PATH_INFO"]}".squeeze("/")
|
||||
@scope = scope
|
||||
end
|
||||
|
||||
def signing_out?
|
||||
route = "destroy_#{@scope}_session_path"
|
||||
respond_to?(route) && @current_path == send(route)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -43,69 +43,12 @@ module Devise
|
||||
end
|
||||
|
||||
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
|
||||
# We can get rid of this once we support Rails > 3.2
|
||||
# We can get rid of this once we support only Rails > 3.2
|
||||
ActionDispatch::Routing::RoutesProxy.class_eval do
|
||||
def respond_to?(method, include_private = false)
|
||||
super || routes.url_helpers.respond_to?(method)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.deprecations" do
|
||||
unless defined?(Rails::Generators)
|
||||
if Devise.case_insensitive_keys == false
|
||||
warn "\n[DEVISE] Devise.case_insensitive_keys is false which is no longer " \
|
||||
"supported. Recent Devise versions automatically downcase the e-mail before " \
|
||||
"saving it to the database but your app isn't using this feature. You can solve " \
|
||||
"this issue by either:\n\n" \
|
||||
"1) Setting config.case_insensitive_keys = [:email] in your Devise initializer and " \
|
||||
"running a migration that will downcase all emails already in the database;\n\n" \
|
||||
"2) Setting config.case_insensitive_keys = [] (so nothing will be downcased) and " \
|
||||
"making sure you are not using Devise :validatable (since validatable assumes case" \
|
||||
"insensitivity)\n"
|
||||
end
|
||||
|
||||
if Devise.apply_schema && defined?(Mongoid)
|
||||
warn "\n[DEVISE] Devise.apply_schema is true. This means Devise was " \
|
||||
"automatically configuring your DB. This no longer happens. You should " \
|
||||
"set Devise.apply_schema to false and manually set the fields used by Devise as shown here: " \
|
||||
"https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n"
|
||||
end
|
||||
|
||||
# TODO: Deprecate the true value of this option as well
|
||||
if Devise.use_salt_as_remember_token == false
|
||||
warn "\n[DEVISE] Devise.use_salt_as_remember_token is false which is no longer " \
|
||||
"supported. Devise now only uses the salt as remember token and the remember_token " \
|
||||
"column can be removed from your models.\n"
|
||||
end
|
||||
|
||||
if Devise.reset_password_within.nil?
|
||||
warn "\n[DEVISE] Devise.reset_password_within is nil. Please set this value to " \
|
||||
"an interval (for example, 6.hours) and add a reset_password_sent_at field to " \
|
||||
"your Devise models (if they don't have one already).\n"
|
||||
end
|
||||
end
|
||||
|
||||
config.after_initialize do
|
||||
example = <<-YAML
|
||||
en:
|
||||
devise:
|
||||
registrations:
|
||||
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
|
||||
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
||||
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
||||
YAML
|
||||
|
||||
if I18n.t(:"devise.registrations.reasons", :default => {}).present?
|
||||
warn "\n[DEVISE] devise.registrations.reasons in yml files is deprecated, " \
|
||||
"please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
|
||||
end
|
||||
|
||||
if I18n.t(:"devise.registrations.inactive_signed_up", :default => "").present?
|
||||
warn "\n[DEVISE] devise.registrations.inactive_signed_up in yml files is deprecated, " \
|
||||
"please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
require "active_support/core_ext/object/try"
|
||||
require "active_support/core_ext/hash/slice"
|
||||
|
||||
module ActionDispatch::Routing
|
||||
class RouteSet #:nodoc:
|
||||
# Ensure Devise modules are included only after loading routes, because we
|
||||
# need devise_for mappings already declared to create filters and helpers.
|
||||
def finalize_with_devise!
|
||||
finalize_without_devise!
|
||||
result = finalize_without_devise!
|
||||
|
||||
@devise_finalized ||= begin
|
||||
if Devise.router_name.nil? && self != Rails.application.try(:routes)
|
||||
warn "[Devise] We have detected that you are using devise_for inside engine routes. " \
|
||||
if Devise.router_name.nil? && defined?(@devise_finalized) && self != Rails.application.try(:routes)
|
||||
warn "[DEVISE] We have detected that you are using devise_for inside engine routes. " \
|
||||
"In this case, you probably want to set Devise.router_name = MOUNT_POINT, where " \
|
||||
"MOUNT_POINT is a symbol representing where this engine will be mounted at. For " \
|
||||
"now, Devise will default the mount point to :main_app."
|
||||
"now Devise will default the mount point to :main_app. You can explicitly set it" \
|
||||
" to :main_app as well in case you want to keep the current behavior."
|
||||
end
|
||||
|
||||
Devise.router_name ||= :main_app
|
||||
Devise.configure_warden!
|
||||
Devise.regenerate_helpers!
|
||||
true
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
alias_method_chain :finalize!, :devise
|
||||
end
|
||||
@@ -134,7 +137,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# devise_for :users, :format => false
|
||||
#
|
||||
# * :constraints => works the same as Rails' contraints
|
||||
# * :constraints => works the same as Rails' constraints
|
||||
#
|
||||
# * :defaults => works the same as Rails' defaults
|
||||
#
|
||||
@@ -182,7 +185,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# In order to get Devise to recognize the deactivate action, your devise_for entry should look like this,
|
||||
#
|
||||
# devise_for :owners, :controllers => { :registrations => "registrations" } do
|
||||
# devise_scope :owner do
|
||||
# post "deactivate", :to => "registrations#deactivate", :as => "deactivate_registration"
|
||||
# end
|
||||
#
|
||||
@@ -196,7 +199,8 @@ module ActionDispatch::Routing
|
||||
options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
|
||||
options[:constraints] = (@scope[:constraints] || {}).merge(options[:constraints] || {})
|
||||
options[:defaults] = (@scope[:defaults] || {}).merge(options[:defaults] || {})
|
||||
options[:options] = (@scope[:options] || {}).merge({:format => false}) if options[:format] == false
|
||||
options[:options] = @scope[:options] || {}
|
||||
options[:options][:format] = false if options[:format] == false
|
||||
|
||||
resources.map!(&:to_sym)
|
||||
|
||||
@@ -233,7 +237,9 @@ module ActionDispatch::Routing
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to add authentication request from the router:
|
||||
# Allow you to add authentication request from the router.
|
||||
# Takes an optional scope and block to provide constraints
|
||||
# on the model instance itself.
|
||||
#
|
||||
# authenticate do
|
||||
# resources :post
|
||||
@@ -243,9 +249,13 @@ module ActionDispatch::Routing
|
||||
# resources :users
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil)
|
||||
# authenticate :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show"
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate!(:scope => scope)
|
||||
request.env["warden"].authenticate!(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
@@ -254,7 +264,8 @@ module ActionDispatch::Routing
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is authenticated. You
|
||||
# can optionally specify which scope.
|
||||
# can optionally specify which scope and a block. The block accepts
|
||||
# a model and allows extra constraints to be done on the instance.
|
||||
#
|
||||
# authenticated :admin do
|
||||
# root :to => 'admin/dashboard#show'
|
||||
@@ -264,11 +275,15 @@ module ActionDispatch::Routing
|
||||
# root :to => 'dashboard#show'
|
||||
# end
|
||||
#
|
||||
# authenticated :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show"
|
||||
# end
|
||||
#
|
||||
# root :to => 'landing#show'
|
||||
#
|
||||
def authenticated(scope=nil)
|
||||
def authenticated(scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate? :scope => scope
|
||||
request.env["warden"].authenticate?(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
@@ -364,16 +379,54 @@ module ActionDispatch::Routing
|
||||
:cancel => mapping.path_names[:cancel]
|
||||
}
|
||||
|
||||
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
|
||||
:path_names => path_names, :controller => controllers[:registrations] do
|
||||
options = {
|
||||
:only => [:new, :create, :edit, :update, :destroy],
|
||||
:path => mapping.path_names[:registration],
|
||||
:path_names => path_names,
|
||||
:controller => controllers[:registrations]
|
||||
}
|
||||
|
||||
resource :registration, options do
|
||||
get :cancel
|
||||
end
|
||||
end
|
||||
|
||||
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
||||
path, @scope[:path] = @scope[:path], nil
|
||||
path_prefix = "/#{mapping.path}/auth".squeeze("/")
|
||||
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.path}/auth".squeeze("/")
|
||||
set_omniauth_path_prefix!(path_prefix)
|
||||
|
||||
providers = Regexp.union(mapping.to.omniauth_providers.map(&:to_s))
|
||||
|
||||
match "#{path_prefix}/:provider",
|
||||
:constraints => { :provider => providers },
|
||||
:to => "#{controllers[:omniauth_callbacks]}#passthru",
|
||||
:as => :omniauth_authorize
|
||||
|
||||
match "#{path_prefix}/:action/callback",
|
||||
:constraints => { :action => providers },
|
||||
:to => controllers[:omniauth_callbacks],
|
||||
:as => :omniauth_callback
|
||||
ensure
|
||||
@scope[:path] = path
|
||||
end
|
||||
|
||||
DEVISE_SCOPE_KEYS = [:as, :path, :module, :constraints, :defaults, :options]
|
||||
|
||||
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
||||
old = {}
|
||||
DEVISE_SCOPE_KEYS.each { |k| old[k] = @scope[k] }
|
||||
|
||||
new = { :as => new_as, :path => new_path, :module => nil }
|
||||
new.merge!(options.slice(:constraints, :defaults, :options))
|
||||
|
||||
@scope.merge!(new)
|
||||
yield
|
||||
ensure
|
||||
@scope.merge!(old)
|
||||
end
|
||||
|
||||
def set_omniauth_path_prefix!(path_prefix) #:nodoc:
|
||||
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
|
||||
raise "Wrong OmniAuth configuration. If you are getting this exception, it means that either:\n\n" \
|
||||
"1) You are manually setting OmniAuth.config.path_prefix and it doesn't match the Devise one\n" \
|
||||
@@ -382,22 +435,6 @@ module ActionDispatch::Routing
|
||||
else
|
||||
::OmniAuth.config.path_prefix = path_prefix
|
||||
end
|
||||
|
||||
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, options) #:nodoc:
|
||||
old_as, old_path, old_module, old_constraints, old_defaults, old_options =
|
||||
*@scope.values_at(:as, :path, :module, :constraints, :defaults, :options)
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
|
||||
new_as, new_path, nil, *options.values_at(:constraints, :defaults, :options)
|
||||
yield
|
||||
ensure
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
|
||||
old_as, old_path, old_module, old_constraints, old_defaults, old_options
|
||||
end
|
||||
|
||||
def raise_no_devise_method_error!(klass) #:nodoc:
|
||||
|
||||
@@ -21,17 +21,23 @@ class Warden::SessionSerializer
|
||||
end
|
||||
|
||||
def deserialize(keys)
|
||||
klass, *args = keys
|
||||
klass_name, *args = keys
|
||||
|
||||
begin
|
||||
ActiveSupport::Inflector.constantize(klass).serialize_from_session(*args)
|
||||
klass = ActiveSupport::Inflector.constantize(klass_name)
|
||||
if klass.respond_to? :serialize_from_session
|
||||
klass.serialize_from_session(*args)
|
||||
else
|
||||
Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
|
||||
nil
|
||||
end
|
||||
rescue NameError => e
|
||||
if e.message =~ /uninitialized constant/
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass_name}"
|
||||
nil
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
module Devise
|
||||
# Holds devise schema information. To use it, just include its methods
|
||||
# and overwrite the apply_schema method.
|
||||
module Schema
|
||||
|
||||
# Creates encrypted_password, and email when it is used as an authentication
|
||||
# key (default).
|
||||
#
|
||||
# == Options
|
||||
# * :null - When true, allow columns to be null.
|
||||
# * :default - Set to "" when :null is false, unless overridden.
|
||||
#
|
||||
# == Notes
|
||||
# For Datamapper compatibility, we explicitly hardcode the limit for the
|
||||
# encrypter password field in 128 characters.
|
||||
def database_authenticatable(options={})
|
||||
null = options[:null] || false
|
||||
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
||||
include_email = !respond_to?(:authentication_keys) || self.authentication_keys.include?(:email)
|
||||
|
||||
apply_devise_schema :email, String, :null => null, :default => default if include_email
|
||||
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
||||
end
|
||||
|
||||
# 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
|
||||
|
||||
# Creates authentication_token.
|
||||
def token_authenticatable
|
||||
apply_devise_schema :authentication_token, String
|
||||
end
|
||||
|
||||
# Creates confirmation_token, confirmed_at and confirmation_sent_at.
|
||||
def confirmable
|
||||
apply_devise_schema :confirmation_token, String
|
||||
apply_devise_schema :confirmed_at, DateTime
|
||||
apply_devise_schema :confirmation_sent_at, DateTime
|
||||
end
|
||||
|
||||
# Creates unconfirmed_email
|
||||
def reconfirmable
|
||||
apply_devise_schema :unconfirmed_email, String
|
||||
end
|
||||
|
||||
# Creates reset_password_token and reset_password_sent_at.
|
||||
#
|
||||
# == Options
|
||||
# * :reset_within - When true, adds a column that reset passwords within some date
|
||||
def recoverable(options={})
|
||||
use_within = options.fetch(:reset_within, Devise.reset_password_within.present?)
|
||||
apply_devise_schema :reset_password_token, String
|
||||
apply_devise_schema :reset_password_sent_at, DateTime if use_within
|
||||
end
|
||||
|
||||
# Creates remember_token and remember_created_at.
|
||||
#
|
||||
# == Options
|
||||
# * :use_salt - When true, does not create a remember_token and use password_salt instead.
|
||||
def rememberable(options={})
|
||||
use_salt = options.fetch(:use_salt, Devise.use_salt_as_remember_token)
|
||||
apply_devise_schema :remember_token, String unless use_salt
|
||||
apply_devise_schema :remember_created_at, DateTime
|
||||
end
|
||||
|
||||
# Creates sign_in_count, current_sign_in_at, last_sign_in_at,
|
||||
# current_sign_in_ip, last_sign_in_ip.
|
||||
def trackable
|
||||
apply_devise_schema :sign_in_count, Integer, :default => 0
|
||||
apply_devise_schema :current_sign_in_at, DateTime
|
||||
apply_devise_schema :last_sign_in_at, DateTime
|
||||
apply_devise_schema :current_sign_in_ip, String
|
||||
apply_devise_schema :last_sign_in_ip, String
|
||||
end
|
||||
|
||||
# Creates failed_attempts, unlock_token and locked_at depending on the options given.
|
||||
#
|
||||
# == Options
|
||||
# * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
|
||||
# If :email or :both, creates a unlock_token field.
|
||||
# * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
|
||||
def lockable(options={})
|
||||
unlock_strategy = options[:unlock_strategy]
|
||||
unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
|
||||
unlock_strategy ||= :both
|
||||
|
||||
lock_strategy = options[:lock_strategy]
|
||||
lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
|
||||
lock_strategy ||= :failed_attempts
|
||||
|
||||
if lock_strategy == :failed_attempts
|
||||
apply_devise_schema :failed_attempts, Integer, :default => 0
|
||||
end
|
||||
|
||||
if [:both, :email].include?(unlock_strategy)
|
||||
apply_devise_schema :unlock_token, String
|
||||
end
|
||||
|
||||
apply_devise_schema :locked_at, DateTime
|
||||
end
|
||||
|
||||
# Overwrite with specific modification to create your own schema.
|
||||
def apply_devise_schema(name, type, options={})
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ module Devise
|
||||
attr_accessor :authentication_hash, :authentication_type, :password
|
||||
|
||||
def store?
|
||||
!mapping.to.skip_session_storage.include?(authentication_type)
|
||||
super && !mapping.to.skip_session_storage.include?(authentication_type)
|
||||
end
|
||||
|
||||
def valid?
|
||||
@@ -18,19 +18,36 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
# Simply invokes valid_for_authentication? with the given block and deal with the result.
|
||||
# Receives a resource and check if it is valid by calling valid_for_authentication?
|
||||
# An optional block that will be triggered while validating can be optionally
|
||||
# given as parameter. Check Devise::Models::Authenticable.valid_for_authentication?
|
||||
# for more information.
|
||||
#
|
||||
# In case the resource can't be validated, it will fail with the given
|
||||
# unauthenticated_message.
|
||||
def validate(resource, &block)
|
||||
unless resource
|
||||
ActiveSupport::Depreation.warn "an empty resource was given to #{self.class.name}#validate. " \
|
||||
"Please ensure the resource is not nil", caller
|
||||
end
|
||||
|
||||
result = resource && resource.valid_for_authentication?(&block)
|
||||
|
||||
case result
|
||||
when String, Symbol
|
||||
when Symbol, String
|
||||
ActiveSupport::Deprecation.warn "valid_for_authentication? should return a boolean value"
|
||||
fail!(result)
|
||||
false
|
||||
when TrueClass
|
||||
return false
|
||||
end
|
||||
|
||||
if result
|
||||
decorate(resource)
|
||||
true
|
||||
else
|
||||
result
|
||||
if resource
|
||||
fail!(resource.unauthenticated_message)
|
||||
end
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -78,8 +95,8 @@ module Devise
|
||||
|
||||
# Extract the appropriate subhash for authentication from params.
|
||||
def params_auth_hash
|
||||
params[scope]
|
||||
end
|
||||
params[scope]
|
||||
end
|
||||
|
||||
# Extract a hash with attributes:values from the http params.
|
||||
def http_auth_hash
|
||||
|
||||
@@ -2,6 +2,11 @@ module Devise
|
||||
module Strategies
|
||||
# Base strategy for Devise. Responsible for verifying correct scope and mapping.
|
||||
class Base < ::Warden::Strategies::Base
|
||||
# Whenever CSRF cannot be verified, we turn off any kind of storage
|
||||
def store?
|
||||
!env["devise.skip_storage"]
|
||||
end
|
||||
|
||||
# Checks if a valid scope was given for devise and find mapping based on this scope.
|
||||
def mapping
|
||||
@mapping ||= begin
|
||||
|
||||
@@ -6,12 +6,11 @@ module Devise
|
||||
class DatabaseAuthenticatable < Authenticatable
|
||||
def authenticate!
|
||||
resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
|
||||
return fail(:invalid) unless resource
|
||||
|
||||
if validate(resource){ resource.valid_password?(password) }
|
||||
resource.after_database_authentication
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
fail(:invalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'devise/strategies/base'
|
||||
require 'devise/strategies/authenticatable'
|
||||
|
||||
module Devise
|
||||
module Strategies
|
||||
@@ -19,11 +19,13 @@ module Devise
|
||||
def authenticate!
|
||||
resource = mapping.to.serialize_from_cookie(*remember_cookie)
|
||||
|
||||
unless resource
|
||||
cookies.delete(remember_key)
|
||||
return pass
|
||||
end
|
||||
|
||||
if validate(resource)
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
cookies.delete(remember_key)
|
||||
pass
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -16,12 +16,11 @@ module Devise
|
||||
|
||||
def authenticate!
|
||||
resource = mapping.to.find_for_token_authentication(authentication_hash)
|
||||
return fail(:invalid_token) unless resource
|
||||
|
||||
if validate(resource)
|
||||
resource.after_token_authentication
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
fail(:invalid_token)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -15,9 +15,8 @@ module Devise
|
||||
|
||||
# Override process to consider warden.
|
||||
def process(*)
|
||||
result = nil
|
||||
_catch_warden { result = super }
|
||||
result
|
||||
# Make sure we always return @response, a la ActionController::TestCase::Behaviour#process, even if warden interrupts
|
||||
_catch_warden { super } || @response
|
||||
end
|
||||
|
||||
# We need to setup the environment variables and the response in the controller.
|
||||
@@ -66,25 +65,66 @@ module Devise
|
||||
|
||||
protected
|
||||
|
||||
# Catch warden continuations and handle like the middleware would.
|
||||
# Returns nil when interrupted, otherwise the normal result of the block.
|
||||
def _catch_warden(&block)
|
||||
result = catch(:warden, &block)
|
||||
|
||||
if result.is_a?(Hash) && !warden.custom_failure? && !@controller.send(:performed?)
|
||||
result[:action] ||= :unauthenticated
|
||||
env = @controller.request.env
|
||||
|
||||
env = @controller.request.env
|
||||
env["PATH_INFO"] = "/#{result[:action]}"
|
||||
env["warden.options"] = result
|
||||
Warden::Manager._run_callbacks(:before_failure, env, result)
|
||||
result ||= {}
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
|
||||
nil
|
||||
# Set the response. In production, the rack result is returned
|
||||
# from Warden::Manager#call, which the following is modelled on.
|
||||
case result
|
||||
when Array
|
||||
if result.first == 401 && intercept_401?(env) # does this happen during testing?
|
||||
_process_unauthenticated(env)
|
||||
else
|
||||
result
|
||||
end
|
||||
when Hash
|
||||
_process_unauthenticated(env, result)
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def _process_unauthenticated(env, options = {})
|
||||
options[:action] ||= :unauthenticated
|
||||
proxy = env['warden']
|
||||
result = options[:result] || proxy.result
|
||||
|
||||
ret = case result
|
||||
when :redirect
|
||||
body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
|
||||
[proxy.status, proxy.headers, [body]]
|
||||
when :custom
|
||||
proxy.custom_response
|
||||
else
|
||||
env["PATH_INFO"] = "/#{options[:action]}"
|
||||
env["warden.options"] = options
|
||||
Warden::Manager._run_callbacks(:before_failure, env, options)
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
nil # causes process return @response
|
||||
end
|
||||
|
||||
# ensure that the controller response is set up. In production, this is
|
||||
# not necessary since warden returns the results to rack. However, at
|
||||
# testing time, we want the response to be available to the testing
|
||||
# framework to verify what would be returned to rack.
|
||||
if ret.is_a?(Array)
|
||||
# ensure the controller response is set to our response.
|
||||
@controller.response ||= @response
|
||||
@response.status = ret.first
|
||||
@response.headers = ret.second
|
||||
@response.body = ret.third
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "2.0.1".freeze
|
||||
VERSION = "2.1.1".freeze
|
||||
end
|
||||
|
||||
@@ -22,10 +22,17 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_class(model_path, class_name, model_contents + <<CONTENT) if model_exists?
|
||||
content = model_contents + <<CONTENT
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me
|
||||
CONTENT
|
||||
|
||||
class_path = class_name.to_s.split("::")
|
||||
|
||||
indent_depth = class_path.size - 1
|
||||
content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
|
||||
|
||||
inject_into_class(model_path, class_path.last, content) if model_exists?
|
||||
end
|
||||
|
||||
def migration_data
|
||||
@@ -48,9 +55,6 @@ CONTENT
|
||||
t.string :current_sign_in_ip
|
||||
t.string :last_sign_in_ip
|
||||
|
||||
## Encryptable
|
||||
# t.string :password_salt
|
||||
|
||||
## Confirmable
|
||||
# t.string :confirmation_token
|
||||
# t.datetime :confirmed_at
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
module Devise
|
||||
module Generators
|
||||
class DeviseGenerator < Rails::Generators::NamedBase
|
||||
include Rails::Generators::ResourceHelpers
|
||||
|
||||
namespace "devise"
|
||||
source_root File.expand_path("../templates", __FILE__)
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ module Devise
|
||||
def model_contents
|
||||
<<-CONTENT
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
|
||||
# :token_authenticatable, :confirmable,
|
||||
# :lockable, :timeoutable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
|
||||
@@ -39,6 +39,18 @@ module 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."
|
||||
hide!
|
||||
|
||||
# Override copy_views to just copy mailer and shared.
|
||||
def copy_views
|
||||
view_directory :shared
|
||||
end
|
||||
end
|
||||
|
||||
class FormForGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
@@ -80,15 +92,12 @@ module Devise
|
||||
end
|
||||
|
||||
class ViewsGenerator < Rails::Generators::Base
|
||||
include ViewPathTemplates
|
||||
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
desc "Copies Devise views to your application."
|
||||
|
||||
def copy_views
|
||||
copy_file "_links.erb", "#{target_path}/_links.erb"
|
||||
end
|
||||
argument :scope, :required => false, :default => nil,
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
invoke SharedViewsGenerator
|
||||
hook_for :form_builder, :aliases => "-b",
|
||||
:desc => "Form builder to be used",
|
||||
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"
|
||||
|
||||
@@ -20,9 +20,12 @@ module Mongoid
|
||||
def migration_data
|
||||
<<RUBY
|
||||
## Database authenticatable
|
||||
field :email, :type => String, :null => false, :default => ""
|
||||
field :encrypted_password, :type => String, :null => false, :default => ""
|
||||
field :email, :type => String, :default => ""
|
||||
field :encrypted_password, :type => String, :default => ""
|
||||
|
||||
validates_presence_of :email
|
||||
validates_presence_of :encrypted_password
|
||||
|
||||
## Recoverable
|
||||
field :reset_password_token, :type => String
|
||||
field :reset_password_sent_at, :type => Time
|
||||
@@ -37,9 +40,6 @@ module Mongoid
|
||||
field :current_sign_in_ip, :type => String
|
||||
field :last_sign_in_ip, :type => String
|
||||
|
||||
## Encryptable
|
||||
# field :password_salt, :type => String
|
||||
|
||||
## Confirmable
|
||||
# field :confirmation_token, :type => String
|
||||
# field :confirmed_at, :type => Time
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
|
||||
===============================================================================
|
||||
|
||||
Some setup you must do manually if you haven't yet:
|
||||
|
||||
1. Setup default url options for your specific environment. Here is an
|
||||
example of development environment:
|
||||
1. Ensure you have defined default url options in your environments files. Here
|
||||
is an example of default_url_options appropriate for a development environment
|
||||
in config/environments/development.rb:
|
||||
|
||||
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
||||
|
||||
This is a required Rails configuration. In production it must be the
|
||||
actual host of your application
|
||||
In production, :host should be set to the actual host of your application.
|
||||
|
||||
2. Ensure you have defined root_url to *something* in your config/routes.rb.
|
||||
For example:
|
||||
|
||||
@@ -9,9 +9,6 @@ Devise.setup do |config|
|
||||
# Configure the class responsible to send e-mails.
|
||||
# config.mailer = "Devise::Mailer"
|
||||
|
||||
# Automatically apply schema changes in tableless databases
|
||||
config.apply_schema = false
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default) and
|
||||
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
||||
@@ -95,7 +92,7 @@ Devise.setup do |config|
|
||||
# the user cannot access the website without confirming his account.
|
||||
# config.allow_unconfirmed_access_for = 2.days
|
||||
|
||||
# If true, requires any email changes to be confirmed (exctly the same way as
|
||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||
# db field (see migrations). Until confirmed new email is stored in
|
||||
# unconfirmed email column, and copied to email column on successful confirmation.
|
||||
@@ -111,13 +108,9 @@ Devise.setup do |config|
|
||||
# If true, extends the user's remember period when remembered via cookie.
|
||||
# config.extend_remember_period = false
|
||||
|
||||
# If true, uses the password salt as remember token. This should be turned
|
||||
# to false if you are not using database authenticatable.
|
||||
config.use_salt_as_remember_token = true
|
||||
|
||||
# Options to be passed to the created cookie. For instance, you can set
|
||||
# :secure => true in order to force SSL only cookies.
|
||||
# config.cookie_options = {}
|
||||
# config.rememberable_options = {}
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length. Default is 6..128.
|
||||
@@ -132,6 +125,9 @@ Devise.setup do |config|
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
# time the user will be asked for credentials again. Default is 30 minutes.
|
||||
# config.timeout_in = 30.minutes
|
||||
|
||||
# If true, expires auth token on session timeout.
|
||||
# config.expire_auth_token_on_timeout = false
|
||||
|
||||
# ==> Configuration for :lockable
|
||||
# Defines which strategy will be used to lock an account.
|
||||
@@ -188,9 +184,8 @@ Devise.setup do |config|
|
||||
# devise role declared in your routes (usually :user).
|
||||
# config.default_scope = :user
|
||||
|
||||
# Configure sign_out behavior.
|
||||
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
|
||||
# The default is true, which means any logout action will sign out all active scopes.
|
||||
# Set this configuration to false if you want /users/sign_out to sign out
|
||||
# only the current scope. By default, Devise signs out all scopes.
|
||||
# config.sign_out_all_scopes = true
|
||||
|
||||
# ==> Navigation configuration
|
||||
@@ -220,4 +215,18 @@ Devise.setup do |config|
|
||||
# manager.intercept_401 = false
|
||||
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
|
||||
# end
|
||||
end
|
||||
|
||||
# ==> Mountable engine configurations
|
||||
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
|
||||
# is mountable, there are some extra configurations to be taken into account.
|
||||
# The following options are available, assuming the engine is mounted as:
|
||||
#
|
||||
# mount MyEngine, at: "/my_engine"
|
||||
#
|
||||
# The router that invoked `devise_for`, in the example above, would be:
|
||||
# config.router_name = :my_engine
|
||||
#
|
||||
# When using omniauth, Devise cannot automatically set Omniauth path,
|
||||
# so you need to do it manually. For the users scope, it would be:
|
||||
# config.omniauth_path_prefix = "/my_engine/users/auth"
|
||||
end
|
||||
@@ -3,13 +3,13 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Resend confirmation instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<%= f.input :reset_password_token, :as => :hidden %>
|
||||
<%= f.full_error :reset_password_token %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :password, :label => "New password", :required => true %>
|
||||
<%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Change my password" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Send me reset password instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-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, :autocomplete => "off", :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">
|
||||
<div class="form-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>
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %>.</p>
|
||||
|
||||
<%= link_to "Back", :back %>
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
<%= f.input :password, :required => true %>
|
||||
<%= f.input :password_confirmation, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Sign up" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<h2>Sign in</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<div class="inputs">
|
||||
<div class="form-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">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Sign in" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Resend unlock instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
62
test/controllers/custom_strategy_test.rb
Normal file
62
test/controllers/custom_strategy_test.rb
Normal file
@@ -0,0 +1,62 @@
|
||||
require 'test_helper'
|
||||
require 'ostruct'
|
||||
require 'warden/strategies/base'
|
||||
require 'devise/test_helpers'
|
||||
|
||||
class CustomStrategyController < ActionController::Base
|
||||
def new
|
||||
warden.authenticate!(:custom_strategy)
|
||||
end
|
||||
end
|
||||
|
||||
# These tests are to prove that a warden strategy can successfully
|
||||
# return a custom response, including a specific status code and
|
||||
# custom http response headers. This does work in production,
|
||||
# however, at the time of writing this, the Devise test helpers do
|
||||
# not recognise the custom response and proceed to calling the
|
||||
# Failure App. This makes it impossible to write tests for a
|
||||
# strategy that return a custom response with Devise.
|
||||
class CustomStrategy < Warden::Strategies::Base
|
||||
def authenticate!
|
||||
custom_headers = { "X-FOO" => "BAR" }
|
||||
response = Rack::Response.new("BAD REQUEST", 400, custom_headers)
|
||||
custom! response.finish
|
||||
end
|
||||
end
|
||||
|
||||
class CustomStrategyTest < ActionController::TestCase
|
||||
tests CustomStrategyController
|
||||
|
||||
include Devise::TestHelpers
|
||||
|
||||
setup do
|
||||
Warden::Strategies.add(:custom_strategy, CustomStrategy)
|
||||
end
|
||||
|
||||
teardown do
|
||||
Warden::Strategies._strategies.delete(:custom_strategy)
|
||||
end
|
||||
|
||||
test "custom strategy can return its own status code" do
|
||||
ret = get :new
|
||||
|
||||
# check the returned rack array
|
||||
assert ret.is_a?(Array)
|
||||
assert_equal 400, ret.first
|
||||
|
||||
# check the saved response as well. This is purely so that the response is available to the testing framework
|
||||
# for verification. In production, the above array would be delivered directly to Rack.
|
||||
assert_response 400
|
||||
end
|
||||
|
||||
test "custom strategy can return custom headers" do
|
||||
ret = get :new
|
||||
|
||||
# check the returned rack array
|
||||
assert ret.is_a?(Array)
|
||||
assert_equal ret.third['X-FOO'], 'BAR'
|
||||
|
||||
# check the saved response headers as well.
|
||||
assert_equal response.headers['X-FOO'], 'BAR'
|
||||
end
|
||||
end
|
||||
@@ -139,30 +139,27 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
assert_equal nil, @controller.instance_variable_get(:@current_admin)
|
||||
end
|
||||
|
||||
test 'sign out clears up any signed in user by scope' do
|
||||
test 'sign out logs out and clears up any signed in user by scope' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).with(:user).returns(user)
|
||||
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(user)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
|
||||
@controller.instance_variable_set(:@current_user, user)
|
||||
@controller.sign_out(:user)
|
||||
assert_equal nil, @controller.instance_variable_get(:@current_user)
|
||||
end
|
||||
|
||||
test 'sign out proxy to logout on warden' do
|
||||
@mock_warden.expects(:user).with(:user).returns(true)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@controller.sign_out(:user)
|
||||
end
|
||||
|
||||
test 'sign out accepts a resource as argument' do
|
||||
@mock_warden.expects(:user).with(:user).returns(true)
|
||||
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(true)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
|
||||
@controller.sign_out(User.new)
|
||||
end
|
||||
|
||||
test 'sign out without args proxy to sign out all scopes' do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
|
||||
@controller.sign_out
|
||||
end
|
||||
|
||||
@@ -230,8 +227,9 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
|
||||
test 'sign out and redirect uses the configured after sign out path when signing out only the current scope' do
|
||||
swap Devise, :sign_out_all_scopes => false do
|
||||
@mock_warden.expects(:user).with(:admin).returns(true)
|
||||
@mock_warden.expects(:user).with(:scope => :admin, :run_callbacks => false).returns(true)
|
||||
@mock_warden.expects(:logout).with(:admin).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :admin).returns(true)
|
||||
@controller.expects(:redirect_to).with(admin_root_path)
|
||||
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
|
||||
@controller.sign_out_and_redirect(:admin)
|
||||
@@ -242,6 +240,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
swap Devise, :sign_out_all_scopes => true do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
|
||||
@controller.expects(:redirect_to).with(admin_root_path)
|
||||
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
|
||||
@controller.sign_out_and_redirect(:admin)
|
||||
|
||||
@@ -33,6 +33,13 @@ class HelpersTest < ActionController::TestCase
|
||||
assert_equal user, @controller.instance_variable_get(:@user)
|
||||
end
|
||||
|
||||
test 'get resource params from request params using resource name as key' do
|
||||
user_params = {'name' => 'Shirley Templar'}
|
||||
@controller.stubs(:params).returns(HashWithIndifferentAccess.new({'user' => user_params}))
|
||||
|
||||
assert_equal user_params, @controller.resource_params
|
||||
end
|
||||
|
||||
test 'resources methods are not controller actions' do
|
||||
assert @controller.class.action_methods.empty?
|
||||
end
|
||||
@@ -71,19 +78,21 @@ class HelpersTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
test 'does not issue blank flash messages' do
|
||||
MyController.send(:public, :set_flash_message)
|
||||
I18n.stubs(:t).returns(' ')
|
||||
@controller.set_flash_message :notice, :send_instructions
|
||||
@controller.send :set_flash_message, :notice, :send_instructions
|
||||
assert flash[:notice].nil?
|
||||
MyController.send(:protected, :set_flash_message)
|
||||
end
|
||||
|
||||
test 'issues non-blank flash messages normally' do
|
||||
MyController.send(:public, :set_flash_message)
|
||||
I18n.stubs(:t).returns('non-blank')
|
||||
@controller.set_flash_message :notice, :send_instructions
|
||||
assert flash[:notice] == 'non-blank'
|
||||
MyController.send(:protected, :set_flash_message)
|
||||
@controller.send :set_flash_message, :notice, :send_instructions
|
||||
assert_equal 'non-blank', flash[:notice]
|
||||
end
|
||||
|
||||
test 'uses custom i18n options' do
|
||||
@controller.stubs(:devise_i18n_options).returns(:default => "devise custom options")
|
||||
@controller.send :set_flash_message, :notice, :invalid_i18n_messagesend_instructions
|
||||
assert_equal 'devise custom options', flash[:notice]
|
||||
end
|
||||
|
||||
test 'navigational_formats not returning a wild card' do
|
||||
|
||||
@@ -4,6 +4,15 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
tests Devise::SessionsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
test "#create works even with scoped views" do
|
||||
swap Devise, :scoped_views => true do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
post :create
|
||||
assert_equal 200, @response.status
|
||||
assert_template "users/sessions/new"
|
||||
end
|
||||
end
|
||||
|
||||
test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
post :create, :user => {
|
||||
@@ -13,4 +22,22 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
assert_equal 200, @response.status
|
||||
assert_template "devise/sessions/new"
|
||||
end
|
||||
end
|
||||
|
||||
if defined?(ActiveRecord) && ActiveRecord::Base.respond_to?(:mass_assignment_sanitizer)
|
||||
test "#new doesn't raise mass-assignment exception even if sign-in key is attr_protected" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :strict
|
||||
User.class_eval { attr_protected :email }
|
||||
|
||||
begin
|
||||
assert_nothing_raised ActiveModel::MassAssignmentSecurity::Error do
|
||||
get :new, :user => { :email => "allez viens!" }
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :logger
|
||||
User.class_eval { attr_accessible :email }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class Encryptors < ActiveSupport::TestCase
|
||||
test 'should match a password created by authlogic' do
|
||||
authlogic = "b623c3bc9c775b0eb8edb218a382453396fec4146422853e66ecc4b6bc32d7162ee42074dcb5f180a770dc38b5df15812f09bbf497a4a1b95fe5e7d2b8eb7eb4"
|
||||
encryptor = Devise::Encryptors::AuthlogicSha512.digest('123mudar', 20, 'usZK_z_EAaF61Gwkw-ed', '')
|
||||
assert_equal authlogic, encryptor
|
||||
end
|
||||
|
||||
test 'should match a password created by restful_authentication' do
|
||||
restful_authentication = "93110f71309ce91366375ea44e2a6f5cc73fa8d4"
|
||||
encryptor = Devise::Encryptors::RestfulAuthenticationSha1.digest('123mudar', 10, '48901d2b247a54088acb7f8ea3e695e50fe6791b', 'fee9a51ec0a28d11be380ca6dee6b4b760c1a3bf')
|
||||
assert_equal restful_authentication, encryptor
|
||||
end
|
||||
|
||||
test 'should match a password created by clearance' do
|
||||
clearance = "0f40bbae18ddefd7066276c3ef209d40729b0378"
|
||||
encryptor = Devise::Encryptors::ClearanceSha1.digest('123mudar', nil, '65c58472c207c829f28c68619d3e3aefed18ab3f', nil)
|
||||
assert_equal clearance, encryptor
|
||||
end
|
||||
|
||||
Devise::ENCRYPTORS_LENGTH.each do |key, value|
|
||||
test "should have length #{value} for #{key.inspect}" do
|
||||
swap Devise, :encryptor => key do
|
||||
encryptor = Devise::Encryptors.const_get(key.to_s.classify)
|
||||
assert_equal value, encryptor.digest('a', 4, encryptor.salt(4), nil).size
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,20 +29,20 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
context 'When redirecting' do
|
||||
test 'return to the default redirect location' do
|
||||
test 'returns 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
|
||||
test 'returns 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
|
||||
test 'returns to the root path if no session path is available' do
|
||||
swap Devise, :router_name => :fake_app do
|
||||
call_failure :app => RootFailureApp
|
||||
assert_equal 302, @response.first
|
||||
@@ -51,6 +51,16 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
if Rails.application.config.respond_to?(:relative_url_root)
|
||||
test 'returns to the default redirect location considering the relative url root' do
|
||||
swap Rails.application.config, :relative_url_root => "/sample" do
|
||||
call_failure
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/sample/users/sign_in', @response.second['Location']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'uses the proxy failure message as symbol' do
|
||||
call_failure('warden' => OpenStruct.new(:message => :invalid))
|
||||
assert_equal 'Invalid email or password.', @request.flash[:alert]
|
||||
|
||||
@@ -34,4 +34,36 @@ if DEVISE_ORM == :active_record
|
||||
assert_no_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
end
|
||||
|
||||
module RailsEngine
|
||||
class Engine < Rails::Engine
|
||||
isolate_namespace RailsEngine
|
||||
end
|
||||
end
|
||||
|
||||
def simulate_inside_engine(engine, namespace)
|
||||
if Rails::Generators.respond_to?(:namespace=)
|
||||
swap Rails::Generators, :namespace => namespace do
|
||||
yield
|
||||
end
|
||||
else
|
||||
swap Rails, :application => engine.instance do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ActiveRecordEngineGeneratorTest < Rails::Generators::TestCase
|
||||
tests ActiveRecord::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
|
||||
run_generator ["monster"]
|
||||
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/,/attr_accessible (:[a-z_]+(, )?)+/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -46,7 +46,7 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
assert_file "app/views/#{scope}/registrations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/sessions/new.html.erb"
|
||||
assert_file "app/views/#{scope}/shared/_links.erb"
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb"
|
||||
assert_file "app/views/#{scope}/_links.erb"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,80 +75,6 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
|
||||
assert_not warden.authenticated?(:admin)
|
||||
end
|
||||
|
||||
test 'not signed in as admin should not be able to access private route restricted to admins' do
|
||||
get private_path
|
||||
assert_redirected_to new_admin_session_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
end
|
||||
|
||||
test 'signed in as user should not be able to access private route restricted to admins' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
get private_path
|
||||
assert_redirected_to new_admin_session_path
|
||||
end
|
||||
|
||||
test 'signed in as admin should be able to access private route restricted to admins' do
|
||||
sign_in_as_admin
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get private_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/private'
|
||||
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 unauthenticated 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 users should see unautheticated 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)
|
||||
@@ -208,6 +134,126 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationRoutesRestrictions < ActionController::IntegrationTest
|
||||
test 'not signed in should not be able to access private route (authenticate denied)' do
|
||||
get private_path
|
||||
assert_redirected_to new_admin_session_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
end
|
||||
|
||||
test 'signed in as user should not be able to access private route restricted to admins (authenticate denied)' do
|
||||
sign_in_as_user
|
||||
assert warden.authenticated?(:user)
|
||||
assert_not warden.authenticated?(:admin)
|
||||
get private_path
|
||||
assert_redirected_to new_admin_session_path
|
||||
end
|
||||
|
||||
test 'signed in as admin should be able to access private route restricted to admins (authenticate accepted)' do
|
||||
sign_in_as_admin
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get private_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/private'
|
||||
assert_contain 'Private!'
|
||||
end
|
||||
|
||||
test 'signed in as inactive admin should not be able to access private/active route restricted to active admins (authenticate denied)' do
|
||||
sign_in_as_admin(:active => false)
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
assert_raises ActionController::RoutingError do
|
||||
get "/private/active"
|
||||
end
|
||||
end
|
||||
|
||||
test 'signed in as active admin should be able to access private/active route restricted to active admins (authenticate accepted)' do
|
||||
sign_in_as_admin(:active => true)
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get private_active_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/private'
|
||||
assert_contain 'Private!'
|
||||
end
|
||||
|
||||
test 'signed in as admin should get admin dashboard (authenticated accepted)' 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 (authenticated accepted)' 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 (authenticated denied)' do
|
||||
assert_raises ActionController::RoutingError do
|
||||
get dashboard_path
|
||||
end
|
||||
end
|
||||
|
||||
test 'signed in as inactive admin should not be able to access dashboard/active route restricted to active admins (authenticated denied)' do
|
||||
sign_in_as_admin(:active => false)
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
assert_raises ActionController::RoutingError do
|
||||
get "/dashboard/active"
|
||||
end
|
||||
end
|
||||
|
||||
test 'signed in as active admin should be able to access dashboard/active route restricted to active admins (authenticated accepted)' do
|
||||
sign_in_as_admin(:active => true)
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
get dashboard_active_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/admin_dashboard'
|
||||
assert_contain 'Admin dashboard'
|
||||
end
|
||||
|
||||
test 'signed in user should not see unauthenticated page (unauthenticated denied)' 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 users should see unautheticated page (unauthenticated accepted)' do
|
||||
get join_path
|
||||
|
||||
assert_response :success
|
||||
assert_template 'home/join'
|
||||
assert_contain 'Join'
|
||||
end
|
||||
end
|
||||
|
||||
class AuthenticationRedirectTest < ActionController::IntegrationTest
|
||||
test 'redirect from warden shows sign in or sign up message' do
|
||||
get admins_path
|
||||
@@ -461,14 +507,14 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
test 'sign out with xml format returns ok response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'xml')
|
||||
assert_response :ok
|
||||
assert_response :no_content
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign out with json format returns empty json response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'json')
|
||||
assert_response :ok
|
||||
assert_response :no_content
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,7 +180,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
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_contain "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
@@ -196,7 +196,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
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_contain "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,7 +118,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
OmniAuth.config.mock_auth[:facebook] = :access_denied
|
||||
visit "/users/auth/facebook/callback?error=access_denied"
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authorize you from Facebook because "Access denied".'
|
||||
assert_contain 'Could not authenticate you from Facebook because "Access denied".'
|
||||
end
|
||||
|
||||
test "handles other exceptions from omniauth" do
|
||||
@@ -128,6 +128,6 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
click_link "Sign in with Facebook"
|
||||
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authorize you from Facebook because "Invalid credentials".'
|
||||
assert_contain 'Could not authenticate you from Facebook because "Invalid credentials".'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,6 +126,12 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'not authenticated user without a reset password token should not be able to visit the page' do
|
||||
get edit_user_password_path
|
||||
assert_response :redirect
|
||||
assert_redirected_to "/users/sign_in"
|
||||
end
|
||||
|
||||
test 'not authenticated user with invalid reset password token should not be able to change his password' do
|
||||
user = create_user
|
||||
reset_password :reset_password_token => 'invalid_reset_password'
|
||||
@@ -268,7 +274,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
|
||||
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_contain "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
@@ -280,8 +286,21 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
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_contain "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
|
||||
test "after recovering a password, should set failed attempts to 0" do
|
||||
user = create_user
|
||||
user.update_attribute(:failed_attempts, 10)
|
||||
|
||||
assert_equal 10, user.failed_attempts
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert warden.authenticated?(:user)
|
||||
user.reload
|
||||
assert_equal 0, user.failed_attempts
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,7 +51,7 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
# We test this by asserting the cookie is not sent after the redirect
|
||||
# since we changed the domain. This is the only difference with the
|
||||
# previous test.
|
||||
swap Devise, :cookie_options => { :domain => "omg.somewhere.com" } do
|
||||
swap Devise, :rememberable_options => { :domain => "omg.somewhere.com" } do
|
||||
user = sign_in_as_user :remember_me => true
|
||||
assert_nil request.cookies["remember_user_token"]
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
||||
assert_equal old_last_request, last_request_at
|
||||
end
|
||||
|
||||
test 'not time out user session before default limit time' do
|
||||
test 'does not time out user session before default limit time' do
|
||||
sign_in_as_user
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
@@ -50,13 +50,41 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
||||
get expire_user_path(user)
|
||||
|
||||
get destroy_user_session_path
|
||||
|
||||
assert_response :redirect
|
||||
assert_redirected_to root_path
|
||||
|
||||
follow_redirect!
|
||||
assert_contain 'Signed out successfully'
|
||||
end
|
||||
|
||||
test 'time out is not triggered on sign in' do
|
||||
user = sign_in_as_user
|
||||
get expire_user_path(user)
|
||||
|
||||
post "/users/sign_in", :email => user.email, :password => "123456"
|
||||
|
||||
assert_response :redirect
|
||||
follow_redirect!
|
||||
assert_contain 'You are signed in'
|
||||
end
|
||||
|
||||
test 'admin does not explode on time out' do
|
||||
admin = sign_in_as_admin
|
||||
get expire_admin_path(admin)
|
||||
|
||||
Admin.send :define_method, :reset_authentication_token! do
|
||||
nil
|
||||
end
|
||||
|
||||
begin
|
||||
get admins_path
|
||||
assert_redirected_to admins_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
ensure
|
||||
Admin.send(:remove_method, :reset_authentication_token!)
|
||||
end
|
||||
end
|
||||
|
||||
test 'user configured timeout limit' do
|
||||
swap Devise, :timeout_in => 8.minutes do
|
||||
user = sign_in_as_user
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user