Compare commits

...

96 Commits

Author SHA1 Message Date
José Valim
2e27d1f763 Update CHANGELOG, release 2.0.2 2012-02-15 17:26:23 +01:00
José Valim
27a83f3dd3 Ensure Devise.available_router_name is never nil, closes #1648 2012-02-15 17:13:57 +01:00
José Valim
79aadb4bc9 Set autocomplete to off by default on password field. 2012-02-15 17:07:58 +01:00
José Valim
43d0715238 Better error message in case a trackable module can't be saved. 2012-02-15 17:07:46 +01:00
José Valim
fb8e093389 Accept devise_i18n_options to handle custom i18n values, closes #1633 2012-02-15 16:58:23 +01:00
José Valim
4b47c3ab73 Clean up devise_controller? related code. 2012-02-15 16:58:23 +01:00
José Valim
a0eff85d73 Use ResourceHelpers so we get a warning in case someone passes a plural name, closes #1651. 2012-02-15 16:58:23 +01:00
Rodrigo Flores
aa36719bd9 Merge branch 'ysiadf-integrating' 2012-02-13 18:24:38 -02:00
Ysiad Ferreiras
33aa71c38f Update lib/generators/templates/README 2012-02-13 18:24:11 -02:00
Ysiad Ferreiras
1f20d7da25 Update lib/generators/templates/README 2012-02-13 18:23:45 -02:00
Ysiad Ferreiras
dfcf825721 Update README.doc to specify adding devise to the Gemfile. 2012-02-13 18:23:07 -02:00
José Valim
eaae041b4c Merge pull request #1635 from sj26/test-helpers-process-should-return-response
Fix test behaviour for rspec subject requests
2012-02-11 22:32:35 -08:00
Samuel Cochran
dbd79746b1 Fix test behaviour for rspec subject requests 2012-02-10 21:42:20 +08:00
José Valim
f1a27b8f33 Release 2.0.1. 2012-02-09 11:11:12 +01:00
José Valim
86c8e5455a Fix gemspec to not include tmp or log files, closes #1632. 2012-02-09 11:07:03 +01:00
José Valim
dc37b82298 Show a warning message in case routes are not mounted in the main app. 2012-02-07 10:56:30 +01:00
José Valim
7d09b84ded Split send_on_create_confirmation_instructions, closes #1621 2012-02-03 17:35:55 +01:00
José Valim
53894e1e2b Better exception message. 2012-02-03 17:29:22 +01:00
José Valim
7e3ccbe835 Better implementation for hide! 2012-02-03 09:12:15 +01:00
José Valim
8b8b6a866d Hide internal generators, closes #1586 2012-02-03 09:04:05 +01:00
Rodrigo Flores
222e606f89 Added a documentup link on README 2012-02-03 00:39:28 -02:00
José Valim
83c47552e8 Extract auth_options into its own method. 2012-02-01 09:37:33 +01:00
José Valim
03851cab90 Update lib/devise/rails/routes.rb 2012-02-01 07:26:39 +01:00
Carlos Antonio da Silva
bb6d89bbc3 Change README do markdown 2012-01-30 18:58:04 -02:00
José Valim
b061f985cf Update README to remove reference to old migration helpers. 2012-01-27 19:43:47 +01:00
José Valim
ecd7c17ffd Improve the message for case_insensitive_keys. 2012-01-27 17:53:44 +01:00
José Valim
a71a352822 Release 2.0.0 2012-01-26 19:40:04 +01:00
José Valim
c08c921b3f Update README.rdoc 2012-01-26 18:19:02 +01:00
Carlos Antonio da Silva
95399f1286 2012 [ci skip]
Hope we can do the same bump next year :)
2012-01-24 19:35:14 -02:00
José Valim
b5fd15c2e1 Let's show the default values for convenience. 2012-01-24 17:34:18 +01:00
José Valim
85e9dab370 Release 2.0.0.rc2. 2012-01-24 14:29:26 +01:00
José Valim
8c9cf7d671 Add deprecations, update changelog. 2012-01-24 14:23:34 +01:00
José Valim
82da877863 Merge pull request #1565 from joliss/unconfirmed-message
More helpful sign-up message for Confirmable
2012-01-24 05:06:51 -08:00
José Valim
275c480f89 Redirect to the previous URL on timeout, closes #1596 2012-01-24 14:00:36 +01:00
José Valim
477d9fbcba Do not fallback to string on failure app, easier for debugging, closes #1587 2012-01-24 13:46:25 +01:00
José Valim
b88524027c Get rid of deprecation warning. 2012-01-24 13:41:19 +01:00
José Valim
55be93d5c4 Deprecated support for nested devise_for blocks 2012-01-24 13:40:04 +01:00
Jo Liss
c78c196423 More helpful sign-up message for Confirmable
This is also better for translations, because we can translate paragraph-wise.

signed_up_but_inactive and signed_up_but_locked are likely not needed,
but I wasn't sure how to best remove them.
2012-01-23 13:52:32 +01:00
José Valim
d8656427fd Merge pull request #1591 from kaleemullah/master
fix unlock message
2012-01-23 03:29:29 -08:00
Kaleem Ullah
41b1e87105 fix unlock message 2012-01-23 15:20:05 +04:00
José Valim
37678ac5ec Merge pull request #1588 from nashby/fix-travis-build
fix travis build
2012-01-23 02:46:24 -08:00
Vasiliy Ermolovich
7832d90077 fix travis build 2012-01-22 22:12:28 +03:00
José Valim
3bd78cabd8 Update to 3.2.0 2012-01-20 19:03:22 +01:00
José Valim
fff75b1904 Merge pull request #1579 from masterkain/patch-1
Fix typos in devise.rb
2012-01-17 14:18:10 -08:00
Claudio Poli
97c0339f66 Fix typos in devise.rb 2012-01-17 23:14:26 +01:00
Rafael Mendonça França
5b3f14df3b Fix README 2012-01-17 15:59:50 -02:00
José Valim
07cdba349d Merge pull request #1563 from asynchrony/handle_regexp_param_filtering
Allow regex to avoid string conversion for parameter filtering
2012-01-16 03:20:17 -08:00
José Valim
197e837e5b Merge pull request #1564 from pcantrell/patch-1
Grammar fix.
2012-01-11 23:09:17 -08:00
pcantrell
13bd4ce46a Grammar fix. 2012-01-11 23:18:04 -06:00
José Valim
a43d1af23e Merge pull request #1557 from plataformatec/rails-3-2-fixes
Rails 3.2 fixes
2012-01-10 12:26:58 -08:00
Rafael Mendonça França
cbf483143f Remove rubinius from travis-ci matrix 2012-01-10 11:59:59 -03:00
Rafael Mendonça França
cf5fbb9d65 Fix order specific test 2012-01-10 11:59:20 -03:00
Rafael Mendonça França
d699b80254 Do not use a local network ip as HTTP_X_FORWARDED_FOR header
If HTTP_X_FORWARDED_FOR is a local network IP the HTTP_CLIENT_IP
need to be set
2012-01-10 11:43:15 -03:00
Rafael Mendonça França
ead414d0a7 Use global Gemfile in travis-ci 2012-01-10 10:52:14 -03:00
Rafael Mendonça França
cfdabf874a Change gemspec to avoid subshells and remove unneeded files
More informations at http://tenderlovemaking.com/2011/12/05/profiling-rails-startup-with-dtrace/
2012-01-09 23:47:35 -03:00
Rafael Mendonça França
e954254abb Fix gemfiles 2012-01-09 23:18:03 -03:00
Rafael Mendonça França
93d4bb8361 Add travis-ci specific gemfiles 2012-01-09 22:59:13 -03:00
Rafael Mendonça França
edb0aac091 Whitespaces ✂️ 2012-01-09 18:11:10 -03:00
Rafael Mendonça França
9549a32500 Do not use deprecated ActiveSupport::Base64. Closes #1554 2012-01-09 18:10:49 -03:00
José Valim
a949f9eca2 FailureApp shuold always consider Devise.router_name, closes #1544 2012-01-03 20:32:51 +01:00
Carlos Antonio da Silva
f4bbad6323 Merge pull request #1543 from joliss/doc
Improve routing API docs
2012-01-03 06:39:41 -08:00
Jo Liss
8a4d4864ea Improve routing API docs 2012-01-03 15:33:19 +01:00
José Valim
a8de38d0b0 Fix http://@ from CHANGELOG 2012-01-02 23:18:57 +01:00
José Valim
18dc82c6b6 add a test that :module => :devise overrides previous configs. 2012-01-02 22:47:28 +01:00
José Valim
897c1c684e Allow router_name to be customizable via Devise.router_name, useful for engines 2012-01-02 22:43:07 +01:00
José Valim
1ebcb09fc1 Do not rely on root_path. Redirect to / if not available. 2012-01-02 22:43:07 +01:00
José Valim
0f11226ced Merge pull request #1540 from michaelklishin/master
Bring .travis.yml up to date
2012-01-02 13:21:51 -08:00
José Valim
dada404a6b Support 3.2 as well. 2012-01-02 22:19:05 +01:00
Michael Klishin
e4a37d6a5e Bring .travis.yml up to date
* rbx and rbx-2.0 are now both aliases for rbx-18mode (master in 1.8 mode)
 * 1.9.3 final is available
2012-01-03 01:14:59 +04:00
José Valim
66b93e8fd2 Clean up as we don't need to call render_with_scope anymore. 2012-01-02 22:12:09 +01:00
José Valim
d9df632671 Get rid of InternalHelpers, refactor scoped views for more performant behavior. 2012-01-02 22:01:28 +01:00
José Valim
aa2d15aa33 Move devise/shared/_links.erb to devise/_links.erb 2012-01-02 21:26:26 +01:00
José Valim
0b55ebb150 Remove 3.0 related code. 2012-01-02 21:04:54 +01:00
José Valim
7c11564613 Remove Rails 3.0 only code. 2012-01-02 20:43:39 +01:00
José Valim
c3f864f2b6 Allow parent controller to be customizable. 2012-01-02 20:39:22 +01:00
José Valim
a29a30effc Move InternalHelpers to parent controller. 2012-01-02 20:30:56 +01:00
José Valim
0af2722926 Let's depend on 3.1 forward. 2012-01-02 20:24:42 +01:00
José Valim
78efec09d5 Move notes to the top. 2012-01-02 20:24:42 +01:00
José Valim
1fdeadd113 Merge pull request #1188 from sj26/controller-inheritence
Make all controllers inherit from a single DeviseController
2012-01-02 11:24:33 -08:00
José Valim
a1464dbad7 Replace github.com/ by @ 2012-01-02 20:16:40 +01:00
José Valim
dd2a66d00c Update CHANGELOG. 2012-01-02 20:16:11 +01:00
José Valim
1152fda687 Only proxy to application controller if it exists. 2012-01-02 20:00:38 +01:00
José Valim
fd0e929087 Generate session routes for token authentication, but mark it as no_input. 2012-01-02 19:38:02 +01:00
José Valim
8b3e0e52f1 Generate routes again for token, closes #1526. 2012-01-02 19:27:05 +01:00
José Valim
8ff080fb99 Improve docs for params/http authenticatable. 2012-01-02 19:24:48 +01:00
José Valim
6bca228888 Merge pull request #1527 from joliss/generator
Use consistent number of hash signs
2012-01-02 10:21:41 -08:00
José Valim
fd1e588645 Merge pull request #1534 from jigyasa/master
Fix for a bug: Incorrect message for locked account
2012-01-02 10:04:17 -08:00
José Valim
024d9e6df7 Merge pull request #1537 from nashby/fix-issue-1530
regenerate confirmation token on reconfirmation
2011-12-31 04:03:14 -08:00
Vasiliy Ermolovich
aca8d3f34c regenerate confirmation token on reconfirmation, closes #1530 2011-12-31 14:22:58 +03:00
Jigyasa Makkar
e2030a740d Fixed a bug in lockable wherein when a user tries to login with correct password after being locked,
failed attempts count gets reset. When the user tries to login with an incorrect password next,
the message shown is for invalid password instead of locked account since this check
depended mainly on failed attempts count.
2011-12-29 23:57:39 +05:30
Jo Liss
27b745d04f Use consistent number of hash signs 2011-12-28 17:26:57 +01:00
José Valim
f712d07b23 Merge pull request #1516 from jm81/master
Move "include Devise::Models::Authenticatable" inside devise_modules_hook! call
2011-12-20 14:00:36 -08:00
Jared Morgan
f8ea5e0942 move include Devise::Models::Authenticatable inside devise_modules_hook! call
This allows alternate ORMs to run compatibility setup code before
Authenticatable is included.

The particular issue for dm-devise is that DataMapper does not have a
before_validation method, which is called when Authenticatable is included
(as of plataformatec/devise@bd27bf76). dm-devise adds before_validation in
it's devise_modules_hook!
2011-12-20 15:52:26 -06:00
José Valim
89db0dd44d Do not run validatins unless on reconfirmable branch, closes #1515. 2011-12-20 20:54:49 +01:00
T1D
c9becd3ea1 Allow regular expressions to avoid string conversion for parameter
filtering.
2011-12-14 10:41:24 -06:00
Samuel Cochran
2b64c6d951 Make all controllers inherit from a single DeviseController 2011-06-25 03:34:13 +08:00
79 changed files with 1007 additions and 880 deletions

4
.gitignore vendored
View File

@@ -1,5 +1,5 @@
**/*/log/*
**/*/tmp/*
test/rails_app/log/*
test/rails_app/tmp/*
*~
coverage/*
*.sqlite3

View File

@@ -1,10 +1,13 @@
script: "bundle exec rake test"
before_install: gem update --system
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- ree
- rbx
- rbx-2.0
gemfile:
- gemfiles/Gemfile.rails-3.1.x
- Gemfile
notifications:
recipients:
- jose.valim@plataformatec.com.br

View File

@@ -1,33 +1,63 @@
== 2.0.0.rc
== 2.0.2
Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
* enhancements
* Add support for e-mail reconfirmation on change (by github.com/Mandaryn and github.com/heimidal)
* Redirect users to sign in page after unlock (by github.com/nashby)
* 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
* bug fix
* Removed tmp and log files from gem
== 2.0.0
* enhancements
* Add support for e-mail reconfirmation on change (by @Mandaryn and @heimidal)
* Redirect users to sign in page after unlock (by @nashby)
* Redirect to the previous URL on timeout
* Inherit from the same Devise parent controller (by @sj26)
* Allow parent_controller to be customizable via Devise.parent_controller, useful for engines
* Allow router_name to be customizable via Devise.router_name, useful for engines
* Allow alternate ORMs to run compatibility setup code before Authenticatable is included (by @jm81)
* deprecation
* Devise.apply_schema is deprecated
* Devise migration helpers are deprecated
* Devise now only supports Rails 3.1 forward
* Devise.confirm_within was deprecated in favor Devise.allow_unconfirmed_access_for
* Devise.stateless_token= is deprecated in favor of appending :token_auth to Devise.skip_session_storage
* Usage of Devise.apply_schema is deprecated
* Usage of Devise migration helpers are deprecated
* Usage of Devise.remember_across_browsers was deprecated
* Usage of Devise.confirm_within was deprecated in favor Devise.allow_unconfirmed_access_for
* Usage of rememberable with remember_token was removed
* Usage of recoverable without reset_password_sent_at was removed
* Usage of Devise.case_insensitive_keys equals to false was removed
* Usage of Devise.stateless_token= is deprecated in favor of appending :token_auth to Devise.skip_session_storage
* 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_*
== 1.5.3
* bug fix
* Ensure delegator converts scope to symbol (by github.com/dmitriy-kiriyenko)
* Ensure delegator converts scope to symbol (by @dmitriy-kiriyenko)
* Ensure passing :format => false to devise_for is not permanent
* Ensure path checker does not check invalid routes
== 1.5.2
* enhancements
* Add support for Rails 3.1 new mass assignment conventions (by github.com/kirs)
* Add timeout_in method to Timeoutable, it can be overridden in a model (by github.com/lest)
* Add support for Rails 3.1 new mass assignment conventions (by @kirs)
* Add timeout_in method to Timeoutable, it can be overridden in a model (by @lest)
* bug fix
* OmniAuth error message now shows the proper option (:strategy_class instead of :klass)
@@ -42,10 +72,10 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Timeoutable also skips tracking if skip_trackable is given
* devise_for now accepts :failure_app as an option
* Models can select the proper mailer via devise_mailer method (by github.com/locomotivecms)
* Migration generator now uses the change method (by github.com/nashby)
* Support to markerb templates on the mailer generator (by github.com/sbounmy)
* Support for Omniauth 1.0 (older versions are no longer supported) (by github.com/TamiasSibiricus)
* Models can select the proper mailer via devise_mailer method (by @locomotivecms)
* Migration generator now uses the change method (by @nashby)
* Support to markerb templates on the mailer generator (by @sbounmy)
* Support for Omniauth 1.0 (older versions are no longer supported) (by @TamiasSibiricus)
* bug fix
* Allow idempotent API requests
@@ -88,7 +118,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* bug fix
* Failure app tries the root path if a session one does not exist
* No need to finalize Devise helpers all the time (by github.com/bradleypriest)
* No need to finalize Devise helpers all the time (by @bradleypriest)
* Reset password shows proper message if user is not active
* `clean_up_passwords` sets the accessors to nil to skip validations
@@ -123,7 +153,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Add :defaults and :format support on router
* Add simple form generators
* Better localization for devise_error_messages! (by github.com/zedtux)
* Better localization for devise_error_messages! (by @zedtux)
* bug fix
* Ensure to_xml is properly white listened
@@ -132,20 +162,20 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 1.4.0
* enhancements
* Added authenticated and unauthenticated to the router to route the used based on his status (by github.com/sj26)
* Improve e-mail regexp (by github.com/rodrigoflores)
* Add strip_whitespace_keys and default to e-mail (by github.com/swrobel)
* Do not run format and uniqueness validations on e-mail if it hasn't changed (by github.com/Thibaut)
* Added update_without_password to update models but not allowing the password to change (by github.com/fschwahn)
* Added config.paranoid, check the generator for more information (by github.com/rodrigoflores)
* Added authenticated and unauthenticated to the router to route the used based on his status (by @sj26)
* Improve e-mail regexp (by @rodrigoflores)
* Add strip_whitespace_keys and default to e-mail (by @swrobel)
* Do not run format and uniqueness validations on e-mail if it hasn't changed (by @Thibaut)
* Added update_without_password to update models but not allowing the password to change (by @fschwahn)
* Added config.paranoid, check the generator for more information (by @rodrigoflores)
* bug fix
* password_required? should not affect length validation
* User cannot access sign up and similar pages if he is already signed in through a cookie or token
* Do not convert booleans to strings on finders (by github.com/xavier)
* Run validations even if current_password fails (by github.com/crx)
* Devise now honors routes constraints (by github.com/macmartine)
* Do not return the user resource when requesting instructions (by github.com/rodrigoflores)
* Do not convert booleans to strings on finders (by @xavier)
* Run validations even if current_password fails (by @crx)
* Devise now honors routes constraints (by @macmartine)
* Do not return the user resource when requesting instructions (by @rodrigoflores)
== 1.3.4
@@ -160,31 +190,31 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 1.3.2
* bug fix
* Fix another regression related to reset_password_sent_at (by github.com/alexdreher)
* Fix another regression related to reset_password_sent_at (by @alexdreher)
== 1.3.1
* enhancements
* Improve failure_app responses (by github.com/indirect)
* Improve failure_app responses (by @indirect)
* sessions/new and registrations/new also respond to xml and json now
* bug fix
* Fix a regression that occurred if reset_password_sent_at is not present (by github.com/stevehodgkiss)
* Fix a regression that occurred if reset_password_sent_at is not present (by @stevehodgkiss)
== 1.3.0
* enhancements
* All controllers can now handle different mime types than html using Responders (by github.com/sikachu)
* Added reset_password_within as configuration option to send the token for recovery (by github.com/jdguyot)
* Bump password length to 128 characters (by github.com/k33l0r)
* Add :only as option to devise_for (by github.com/timoschilling)
* Allow to override path after sending password instructions (by github.com/irohiroki)
* require_no_authentication has its own flash message (by github.com/jackdempsey)
* All controllers can now handle different mime types than html using Responders (by @sikachu)
* Added reset_password_within as configuration option to send the token for recovery (by @jdguyot)
* Bump password length to 128 characters (by @k33l0r)
* Add :only as option to devise_for (by @timoschilling)
* Allow to override path after sending password instructions (by @irohiroki)
* require_no_authentication has its own flash message (by @jackdempsey)
* bug fix
* Fix a bug where configuration options were being included too late
* Ensure Devise::TestHelpers can be used to tests Devise internal controllers (by github.com/jwilger)
* valid_password? should not choke on empty passwords (by github.com/mikel)
* Ensure Devise::TestHelpers can be used to tests Devise internal controllers (by @jwilger)
* valid_password? should not choke on empty passwords (by @mikel)
* Calling devise more than once does not include previously added modules anymore
* downcase_keys before validation
@@ -211,16 +241,16 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* bug fix
* Fix an issue causing infinite redirects in production
* rails g destroy works properly with devise generators (by github.com/andmej)
* before_failure callbacks should work on test helpers (by github.com/twinge)
* rememberable cookie now is httponly by default (by github.com/JamesFerguson)
* Add missing confirmation_keys (by github.com/JohnPlummer)
* rails g destroy works properly with devise generators (by @andmej)
* before_failure callbacks should work on test helpers (by @twinge)
* rememberable cookie now is httponly by default (by @JamesFerguson)
* Add missing confirmation_keys (by @JohnPlummer)
* Ensure after_* hooks are called on RegistrationsController
* When using database_authenticatable Devise will now only create an email field when appropriate (if using default authentication_keys or custom authentication_keys with email included)
* Ensure stateless token does not trigger timeout (by github.com/pixelauthority)
* Ensure stateless token does not trigger timeout (by @pixelauthority)
* Implement handle_unverified_request for Rails 3.0.4 compatibility and improve FailureApp reliance on symbols
* Consider namespaces while generating routes
* Custom failure apps no longer ignored in test mode (by github.com/jaghion)
* Custom failure apps no longer ignored in test mode (by @jaghion)
* Do not depend on ActiveModel::Dirty
* Manual sign_in now triggers remember token
* Be sure to halt strategies on failures
@@ -229,7 +259,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Ensure there is no Mongoid injection
* deprecations
* Deprecated anybody_signed_in? in favor of signed_in? (by github.com/gavinhughes)
* Deprecated anybody_signed_in? in favor of signed_in? (by @gavinhughes)
* Removed --haml and --slim view templates
* Devise::OmniAuth helpers were deprecated and removed in favor of Omniauth.config.test_mode
@@ -242,11 +272,11 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Added OmniAuth support
* Added ORM adapter to abstract ORM iteraction
* sign_out_via is available in the router to configure the method used for sign out (by github.com/martinrehfeld)
* Improved Ajax requests handling in failure app (by github.com/spastorino)
* sign_out_via is available in the router to configure the method used for sign out (by @martinrehfeld)
* Improved Ajax requests handling in failure app (by @spastorino)
* Added request_keys to easily use request specific values (like subdomain) in authentication
* Increased the size of friendly_token to 60 characters (reduces the chances of a successful brute attack)
* Ensure the friendly token does not include "_" or "-" since some e-mails may not autolink it properly (by github.com/rymai)
* Ensure the friendly token does not include "_" or "-" since some e-mails may not autolink it properly (by @rymai)
* Extracted encryptors into :encryptable for better bcrypt support
* :rememberable is now able to use salt as token if no remember_token is provided
* Store the salt in session and expire the session if the user changes his password
@@ -255,7 +285,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Sign up now check if the user is active or not and redirect him accordingly setting the inactive_signed_up message
* Use ActiveModel#to_key instead of #id
* sign_out_all_scopes now destroys the whole session
* Added case_insensitive_keys that automatically downcases the given keys, by default downcases only e-mail (by github.com/adahl)
* Added case_insensitive_keys that automatically downcases the given keys, by default downcases only e-mail (by @adahl)
* default behavior changes
* sign_out_all_scopes defaults to true as security measure
@@ -264,12 +294,12 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* bugfix
* after_sign_in_path_for always receives a resource
* Do not execute Warden::Callbacks on Devise::TestHelpers (by github.com/sgronblo)
* Allow password recovery and account unlocking to change used keys (by github.com/RStankov)
* Do not execute Warden::Callbacks on Devise::TestHelpers (by @sgronblo)
* Allow password recovery and account unlocking to change used keys (by @RStankov)
* FailureApp now properly handles nil request.format
* Fix a bug causing FailureApp to return with HTTP Auth Headers for IE7
* Ensure namespaces has proper scoped views
* Ensure Devise does not set empty flash messages (by github.com/sxross)
* Ensure Devise does not set empty flash messages (by @sxross)
== 1.1.6
@@ -294,11 +324,11 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* bugfix
* Add reply-to to e-mail headers by default
* Updated the views generator to respect the rails :template_engine option (by github.com/fredwu)
* Updated the views generator to respect the rails :template_engine option (by @fredwu)
* Check the type of HTTP Authentication before using Basic headers
* Avoid invalid_salt errors by checking salt presence (by github.com/thibaudgg)
* Forget user deletes the right cookie before logout, not remembering the user anymore (by github.com/emtrane)
* Fix for failed first-ever logins on PostgreSQL where column default is nil (by github.com/bensie)
* Avoid invalid_salt errors by checking salt presence (by @thibaudgg)
* Forget user deletes the right cookie before logout, not remembering the user anymore (by @emtrane)
* Fix for failed first-ever logins on PostgreSQL where column default is nil (by @bensie)
* :default options is now honored in migrations
== 1.1.2
@@ -314,16 +344,16 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 1.1.0
* enhancements
* Rememberable module allows user to be remembered across browsers and is enabled by default (by github.com/trevorturk)
* Rememberable module allows you to activate the period the remember me token is extended (by github.com/trevorturk)
* Rememberable module allows user to be remembered across browsers and is enabled by default (by @trevorturk)
* Rememberable module allows you to activate the period the remember me token is extended (by @trevorturk)
* devise_for can now be used together with scope method in routes but with a few limitations (check the documentation)
* Support `as` or `devise_scope` in the router to specify controller access scope
* HTTP Basic Auth can now be disabled/enabled for xhr(ajax) requests using http_authenticatable_on_xhr option (by github.com/pellja)
* HTTP Basic Auth can now be disabled/enabled for xhr(ajax) requests using http_authenticatable_on_xhr option (by @pellja)
* bug fix
* Fix a bug in Devise::TestHelpers where current_user was returning a Response object for non active accounts
* Devise should respect script_name and path_info contracts
* Fix a bug when accessing a path with (.:format) (by github.com/klacointe)
* Fix a bug when accessing a path with (.:format) (by @klacointe)
* Do not add unlock routes unless unlock strategy is email or both
* Email should be case insensitive
* Store classes as string in session, to avoid serialization and stale data issues
@@ -334,10 +364,10 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 1.1.rc2
* enhancements
* Allow to set cookie domain for the remember token. (by github.com/mantas)
* Allow to set cookie domain for the remember token. (by @mantas)
* Added navigational formats to specify when it should return a 302 and when a 401.
* Added authenticate(scope) support in routes (by github.com/wildchild)
* Added after_update_path_for to registrations controller (by github.com/thedelchop)
* Added authenticate(scope) support in routes (by @wildchild)
* Added after_update_path_for to registrations controller (by @thedelchop)
* Allow the mailer object to be replaced through config.mailer = "MyOwnMailer"
* bug fix
@@ -385,10 +415,10 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Support for latest MongoMapper
* Added anybody_signed_in? helper (by github.com/SSDany)
* Added anybody_signed_in? helper (by @SSDany)
* bug fix
* confirmation_required? is properly honored on active? calls. (by github.com/paulrosania)
* confirmation_required? is properly honored on active? calls. (by @paulrosania)
== 1.0.7
@@ -429,7 +459,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 1.0.2
* enhancements
* Allows you set mailer content type (by github.com/glennr)
* Allows you set mailer content type (by @glennr)
* bug fix
* Uses the same content type as request on http authenticatable 401 responses
@@ -462,12 +492,12 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Added gemspec to repo
* Added token authenticatable (by github.com/grimen)
* Added token authenticatable (by @grimen)
== 0.9.1
* bug fix
* Allow bigger salt size (by github.com/jgeiger)
* Allow bigger salt size (by @jgeiger)
* Fix relative url root
== 0.9.0
@@ -477,11 +507,11 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* :success and :failure flash messages are now :notice and :alert
* enhancements
* Added devise lockable (by github.com/mhfs)
* Added devise lockable (by @mhfs)
* Warden 0.9.0 compatibility
* Mongomapper 0.6.10 compatibility
* Added Devise.add_module as hooks for extensions (by github.com/grimen)
* Ruby 1.9.1 compatibility (by github.com/grimen)
* Added Devise.add_module as hooks for extensions (by @grimen)
* Ruby 1.9.1 compatibility (by @grimen)
* bug fix
* Accept path prefix not starting with slash
@@ -490,10 +520,10 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.8.2
* enhancements
* Allow Devise.mailer_sender to be a proc (by github.com/grimen)
* Allow Devise.mailer_sender to be a proc (by @grimen)
* bug fix
* Fix bug with passenger, update is required to anyone deploying on passenger (by github.com/dvdpalm)
* Fix bug with passenger, update is required to anyone deploying on passenger (by @dvdpalm)
== 0.8.1
@@ -510,11 +540,11 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* enhancements
* Warden 0.8.0 compatibility
* Add an easy for map.connect "sign_in", :controller => "sessions", :action => "new" to work
* Added :bcrypt encryptor (by github.com/capotej)
* Added :bcrypt encryptor (by @capotej)
* bug fix
* sign_in_count is also increased when user signs in via password change, confirmation, etc..
* More DataMapper compatibility (by github.com/lancecarlson)
* More DataMapper compatibility (by @lancecarlson)
* deprecation
* Removed DeviseMailer.sender
@@ -554,7 +584,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.7.1
* enhancements
* Small enhancements for other plugins compatibility (by github.com/grimen)
* Small enhancements for other plugins compatibility (by @grimen)
== 0.7.0
@@ -648,9 +678,9 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Fixed a bug where remember me module was not working properly
* enhancements
* Moved encryption strategy into the Encryptors module to allow several algorithms (by github.com/mhfs)
* Implemented encryptors for Clearance, Authlogic and Restful-Authentication (by github.com/mhfs)
* Added support for MongoMapper (by github.com/shingara)
* Moved encryption strategy into the Encryptors module to allow several algorithms (by @mhfs)
* Implemented encryptors for Clearance, Authlogic and Restful-Authentication (by @mhfs)
* Added support for MongoMapper (by @shingara)
== 0.4.3

View File

@@ -2,7 +2,7 @@ source "http://rubygems.org"
gemspec
gem "rails", "~> 3.1.0"
gem "rails", "~> 3.2.0"
gem "omniauth", "~> 1.0.0"
gem "omniauth-oauth2", "~> 1.0.0"
gem "rdoc"

View File

@@ -1,44 +1,44 @@
PATH
remote: .
specs:
devise (1.5.2)
devise (2.0.1)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.0.3)
railties (~> 3.1)
warden (~> 1.1)
GEM
remote: http://rubygems.org/
specs:
actionmailer (3.1.3)
actionpack (= 3.1.3)
mail (~> 2.3.0)
actionpack (3.1.3)
activemodel (= 3.1.3)
activesupport (= 3.1.3)
actionmailer (3.2.0)
actionpack (= 3.2.0)
mail (~> 2.4.0)
actionpack (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
builder (~> 3.0.0)
erubis (~> 2.7.0)
i18n (~> 0.6)
rack (~> 1.3.5)
journey (~> 1.0.0)
rack (~> 1.4.0)
rack-cache (~> 1.1)
rack-mount (~> 0.8.2)
rack-test (~> 0.6.1)
sprockets (~> 2.0.3)
activemodel (3.1.3)
activesupport (= 3.1.3)
sprockets (~> 2.1.2)
activemodel (3.2.0)
activesupport (= 3.2.0)
builder (~> 3.0.0)
i18n (~> 0.6)
activerecord (3.1.3)
activemodel (= 3.1.3)
activesupport (= 3.1.3)
arel (~> 2.2.1)
activerecord (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
arel (~> 3.0.0)
tzinfo (~> 0.3.29)
activeresource (3.1.3)
activemodel (= 3.1.3)
activesupport (= 3.1.3)
activesupport (3.1.3)
activeresource (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
activesupport (3.2.0)
i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.2.6)
arel (2.2.1)
arel (3.0.0)
bcrypt-ruby (3.0.1)
bson (1.5.1)
bson_ext (1.3.1)
@@ -52,10 +52,11 @@ GEM
hashie (1.2.0)
hike (1.2.1)
i18n (0.6.0)
json (1.6.3)
journey (1.0.0)
json (1.6.5)
linecache (0.46)
rbx-require-relative (> 0.0.4)
mail (2.3.0)
mail (2.4.1)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -86,13 +87,11 @@ GEM
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
orm_adapter (0.0.5)
orm_adapter (0.0.6)
polyglot (0.3.3)
rack (1.3.5)
rack (1.4.1)
rack-cache (1.1)
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)
@@ -100,24 +99,24 @@ GEM
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.1.3)
actionmailer (= 3.1.3)
actionpack (= 3.1.3)
activerecord (= 3.1.3)
activeresource (= 3.1.3)
activesupport (= 3.1.3)
rails (3.2.0)
actionmailer (= 3.2.0)
actionpack (= 3.2.0)
activerecord (= 3.2.0)
activeresource (= 3.2.0)
activesupport (= 3.2.0)
bundler (~> 1.0)
railties (= 3.1.3)
railties (3.1.3)
actionpack (= 3.1.3)
activesupport (= 3.1.3)
railties (= 3.2.0)
railties (3.2.0)
actionpack (= 3.2.0)
activesupport (= 3.2.0)
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.11)
rdoc (3.12)
json (~> 1.4)
ruby-debug (0.10.4)
columnize (>= 0.1)
@@ -125,7 +124,7 @@ GEM
ruby-debug-base (0.10.4)
linecache (>= 0.3)
ruby-openid (2.1.8)
sprockets (2.0.3)
sprockets (2.1.2)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
@@ -161,7 +160,7 @@ DEPENDENCIES
omniauth-facebook
omniauth-oauth2 (~> 1.0.0)
omniauth-openid (~> 1.0.1)
rails (~> 3.1.0)
rails (~> 3.2.0)
rdoc
ruby-debug (>= 0.10.3)
sqlite3-ruby

View File

@@ -1,4 +1,4 @@
Copyright 2009-2011 Plataforma Tecnologia. http://blog.plataformatec.com.br
Copyright 2009-2012 Plataforma Tecnologia. http://blog.plataformatec.com.br
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,8 +1,10 @@
*IMPORTANT:* Devise 2.0.0.rc is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
*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
== Devise
## Devise
{<img src="https://secure.travis-ci.org/plataformatec/devise.png" />}[http://travis-ci.org/plataformatec/devise]
INFO: This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
[![Build Status](https://secure.travis-ci.org/plataformatec/devise.png)](http://travis-ci.org/plataformatec/devise)
Devise is a flexible authentication solution for Rails based on Warden. It:
@@ -26,15 +28,15 @@ It's comprised of 12 modules:
* 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).
== Information
## Information
=== The Devise wiki
### The Devise wiki
The Devise Wiki has lots of additional information about Devise including many "how-to" articles and answers to the most frequently asked questions. Please browse the Wiki after finishing this README:
https://wiki.github.com/plataformatec/devise
=== Bug reports
### Bug reports
If you discover a problem with Devise, we would like to know about it. However, we ask that you please review these guidelines before submitting a bug report:
@@ -42,59 +44,41 @@ 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.
=== Mailing list
### Mailing list
If you have any questions, comments, or concerns, please use the Google Group instead of the GitHub issue tracker:
https://groups.google.com/group/plataformatec-devise
=== RDocs
### RDocs
You can view the Devise documentation in RDoc format here:
http://rubydoc.info/github/plataformatec/devise/master/frames
If you need to use Devise with Rails 2.3, you can always run `gem server` from the command line after you install the gem to access the old documentation.
If you need to use Devise with Rails 2.3, you can always run "gem server" from the command line after you install the gem to access the old documentation.
=== Example applications
### Example applications
There are a few example applications available on GitHub that demonstrate various features of Devise with different versions of Rails. You can view them here:
https://github.com/plataformatec/devise/wiki/Example-Applications
=== Extensions
### Extensions
Our community has created a number of extensions that add functionality above and beyond what is included with Devise. You can view a list of available extensions and add your own here:
https://github.com/plataformatec/devise/wiki/Extensions
=== Contributing
### Contributing
We hope that you will consider contributing to Devise. Please read this short overview for some information about how to get started:
https://github.com/plataformatec/devise/wiki/Contributing
You will usually want to write tests for your changes. To run the test suite, `cd` into Devise's top-level directory and run `bundle install` and `rake`. For the tests to pass, you will need to have a MongoDB server (version 2.0 or newer) running on your system.
You will usually want to write tests for your changes. To run the test suite, go into Devise's top-level directory and run "bundle install" and "rake". For the tests to pass, you will need to have a MongoDB server (version 2.0 or newer) running on your system.
== Installation
You can use the latest Rails 3 gem with the latest Devise gem:
gem install devise
After you install Devise and add it to your Gemfile, you need to run the generator:
rails generate devise:install
The generator will install an initializer which describes ALL Devise's configuration options and you MUST take a look at it. When you are done, you are ready to add Devise to any of your models using the generator:
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 db:migrate as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file, continue reading this file to understand exactly what the generator produces and how to use it. Finally, if your server was already running, then restart it as Rails doesn't automatically load methods from a new gem.
Support for Rails 2.3.x can be found by installing Devise 1.0.x from the v1.0 branch.
== Starting with Rails?
## Starting with Rails?
If you are building your first Rails application, we recommend you to *not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch, today we have two resources:
@@ -103,266 +87,302 @@ If you are building your first Rails application, we recommend you to *not* use
Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
== Getting started
## Getting started
This is a walkthrough with all steps you need to setup a devise resource, including model, migration, route files, and optional configuration.
Devise 2.0 works with Rails 3.1 onwards. You can add it to your Gemfile with:
Devise must be set up within the model (or models) you want to use. Devise routes must be created inside your config/routes.rb file.
gem 'devise'
We're assuming here you want a User model with some Devise modules, as outlined below:
Run the bundle command to install it.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
end
After you install Devise and add it to your Gemfile, you need to run the generator:
After you choose which modules to use, you need to set up your migrations. Luckily, Devise has some helpers to save you from this boring work:
```console
rails generate devise:install
```
create_table :users do |t|
t.database_authenticatable
t.confirmable
t.recoverable
t.rememberable
t.trackable
t.timestamps
end
The generator will install an initializer which describes ALL Devise's configuration options and you MUST take a look at it. When you are done, you are ready to add Devise to any of your models using the generator:
Devise doesn't use _attr_accessible_ or _attr_protected_ inside its modules, so be sure to define attributes as accessible or protected in your model.
```console
rails generate devise MODEL
```
Configure your routes after setting up your model. Open your config/routes.rb file and add:
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.
devise_for :users
This will use your User model to create a set of needed routes (you can see them by running `rake routes`). If you invoked the devise generator, you noticed that this is exactly what the generator produces for us: model, routes and migrations.
Don't forget to run rake db:migrate and you are ready to go! But don't stop reading here, we still have a lot to tell you.
=== Controller filters and helpers
### 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:
before_filter :authenticate_user!
```ruby
before_filter :authenticate_user!
```
To verify if a user is signed in, use the following helper:
user_signed_in?
```ruby
user_signed_in?
```
For the current signed-in user, this helper is available:
current_user
```ruby
current_user
```
You can access the session for this scope:
user_session
```ruby
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:
root :to => "home#index"
```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:
Finally, you need to set up default url options for the mailer in each environment. Here is the configuration for "config/environments/development.rb":
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
```ruby
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
```
Notice that if your devise model is not called "user" but "member", then the helpers you should use are:
before_filter :authenticate_member!
```ruby
before_filter :authenticate_member!
member_signed_in?
member_signed_in?
current_member
current_member
member_session
member_session
```
=== Configuring Models
### Configuring Models
The devise method in your models also accepts some options to configure its modules. For example, you can choose which encryptor to use in database_authenticatable:
The devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the encryption algorithm with:
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20
```ruby
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20
```
Besides :stretches, you can define :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the "devise:install" generator described above.
=== Configuring multiple models
### Configuring multiple models
Devise allows you to set up as many roles as you want. For example, you may have a User model and also want an Admin model with just authentication, trackable, lockable and timeoutable features and no confirmation or password-recovery features. Just follow these steps:
Devise allows you to set up as many roles as you want. For example, you may have a User model and also want an Admin model with just authentication and timeoutable features. If so, just follow these steps:
# Create a migration with the required fields
create_table :admins do |t|
t.database_authenticatable
t.lockable
t.trackable
t.timestamps
end
```ruby
# Create a migration with the required fields
create_table :admins do |t|
t.string :email
t.string :encrypted_password
t.timestamps
end
# Inside your Admin model
devise :database_authenticatable, :trackable, :timeoutable, :lockable
# Inside your Admin model
devise :database_authenticatable, :timeoutable
# Inside your routes
devise_for :admins
# Inside your routes
devise_for :admins
# Inside your protected controller
before_filter :authenticate_admin!
# Inside your protected controller
before_filter :authenticate_admin!
# Inside your controllers and views
admin_signed_in?
current_admin
admin_session
# Inside your controllers and views
admin_signed_in?
current_admin
admin_session
```
=== Configuring views
On the other hand, you can simply run the generator!
### Configuring views
We built Devise to help you quickly develop an application that uses authentication. However, we don't want to be in your way when you need to customize it.
Since Devise is an engine, all its views are packaged inside the gem. These views will help you get started, but after sometime you may want to change them. If this is the case, you just need to invoke the following generator, and it will copy all views to your application:
Since Devise is an engine, all its views are packaged inside the gem. These views will help you get started, but after some time you may want to change them. If this is the case, you just need to invoke the following generator, and it will copy all views to your application:
rails generate devise:views
```console
rails generate devise:views
```
If you have more than one role in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all roles. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new". You can also use the generator to generate scoped views:
rails generate devise:views users
```console
rails generate devise:views users
```
=== Configuring controllers
### Configuring controllers
If the customization at the views level is not enough, you can customize each controller by following these steps:
1) Create your custom controller, for example a Admins::SessionsController:
class Admins::SessionsController < Devise::SessionsController
end
```ruby
class Admins::SessionsController < Devise::SessionsController
end
```
2) Tell the router to use this controller:
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
```ruby
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
```
3) And since we changed the controller, it won't use the "devise/sessions" views, so remember to copy "devise/sessions" to "admin/sessions".
Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate.
=== Configuring routes
### Configuring routes
Devise also ships with default routes. If you need to customize them, you should probably be able to do it through the devise_for method. It accepts several options like :class_name, :path_prefix and so on, including the possibility to change path names for I18n:
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' }
```ruby
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:
devise_scope :user do
get "sign_in", :to => "devise/sessions#new"
end
```ruby
devise_scope :user do
get "sign_in", :to => "devise/sessions#new"
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:
devise_for :users do
get "sign_in", :to => "devise/sessions#new"
end
```ruby
devise_for :users do
get "sign_in", :to => "devise/sessions#new"
end
```
Feel free to choose the one you prefer!
=== I18n
### I18n
Devise uses flash messages with I18n with the flash keys :notice and :alert. To customize your app, you can set up your locale file:
en:
devise:
sessions:
signed_in: 'Signed in successfully.'
```yaml
en:
devise:
sessions:
signed_in: 'Signed in successfully.'
```
You can also create distinct messages based on the resource you've configured using the singular name given in routes:
en:
devise:
sessions:
user:
signed_in: 'Welcome user, you are signed in.'
admin:
signed_in: 'Hello admin!'
```yaml
en:
devise:
sessions:
user:
signed_in: 'Welcome user, you are signed in.'
admin:
signed_in: 'Hello admin!'
```
The Devise mailer uses a similar pattern to create subject messages:
en:
devise:
mailer:
confirmation_instructions:
subject: 'Hello everybody!'
user_subject: 'Hello User! Please confirm your email'
reset_password_instructions:
subject: 'Reset instructions'
```yaml
en:
devise:
mailer:
confirmation_instructions:
subject: 'Hello everybody!'
user_subject: 'Hello User! Please confirm your email'
reset_password_instructions:
subject: 'Reset instructions'
```
Take a look at our locale file to check all available messages. You may also be interested in one of the many translations that are available on our wiki:
https://github.com/plataformatec/devise/wiki/I18n
=== Test helpers
### 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:
sign_in :user, @user # sign_in(scope, resource)
sign_in @user # sign_in(resource)
```ruby
sign_in :user, @user # sign_in(scope, resource)
sign_in @user # sign_in(resource)
sign_out :user # sign_out(scope)
sign_out @user # sign_out(resource)
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:
class ActionController::TestCase
include Devise::TestHelpers
end
```ruby
class ActionController::TestCase
include Devise::TestHelpers
end
```
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:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
```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).
=== Omniauth
### Omniauth
Devise comes with Omniauth support out of the box to authenticate from other providers. You can read more about Omniauth support in the wiki:
* https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
=== Other ORMs
### Other ORMs
Devise supports ActiveRecord (default) and Mongoid. To choose other ORM, you just need to require it in the initializer file.
=== Migrating from other solutions
### Migrating from other solutions
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of these strategies, you need set the desired encryptor in the encryptor initializer config option and add :encryptable to your model. You might also need to rename your encrypted password and salt columns to match Devise's fields (encrypted_password and password_salt).
== Troubleshooting
## Troubleshooting
=== Heroku
### Heroku
Using devise on Heroku with Ruby on Rails 3.1 requires setting:
config.assets.initialize_on_precompile = false
```ruby
config.assets.initialize_on_precompile = false
```
Read more about the potential issues at http://guides.rubyonrails.org/asset_pipeline.html
== Additional information
## Additional information
=== Warden
### Warden
Devise is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here:
https://github.com/hassox/warden
=== Contributors
### Contributors
We have a long list of valued contributors. Check them all at:
https://github.com/plataformatec/devise/contributors
=== Maintainers
### Maintainers
* José Valim (https://github.com/josevalim)
* Carlos Antônio da Silva (https://github.com/carlosantoniodasilva)
* Rodrigo Flores (https://github.com/rodrigoflores)
== License
## License
MIT License. Copyright 2011 Plataforma Tecnologia. http://blog.plataformatec.com.br
MIT License. Copyright 2012 Plataforma Tecnologia. http://blog.plataformatec.com.br

View File

@@ -1,10 +1,7 @@
class Devise::ConfirmationsController < ApplicationController
include Devise::Controllers::InternalHelpers
class Devise::ConfirmationsController < DeviseController
# GET /resource/confirmation/new
def new
build_resource({})
render_with_scope :new
end
# POST /resource/confirmation
@@ -14,7 +11,7 @@ class Devise::ConfirmationsController < ApplicationController
if successfully_sent?(resource)
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
else
respond_with_navigational(resource){ render_with_scope :new }
respond_with(resource)
end
end
@@ -27,7 +24,7 @@ class Devise::ConfirmationsController < ApplicationController
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end

View File

@@ -1,6 +1,4 @@
class Devise::OmniauthCallbacksController < ApplicationController
include Devise::Controllers::InternalHelpers
class Devise::OmniauthCallbacksController < DeviseController
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)

View File

@@ -1,11 +1,9 @@
class Devise::PasswordsController < ApplicationController
class Devise::PasswordsController < DeviseController
prepend_before_filter :require_no_authentication
include Devise::Controllers::InternalHelpers
# GET /resource/password/new
def new
build_resource({})
render_with_scope :new
end
# POST /resource/password
@@ -15,7 +13,7 @@ class Devise::PasswordsController < ApplicationController
if successfully_sent?(resource)
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with_navigational(resource){ render_with_scope :new }
respond_with(resource)
end
end
@@ -23,7 +21,6 @@ class Devise::PasswordsController < ApplicationController
def edit
self.resource = resource_class.new
resource.reset_password_token = params[:reset_password_token]
render_with_scope :edit
end
# PUT /resource/password
@@ -36,7 +33,7 @@ class Devise::PasswordsController < ApplicationController
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_in_path_for(resource)
else
respond_with_navigational(resource){ render_with_scope :edit }
respond_with resource
end
end

View File

@@ -1,12 +1,11 @@
class Devise::RegistrationsController < ApplicationController
class Devise::RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
include Devise::Controllers::InternalHelpers
# GET /resource/sign_up
def new
resource = build_resource({})
respond_with_navigational(resource){ render_with_scope :new }
respond_with resource
end
# POST /resource
@@ -19,19 +18,19 @@ class Devise::RegistrationsController < ApplicationController
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
respond_with_navigational(resource) { render_with_scope :new }
clean_up_passwords resource
respond_with resource
end
end
# GET /resource/edit
def edit
render_with_scope :edit
render :edit
end
# PUT /resource
@@ -50,8 +49,8 @@ class Devise::RegistrationsController < ApplicationController
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords(resource)
respond_with_navigational(resource){ render_with_scope :edit }
clean_up_passwords resource
respond_with resource
end
end
@@ -75,40 +74,34 @@ class Devise::RegistrationsController < ApplicationController
protected
# 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] || {}
self.resource = resource_class.new_with_session(hash, session)
end
# 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] || {}
self.resource = resource_class.new_with_session(hash, session)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# Returns the inactive reason translated.
def inactive_reason(resource)
reason = resource.inactive_message.to_s
I18n.t("devise.registrations.reasons.#{reason}", :default => reason)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
root_path
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
end

View File

@@ -1,18 +1,17 @@
class Devise::SessionsController < ApplicationController
class Devise::SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
include Devise::Controllers::InternalHelpers
# GET /resource/sign_in
def new
resource = build_resource
clean_up_passwords(resource)
respond_with_navigational(resource, stub_options(resource)){ render_with_scope :new }
respond_with(resource, serialize_options(resource))
end
# POST /resource/sign_in
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_in_path_for(resource)
@@ -39,11 +38,15 @@ class Devise::SessionsController < ApplicationController
protected
def stub_options(resource)
def serialize_options(resource)
methods = resource_class.authentication_keys.dup
methods = methods.keys if methods.is_a?(Hash)
methods << :password if resource.respond_to?(:password)
{ :methods => methods, :only => [:password] }
end
def auth_options
{ :scope => resource_name, :recall => "#{controller_path}#new" }
end
end

View File

@@ -1,11 +1,9 @@
class Devise::UnlocksController < ApplicationController
class Devise::UnlocksController < DeviseController
prepend_before_filter :require_no_authentication
include Devise::Controllers::InternalHelpers
# GET /resource/unlock/new
def new
build_resource({})
render_with_scope :new
end
# POST /resource/unlock
@@ -15,7 +13,7 @@ class Devise::UnlocksController < ApplicationController
if successfully_sent?(resource)
respond_with({}, :location => new_session_path(resource_name))
else
respond_with_navigational(resource){ render_with_scope :new }
respond_with(resource)
end
end
@@ -27,7 +25,7 @@ class Devise::UnlocksController < ApplicationController
set_flash_message :notice, :unlocked if is_navigational_format?
respond_with_navigational(resource){ redirect_to new_session_path(resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
end

View File

@@ -0,0 +1,165 @@
# All Devise controllers are inherited from here.
class DeviseController < Devise.parent_controller.constantize
include Devise::Controllers::ScopedViews
helper DeviseHelper
helpers = %w(resource scope_name resource_name signed_in_resource
resource_class devise_mapping)
hide_action *helpers
helper_method *helpers
prepend_before_filter :assert_is_devise_resource!
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
# Gets the actual resource stored in the instance variable
def resource
instance_variable_get(:"@#{resource_name}")
end
# Proxy to devise map name
def resource_name
devise_mapping.name
end
alias :scope_name :resource_name
# Proxy to devise map class
def resource_class
devise_mapping.to
end
# Returns a signed in resource from session (if one exists)
def signed_in_resource
warden.authenticate(:scope => resource_name)
end
# Attempt to find the mapped route for devise based on request path
def devise_mapping
@devise_mapping ||= request.env["devise.mapping"]
end
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:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
MESSAGE
end
# Returns real navigational formats which are supported by Rails
def navigational_formats
@navigational_formats ||= Devise.navigational_formats.select { |format| Mime::EXTENSION_LOOKUP[format.to_s] }
end
def unknown_action!(msg)
logger.debug "[Devise] #{msg}" if logger
raise AbstractController::ActionNotFound, msg
end
# Sets the resource creating an instance variable
def resource=(new_resource)
instance_variable_set(:"@#{resource_name}", new_resource)
end
# Build a devise resource.
def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new(hash)
end
# Helper for use in before_filters where no authentication is required.
#
# Example:
# before_filter :require_no_authentication, :only => :new
def require_no_authentication
assert_is_devise_resource!
return unless is_navigational_format?
no_input = devise_mapping.no_input_strategies
authenticated = if no_input.present?
args = no_input.dup.push :scope => resource_name
warden.authenticate?(*args)
else
warden.authenticated?(resource_name)
end
if authenticated
resource = warden.user(resource_name)
flash[:alert] = I18n.t("devise.failure.already_authenticated")
redirect_to after_sign_in_path_for(resource)
end
end
# Helper for use after calling send_*_instructions methods on a resource.
# If we are in paranoid mode, we always act as if the resource was valid
# and instructions were sent.
def successfully_sent?(resource)
notice = if Devise.paranoid
resource.errors.clear
:send_paranoid_instructions
elsif resource.errors.empty?
:send_instructions
end
if notice
set_flash_message :notice, notice if is_navigational_format?
true
end
end
# Sets the flash message with :key, using I18n. By default you are able
# to setup your messages using specific resource scope, and if no one is
# found we look to default scope.
# Example (i18n locale file):
#
# en:
# devise:
# passwords:
# #default_scope_messages - only if resource_scope is not found
# user:
# #resource_scope_messages
#
# Please refer to README or en.yml locale file to check what messages are
# available.
def set_flash_message(key, kind, options={})
options[:scope] = "devise.#{controller_name}"
options[:default] = Array(options[:default]).unshift(kind.to_sym)
options[:resource_name] = resource_name
options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
message = I18n.t("#{resource_name}.#{kind}", options)
flash[key] = message if message.present?
end
def clean_up_passwords(object)
object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
end
def respond_with_navigational(*args, &block)
respond_with(*args) do |format|
format.any(*navigational_formats, &block)
end
end
def request_format
@request_format ||= request.format.try(:ref)
end
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? && devise_mapping
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
else
super
end
end
end

View File

@@ -0,0 +1,25 @@
<%- 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 -%>

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Resend confirmation instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -13,4 +13,4 @@
<div><%= f.submit "Change my password" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Send me reset password instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -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>

View File

@@ -15,4 +15,4 @@
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -14,4 +14,4 @@
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -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/shared/_links.erb is deprecated" \
"please use devise/_links.erb instead." %>
<%= render "links" %>

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -35,17 +35,15 @@ en:
confirmed: 'Your account was successfully confirmed. You are now signed in.'
registrations:
signed_up: 'Welcome! You have signed up successfully.'
inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.'
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.'
updated: 'You updated your account successfully.'
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
reasons:
inactive: 'inactive'
unconfirmed: 'unconfirmed'
locked: 'locked'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account was successfully unlocked. You are now signed in.'
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.'

View File

@@ -5,7 +5,7 @@ require "devise/version"
Gem::Specification.new do |s|
s.name = "devise"
s.version = Devise::VERSION.dup
s.platform = Gem::Platform::RUBY
s.platform = Gem::Platform::RUBY
s.summary = "Flexible authentication solution for Rails with Warden"
s.email = "contact@plataformatec.com.br"
s.homepage = "http://github.com/plataformatec/devise"
@@ -15,11 +15,11 @@ Gem::Specification.new do |s|
s.rubyforge_project = "devise"
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.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("bcrypt-ruby", "~> 3.0")
end
s.add_dependency("railties", "~> 3.1")
end

View File

@@ -0,0 +1,35 @@
source "http://rubygems.org"
gem "devise", :path => ".."
gem "rails", "~> 3.1.0"
gem "omniauth", "~> 1.0.0"
gem "omniauth-oauth2", "~> 1.0.0"
gem "rdoc"
group :test do
gem "omniauth-facebook"
gem "omniauth-openid", "~> 1.0.1"
gem "webrat", "0.7.2", :require => false
gem "mocha", :require => false
platforms :mri_18 do
gem "ruby-debug", ">= 0.10.3"
end
end
platforms :jruby do
gem "activerecord-jdbc-adapter"
gem "activerecord-jdbcsqlite3-adapter"
gem "jruby-openssl"
end
platforms :ruby do
gem "sqlite3-ruby"
group :mongoid do
gem "mongo", "~> 1.3.0"
gem "mongoid", "~> 2.0"
gem "bson_ext", "~> 1.3.0"
end
end

View File

@@ -16,10 +16,8 @@ module Devise
module Controllers
autoload :Helpers, 'devise/controllers/helpers'
autoload :InternalHelpers, 'devise/controllers/internal_helpers'
autoload :Rememberable, 'devise/controllers/rememberable'
autoload :ScopedViews, 'devise/controllers/scoped_views'
autoload :SharedHelpers, 'devise/controllers/shared_helpers'
autoload :UrlHelpers, 'devise/controllers/url_helpers'
end
@@ -202,9 +200,8 @@ module Devise
@@skip_session_storage = []
# Which formats should be treated as navigational.
# We need both :"*/*" and "*/*" to work on different Rails versions.
mattr_accessor :navigational_formats
@@navigational_formats = [:"*/*", "*/*", :html]
@@navigational_formats = ["*/*", :html]
# When set to true, signing out a user signs out all other scopes.
mattr_accessor :sign_out_all_scopes
@@ -214,6 +211,18 @@ module Devise
mattr_accessor :sign_out_via
@@sign_out_via = :get
# The parent controller all Devise controllers inherits from.
# Defaults to ApplicationController. This should be set early
# in the initialization process and should be set to a string.
mattr_accessor :parent_controller
@@parent_controller = "ApplicationController"
# The router Devise should use to generate routes. Defaults
# to :main_app. Should be overriden by engines in order
# to provide custom routes.
mattr_accessor :router_name
@@router_name = nil
# DEPRECATED CONFIG
# If true, uses salt as remember token and does not create it in the database.
@@ -290,6 +299,10 @@ module Devise
end
end
def self.available_router_name
router_name || :main_app
end
def self.omniauth_providers
omniauth_configs.keys
end
@@ -334,7 +347,7 @@ module Devise
#
def self.add_module(module_name, options = {})
ALL << module_name
options.assert_valid_keys(:strategy, :model, :controller, :route)
options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input)
if strategy = options[:strategy]
strategy = (strategy == true ? module_name : strategy)
@@ -346,7 +359,7 @@ module Devise
CONTROLLERS[module_name] = controller
end
NO_INPUT << strategy if strategy && controller != :sessions
NO_INPUT << strategy if options[:no_input]
if route = options[:route]
case route
@@ -413,11 +426,6 @@ module Devise
end
end
# Returns true if Rails version is bigger than 3.0.x
def self.rack_session?
Rails::VERSION::STRING[0,3] != "3.0"
end
# Regenerates url helpers considering Devise.mapping
def self.regenerate_helpers!
Devise::Controllers::UrlHelpers.remove_helpers!

View File

@@ -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.
@@ -168,7 +168,13 @@ module Devise
def signed_in_root_path(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
home_path = "#{scope}_root_path"
respond_to?(home_path, true) ? send(home_path) : root_path
if respond_to?(home_path, true)
send(home_path)
elsif respond_to?(:root_path)
root_path
else
"/"
end
end
# The default url to be used after signing in. This is used by all Devise
@@ -209,7 +215,7 @@ module Devise
#
# By default it is the root_path.
def after_sign_out_path_for(resource_or_scope)
root_path
respond_to?(:root_path) ? root_path : "/"
end
# Sign in a user and tries to redirect first to the stored location and

View File

@@ -1,161 +0,0 @@
module Devise
module Controllers
# Those helpers are used only inside Devise controllers and should not be
# included in ApplicationController since they all depend on the url being
# accessed.
module InternalHelpers #:nodoc:
extend ActiveSupport::Concern
include Devise::Controllers::ScopedViews
include Devise::Controllers::SharedHelpers
included do
helper DeviseHelper
helpers = %w(resource scope_name resource_name signed_in_resource
resource_class devise_mapping devise_controller?)
hide_action *helpers
helper_method *helpers
prepend_before_filter :is_devise_resource?
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
end
# Gets the actual resource stored in the instance variable
def resource
instance_variable_get(:"@#{resource_name}")
end
# Proxy to devise map name
def resource_name
devise_mapping.name
end
alias :scope_name :resource_name
# Proxy to devise map class
def resource_class
devise_mapping.to
end
# Returns a signed in resource from session (if one exists)
def signed_in_resource
warden.authenticate(:scope => resource_name)
end
# Attempt to find the mapped route for devise based on request path
def devise_mapping
@devise_mapping ||= request.env["devise.mapping"]
end
# Overwrites devise_controller? to return true
def devise_controller?
true
end
protected
# Checks whether it's a devise mapped resource or not.
def 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:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
MESSAGE
end
# Returns real navigational formats which are supported by Rails
def navigational_formats
@navigational_formats ||= Devise.navigational_formats.select{ |format| Mime::EXTENSION_LOOKUP[format.to_s] }
end
def unknown_action!(msg)
logger.debug "[Devise] #{msg}" if logger
raise ActionController::UnknownAction, msg
end
# Sets the resource creating an instance variable
def resource=(new_resource)
instance_variable_set(:"@#{resource_name}", new_resource)
end
# Build a devise resource.
def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new(hash)
end
# Helper for use in before_filters where no authentication is required.
#
# Example:
# before_filter :require_no_authentication, :only => :new
def require_no_authentication
return unless is_navigational_format?
no_input = devise_mapping.no_input_strategies
authenticated = if no_input.present?
args = no_input.dup.push :scope => resource_name
warden.authenticate?(*args)
else
warden.authenticated?(resource_name)
end
if authenticated
resource = warden.user(resource_name)
flash[:alert] = I18n.t("devise.failure.already_authenticated")
redirect_to after_sign_in_path_for(resource)
end
end
# Helper for use after calling send_*_instructions methods on a resource.
# If we are in paranoid mode, we always act as if the resource was valid
# and instructions were sent.
def successfully_sent?(resource)
notice = if Devise.paranoid
resource.errors.clear
:send_paranoid_instructions
elsif resource.errors.empty?
:send_instructions
end
if notice
set_flash_message :notice, notice if is_navigational_format?
true
end
end
# Sets the flash message with :key, using I18n. By default you are able
# to setup your messages using specific resource scope, and if no one is
# found we look to default scope.
# Example (i18n locale file):
#
# en:
# devise:
# passwords:
# #default_scope_messages - only if resource_scope is not found
# user:
# #resource_scope_messages
#
# Please refer to README or en.yml locale file to check what messages are
# available.
def set_flash_message(key, kind, options={}) #:nodoc:
options[:scope] = "devise.#{controller_name}"
options[:default] = Array(options[:default]).unshift(kind.to_sym)
options[:resource_name] = resource_name
message = I18n.t("#{resource_name}.#{kind}", options)
flash[key] = message if message.present?
end
def clean_up_passwords(object) #:nodoc:
object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
end
def respond_with_navigational(*args, &block)
respond_with(*args) do |format|
format.any(*navigational_formats, &block)
end
end
end
end
end

View File

@@ -12,22 +12,6 @@ module Devise
@scoped_views = value
end
end
protected
# Render a view for the specified scope. Turned off by default.
# Accepts just :controller as option.
def render_with_scope(action, path=self.controller_path)
if self.class.scoped_views?
begin
render :template => "#{devise_mapping.scoped_path}/#{path.split("/").last}/#{action}"
rescue ActionView::MissingTemplate
render :template => "#{path}/#{action}"
end
else
render :template => "#{path}/#{action}"
end
end
end
end
end

View File

@@ -1,26 +0,0 @@
module Devise
module Controllers
# Helpers used in both FailureApp and Devise controllers.
module SharedHelpers
MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
protected
# Helper used by FailureApp and Devise controllers to retrieve proper formats.
def request_format
@request_format ||= if request.format.respond_to?(:ref)
request.format.ref
elsif MIME_REFERENCES
request.format
elsif request.format # Rails < 3.0.4
request.format.to_sym
end
end
# Check whether it's navigational format, such as :html or :iphone, or not.
def is_navigational_format?
Devise.navigational_formats.include?(request_format)
end
end
end
end

View File

@@ -16,7 +16,15 @@ module Devise
# new_confirmation_path(:user) => new_user_confirmation_path
# confirmation_path(:user) => user_confirmation_path
#
# Those helpers are added to your ApplicationController.
# Those helpers are included by default to ActionController::Base.
#
# In case you want to add such helpers to another class, you can do
# that as long as this new class includes both url_helpers and
# mounted_helpers. Example:
#
# include Rails.application.routes.url_helpers
# include Rails.application.routes.mounted_helpers
#
module UrlHelpers
def self.remove_helpers!
self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
@@ -39,7 +47,7 @@ module Devise
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{method}(resource_or_scope, *args)
scope = Devise::Mapping.find_scope!(resource_or_scope)
send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
_devise_route_context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
end
URL_HELPERS
end
@@ -48,6 +56,12 @@ module Devise
end
generate_helpers!(Devise::URL_HELPERS)
private
def _devise_route_context
@_devise_route_context ||= send(Devise.available_router_name)
end
end
end
end

View File

@@ -9,8 +9,9 @@ module Devise
include ActionController::RackDelegation
include ActionController::UrlFor
include ActionController::Redirecting
include Rails.application.routes.url_helpers
include Devise::Controllers::SharedHelpers
include Rails.application.routes.mounted_helpers
delegate :flash, :to => :request
@@ -20,7 +21,11 @@ module Devise
end
def self.default_url_options(*args)
ApplicationController.default_url_options(*args)
if defined?(ApplicationController)
ApplicationController.default_url_options(*args)
else
{}
end
end
def respond
@@ -48,32 +53,50 @@ module Devise
def redirect
store_location!
flash[:alert] = i18n_message
if flash[:timedout] && flash[:alert]
flash.keep(:timedout)
flash.keep(:alert)
else
flash[:alert] = i18n_message
end
redirect_to redirect_url
end
protected
def i18n_message(default = nil)
message = warden.message || warden_options[:message] || default || :unauthenticated
message = warden_message || default || :unauthenticated
if message.is_a?(Symbol)
I18n.t(:"#{scope}.#{message}", :resource_name => scope,
:scope => "devise.failure", :default => [message, message.to_s])
:scope => "devise.failure", :default => [message])
else
message.to_s
end
end
def redirect_url
if warden_message == :timeout
flash[:timedout] = true
attempted_path || scope_path
else
scope_path
end
end
def scope_path
opts = {}
route = :"new_#{scope}_session_path"
opts[:format] = request_format unless skip_format?
if respond_to?(route)
send(route, opts)
else
context = send(Devise.available_router_name)
if context.respond_to?(route)
context.send(route, opts)
elsif respond_to?(:root_path)
root_path(opts)
else
"/"
end
end
@@ -130,6 +153,10 @@ module Devise
env['warden.options']
end
def warden_message
@message ||= warden.message || warden_options[:message]
end
def scope
@scope ||= warden_options[:scope] || Devise.default_scope
end
@@ -145,5 +172,13 @@ module Devise
def store_location!
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
end
def is_navigational_format?
Devise.navigational_formats.include?(request_format)
end
def request_format
@request_format ||= request.format.try(:ref)
end
end
end

View File

@@ -48,7 +48,6 @@ module Devise
# for a complete description on those values.
#
def devise(*modules)
include Devise::Models::Authenticatable
options = modules.extract_options!.dup
selected_modules = modules.map(&:to_sym).uniq.sort_by do |s|
@@ -56,6 +55,7 @@ module Devise
end
devise_modules_hook! do
include Devise::Models::Authenticatable
selected_modules.each do |m|
mod = Devise::Models.const_get(m.to_s.classify)

View File

@@ -31,7 +31,7 @@ module Devise
included do
before_create :generate_confirmation_token, :if => :confirmation_required?
after_create :send_confirmation_instructions, :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?
end
@@ -40,15 +40,17 @@ module Devise
# is already confirmed, add an error to email field. If the user is invalid
# add errors
def confirm!
unless_confirmed do
pending_any_confirmation do
self.confirmation_token = nil
self.confirmed_at = Time.now.utc
if self.class.reconfirmable
if self.class.reconfirmable && unconfirmed_email.present?
@bypass_postpone = true
self.email = unconfirmed_email if unconfirmed_email.present?
self.email = unconfirmed_email
self.unconfirmed_email = nil
save
# We need to validate in such cases to enforce e-mail uniqueness
save(:validate => true)
else
save(:validate => false)
end
@@ -66,14 +68,16 @@ module Devise
# Send confirmation instructions by email
def send_confirmation_instructions
self.confirmation_token = nil if reconfirmation_required?
@reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
self.devise_mailer.confirmation_instructions(self).deliver
end
# Resend confirmation token. This method does not need to generate a new token.
def resend_confirmation_token
unless_confirmed { send_confirmation_instructions }
pending_any_confirmation { send_confirmation_instructions }
end
# Overwrites active_for_authentication? for confirmation
@@ -105,6 +109,13 @@ module Devise
protected
# A callback method used to deliver confirmation
# 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
end
# Callback to overwrite if confirmation is required or not.
def confirmation_required?
!confirmed?
@@ -133,10 +144,9 @@ module Devise
confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
end
# Checks whether the record is confirmed or not or a new email has been added, yielding to the block
# if it's already confirmed, otherwise adds an error to email.
def unless_confirmed
unless confirmed? && !pending_reconfirmation?
# Checks whether the record requires any confirmation.
def pending_any_confirmation
if !confirmed? || pending_reconfirmation?
yield
else
self.errors.add(:email, :already_confirmed)

View File

@@ -79,7 +79,7 @@ module Devise
# if the user can login or not (wrong password, etc)
unlock_access! if lock_expired?
if super
if super && !access_locked?
self.failed_attempts = 0
save(:validate => false)
true

View File

@@ -9,8 +9,11 @@ module Devise
module Serializable
extend ActiveSupport::Concern
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
%w(to_xml serializable_hash).each do |method|
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 ||= {}

View File

@@ -23,7 +23,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

View File

@@ -5,8 +5,8 @@ Devise.with_options :model => true do |d|
d.with_options :strategy => true do |s|
routes = [nil, :new, :destroy]
s.add_module :database_authenticatable, :controller => :sessions, :route => { :session => routes }
s.add_module :token_authenticatable
s.add_module :rememberable
s.add_module :token_authenticatable, :controller => :sessions, :route => { :session => routes }, :no_input => true
s.add_module :rememberable, :no_input => true
end
# Other authentications

View File

@@ -35,7 +35,7 @@ module Devise
# Determine which values should be transformed to string or passed as-is to the query builder underneath
def param_requires_string_conversion?(value)
true unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Fixnum)
[Fixnum, TrueClass, FalseClass, Regexp].none? {|clz| value.is_a? clz }
end
end
end

View File

@@ -3,7 +3,11 @@ module Devise
include Rails.application.routes.url_helpers
def self.default_url_options(*args)
ApplicationController.default_url_options(*args)
if defined?(ApplicationController)
ApplicationController.default_url_options(*args)
else
{}
end
end
def initialize(env, scope)

View File

@@ -42,13 +42,27 @@ module Devise
end
end
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
# We can get rid of this once we support 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. If you want to continue running on this mode, please ensure " \
"you are not using validatable (you can copy the validations directly to your model) " \
"and set case_insensitive_keys to an empty array.\n"
"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)
@@ -71,6 +85,27 @@ module Devise
"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

View File

@@ -1,3 +1,5 @@
require "active_support/core_ext/object/try"
module ActionDispatch::Routing
class RouteSet #:nodoc:
# Ensure Devise modules are included only after loading routes, because we
@@ -6,6 +8,14 @@ module ActionDispatch::Routing
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. " \
"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. You can explicitly set it" \
" to :main_app as well in case you want to keep the current behavior."
end
Devise.configure_warden!
Devise.regenerate_helpers!
true
@@ -84,15 +94,16 @@ module ActionDispatch::Routing
#
# You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
#
# * :module => the namespace to find controlers. By default, devise will access devise/sessions,
# devise/registrations and so on. If you want to namespace all at once, use module:
# * :module => the namespace to find controllers (default: "devise", thus
# accessing devise/sessions, devise/registrations, and so on). If you want
# to namespace all at once, use module:
#
# devise_for :users, :module => "users"
#
# Notice that whenever you use namespace in the router DSL, it automatically sets the module.
# So the following setup:
#
# namespace :publisher
# namespace :publisher do
# devise_for :account
# end
#
@@ -135,15 +146,15 @@ module ActionDispatch::Routing
# devise_for :users
# end
#
# However, since Devise uses the request path to retrieve the current user, it has one caveats.
# If you are using a dynamic segment, as below:
# However, since Devise uses the request path to retrieve the current user,
# this has one caveat: If you are using a dynamic segment, like so ...
#
# scope ":locale" do
# devise_for :users
# end
#
# You are required to configure default_url_options in your ApplicationController class level, so
# Devise can pick it:
# you are required to configure default_url_options in your
# ApplicationController class, so Devise can pick it:
#
# class ApplicationController < ActionController::Base
# def self.default_url_options
@@ -207,7 +218,14 @@ module ActionDispatch::Routing
routes = mapping.used_routes
devise_scope mapping.name do
yield if block_given?
if block_given?
ActiveSupport::Deprecation.warn "Passing a block to devise_for is deprecated. " \
"Please remove the block from devise_for (only the block, the call to " \
"devise_for must still exist) and call devise_scope :#{mapping.name} do ... end " \
"with the block instead", caller
yield
end
with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
end
@@ -357,7 +375,10 @@ module ActionDispatch::Routing
path_prefix = "/#{mapping.path}/auth".squeeze("/")
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
raise "You can only add :omniauthable behavior to one Devise model"
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" \
"2) You are setting :omniauthable in more than one model\n" \
"3) You changed your Devise routes/OmniAuth setting and haven't restarted your server"
else
::OmniAuth.config.path_prefix = path_prefix
end
@@ -369,13 +390,13 @@ module ActionDispatch::Routing
end
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
old_as, old_path, old_module, old_constraints, old_defaults, old_options =
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] =
@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

View File

@@ -34,87 +34,4 @@ class Warden::SessionSerializer
end
end
end
end
unless Devise.rack_session?
# We cannot use Rails Indifferent Hash because it messes up the flash object.
class Devise::IndifferentHash < Hash
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
alias_method :regular_update, :update unless method_defined?(:regular_update)
def [](key)
super(convert_key(key))
end
def []=(key, value)
regular_writer(convert_key(key), value)
end
alias_method :store, :[]=
def update(other_hash)
other_hash.each_pair { |key, value| regular_writer(convert_key(key), value) }
self
end
alias_method :merge!, :update
def key?(key)
super(convert_key(key))
end
alias_method :include?, :key?
alias_method :has_key?, :key?
alias_method :member?, :key?
def fetch(key, *extras)
super(convert_key(key), *extras)
end
def values_at(*indices)
indices.collect {|key| self[convert_key(key)]}
end
def merge(hash)
self.dup.update(hash)
end
def delete(key)
super(convert_key(key))
end
def stringify_keys!; self end
def stringify_keys; dup end
undef :symbolize_keys!
def symbolize_keys; to_hash.symbolize_keys end
def to_options!; self end
def to_hash; Hash.new.update(self) end
protected
def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end
end
class ActionDispatch::Request
def reset_session
session.destroy if session && session.respond_to?(:destroy)
self.session = {}
@env['action_dispatch.request.flash_hash'] = nil
end
end
Warden::Manager.after_set_user :event => [:set_user, :authentication] do |record, warden, options|
if options[:scope] && warden.authenticated?(options[:scope])
request, flash = warden.request, warden.env['action_dispatch.request.flash_hash']
backup = request.session.to_hash
backup.delete("session_id")
request.reset_session
warden.env['action_dispatch.request.flash_hash'] = flash
request.session = Devise::IndifferentHash.new.update(backup)
end
end
end

View File

@@ -105,7 +105,7 @@ module Devise
# Helper to decode credentials from HTTP.
def decode_credentials
return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m
ActiveSupport::Base64.decode64($1).split(/:/, 2)
Base64.decode64($1).split(/:/, 2)
end
# Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
@@ -156,4 +156,4 @@ module Devise
end
end
end
end
end

View File

@@ -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,6 +65,8 @@ 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)

View File

@@ -1,3 +1,3 @@
module Devise
VERSION = "2.0.0.rc".freeze
VERSION = "2.0.2".freeze
end

View File

@@ -62,7 +62,7 @@ CONTENT
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Token authenticatable
## Token authenticatable
# t.string :authentication_token
RUBY
end

View File

@@ -1,9 +1,5 @@
class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
<% if ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR >= 1 -%>
def change
<% else -%>
def self.up
<% end -%>
create_table(:<%= table_name %>) do |t|
<%= migration_data -%>
@@ -20,10 +16,4 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
# add_index :<%= table_name %>, :unlock_token, :unique => true
# add_index :<%= table_name %>, :authentication_token, :unique => true
end
<% unless ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR >= 1 -%>
def self.down
drop_table :<%= table_name %>
end
<% end -%>
end

View File

@@ -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__)

View File

@@ -13,6 +13,13 @@ module Devise
public_task :copy_views
end
# TODO: Add this to Rails itslef
module ClassMethods
def hide!
Rails::Generators.hide_namespace self.namespace
end
end
def copy_views
view_directory :confirmations
view_directory :passwords
@@ -32,33 +39,25 @@ 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."
# 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__)
desc "Copies default Devise views to your application."
hide!
end
class SimpleFormForGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../templates/simple_form_for", __FILE__)
desc "Copies simple form enabled views to your application."
hide!
end
class ErbGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../../../app/views/devise", __FILE__)
desc "Copies Devise mail erb views to your application."
hide!
def copy_views
view_directory :mailer
@@ -69,6 +68,7 @@ module Devise
include ViewPathTemplates
source_root File.expand_path("../../templates", __FILE__)
desc "Copies Devise mail markerb views to your application."
hide!
def copy_views
view_directory :markerb, target_path
@@ -80,12 +80,15 @@ 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."
argument :scope, :required => false, :default => nil,
:desc => "The scope to copy views to"
def copy_views
copy_file "_links.erb", "#{target_path}/_links.erb"
end
invoke SharedViewsGenerator
hook_for :form_builder, :aliases => "-b",
:desc => "Form builder to be used",
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"

View File

@@ -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:

View File

@@ -46,9 +46,15 @@ Devise.setup do |config|
config.strip_whitespace_keys = [ :email ]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Basic Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:token]` will
# enable it only for token authentication.
# config.http_authenticatable = false
# If http headers should be returned for AJAX requests. True by default.
@@ -64,6 +70,9 @@ Devise.setup do |config|
# By default Devise will store the user in session. You can skip storage for
# :http_auth and :token_auth by adding those symbols to the array below.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing :skip => :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# ==> Configuration for :database_authenticatable
@@ -192,9 +201,8 @@ Devise.setup do |config|
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The :"*/*" and "*/*" formats below is required to match Internet
# Explorer requests.
# config.navigational_formats = [:"*/*", "*/*", :html]
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ["*/*", :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete

View File

@@ -12,4 +12,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -16,4 +16,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -12,4 +12,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -5,7 +5,7 @@
<div class="inputs">
<%= f.input :email, :required => true, :autofocus => true %>
<%= f.input :password, :hint => "leave it blank if you don't want to change it", :required => false %>
<%= f.input :password, :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>

View File

@@ -14,4 +14,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -12,4 +12,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -12,4 +12,4 @@
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "links" %>

View File

@@ -1,7 +1,6 @@
require 'test_helper'
class MyController < ApplicationController
include Devise::Controllers::InternalHelpers
class MyController < DeviseController
end
class HelpersTest < ActionController::TestCase
@@ -72,19 +71,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

View File

@@ -3,7 +3,9 @@ require 'ostruct'
class FailureTest < ActiveSupport::TestCase
class RootFailureApp < Devise::FailureApp
undef_method :new_user_session_path
def fake_app
Object.new
end
end
def self.context(name, &block)
@@ -41,15 +43,17 @@ class FailureTest < ActiveSupport::TestCase
end
test 'return to the root path if no session path is available' do
call_failure :app => RootFailureApp
assert_equal 302, @response.first
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
assert_equal 'http://test.host/', @response.second['Location']
swap Devise, :router_name => :fake_app do
call_failure :app => RootFailureApp
assert_equal 302, @response.first
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
assert_equal 'http://test.host/', @response.second['Location']
end
end
test 'uses the proxy failure message as symbol' do
call_failure('warden' => OpenStruct.new(:message => :test))
assert_equal 'test', @request.flash[:alert]
call_failure('warden' => OpenStruct.new(:message => :invalid))
assert_equal 'Invalid email or password.', @request.flash[:alert]
assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
end
@@ -73,14 +77,14 @@ class FailureTest < ActiveSupport::TestCase
test 'works for any navigational format' do
swap Devise, :navigational_formats => [:xml] do
call_failure('formats' => :xml)
call_failure('formats' => Mime::XML)
assert_equal 302, @response.first
end
end
test 'redirects the correct format if it is a non-html format request' do
swap Devise, :navigational_formats => [:js] do
call_failure('formats' => :js)
call_failure('formats' => Mime::JS)
assert_equal 'http://test.host/users/sign_in.js', @response.second["Location"]
end
end
@@ -88,18 +92,18 @@ class FailureTest < ActiveSupport::TestCase
context 'For HTTP request' do
test 'return 401 status' do
call_failure('formats' => :xml)
call_failure('formats' => Mime::XML)
assert_equal 401, @response.first
end
test 'return appropriate body for xml' do
call_failure('formats' => :xml)
call_failure('formats' => Mime::XML)
result = %(<?xml version="1.0" encoding="UTF-8"?>\n<errors>\n <error>You need to sign in or sign up before continuing.</error>\n</errors>\n)
assert_equal result, @response.last.body
end
test 'return appropriate body for json' do
call_failure('formats' => :json)
call_failure('formats' => Mime::JSON)
result = %({"error":"You need to sign in or sign up before continuing."})
assert_equal result, @response.last.body
end
@@ -110,26 +114,26 @@ class FailureTest < ActiveSupport::TestCase
end
test 'return WWW-authenticate headers if model allows' do
call_failure('formats' => :xml)
call_failure('formats' => Mime::XML)
assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
end
test 'does not return WWW-authenticate headers if model does not allow' do
swap Devise, :http_authenticatable => false do
call_failure('formats' => :xml)
call_failure('formats' => Mime::XML)
assert_nil @response.second["WWW-Authenticate"]
end
end
test 'works for any non navigational format' do
swap Devise, :navigational_formats => [] do
call_failure('formats' => :html)
call_failure('formats' => Mime::HTML)
assert_equal 401, @response.first
end
end
test 'uses the failure message as response body' do
call_failure('formats' => :xml, 'warden' => OpenStruct.new(:message => :invalid))
call_failure('formats' => Mime::XML, 'warden' => OpenStruct.new(:message => :invalid))
assert_match '<error>Invalid email or password.</error>', @response.third.body
end
@@ -137,7 +141,7 @@ class FailureTest < ActiveSupport::TestCase
context 'when http_authenticatable_on_xhr is false' do
test 'dont return 401 with navigational formats' do
swap Devise, :http_authenticatable_on_xhr => false do
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
assert_equal 302, @response.first
assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
end
@@ -145,7 +149,7 @@ class FailureTest < ActiveSupport::TestCase
test 'dont return 401 with non navigational formats' do
swap Devise, :http_authenticatable_on_xhr => false do
call_failure('formats' => :json, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
call_failure('formats' => Mime::JSON, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
assert_equal 302, @response.first
assert_equal 'http://test.host/users/sign_in.json', @response.second["Location"]
end
@@ -155,14 +159,14 @@ class FailureTest < ActiveSupport::TestCase
context 'when http_authenticatable_on_xhr is true' do
test 'return 401' do
swap Devise, :http_authenticatable_on_xhr => true do
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
assert_equal 401, @response.first
end
end
test 'skip WWW-Authenticate header' do
swap Devise, :http_authenticatable_on_xhr => true do
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
assert_nil @response.second['WWW-Authenticate']
end
end

View File

@@ -8,20 +8,10 @@ if DEVISE_ORM == :active_record
destination File.expand_path("../../tmp", __FILE__)
setup :prepare_destination
test "all files are properly created" do
with_rails_version :MAJOR => 3, :MINOR => 0 do
run_generator %w(monster)
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
assert_migration "db/migrate/devise_create_monsters.rb", /def self\.up/
end
end
test "all files are properly created with rails31 migration syntax" do
with_rails_version :MAJOR => 3, :MINOR => 1 do
run_generator %w(monster)
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
assert_migration "db/migrate/devise_create_monsters.rb", /def change/
end
run_generator %w(monster)
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
assert_migration "db/migrate/devise_create_monsters.rb", /def change/
end
test "update model migration when model exists" do

View File

@@ -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

View File

@@ -407,7 +407,10 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
test 'sign in stub in xml format' do
get new_user_session_path(:format => 'xml')
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>\n <email></email>\n <password nil=\"true\"></password>\n</user>\n", response.body
assert_match '<?xml version="1.0" encoding="UTF-8"?>', response.body
assert_match /<user>.*<\/user>/m, response.body
assert_match '<email></email>', response.body
assert_match '<password nil="true"></password>', response.body
end
test 'sign in stub in json format' do
@@ -432,12 +435,6 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
assert_not warden.authenticated?(:admin)
end
test 'uses the mapping from nested devise_for call' do
sign_in_as_user :visit => "/devise_for/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
test 'sign in with xml format returns xml response' do
create_user
post user_session_path(:format => 'xml'), :user => {:email => "user@test.com", :password => '123456'}

View File

@@ -4,7 +4,7 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
test 'handles unverified requests gets rid of caches but continues signed in' do
swap UsersController, :allow_forgery_protection => true do
create_user
post exhibit_user_url(1), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("user@test.com:123456")}"
post exhibit_user_url(1), {}, "HTTP_AUTHORIZATION" => "Basic #{Base64.encode64("user@test.com:123456")}"
assert warden.authenticated?(:user)
assert_equal "User is authenticated", response.body
end
@@ -74,7 +74,7 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
token = "token_containing_so_many_characters_that_the_base64_encoding_will_wrap"
user = create_user
user.update_attribute :authentication_token, token
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{token}:x")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{Base64.encode64("#{token}:x")}"
assert_response :success
assert_match "<email>user@test.com</email>", response.body
assert warden.authenticated?(:user)
@@ -84,14 +84,14 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
def sign_in_as_new_user_with_http(username="user@test.com", password="123456")
user = create_user
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{Base64.encode64("#{username}:#{password}")}"
user
end
# Sign in with oauth2 token. This is just to test that it isn't misinterpreted as basic authentication
def add_oauth2_header
user = create_user
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "OAuth #{ActiveSupport::Base64.encode64("#{user.email}:123456")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "OAuth #{Base64.encode64("#{user.email}:123456")}"
end
end

View File

@@ -81,7 +81,7 @@ class LockTest < ActionController::IntegrationTest
visit_user_unlock_with_token(user.unlock_token)
assert_current_url "/users/sign_in"
assert_contain 'Your account was successfully unlocked.'
assert_contain 'Your account has been unlocked successfully. Please sign in to continue.'
assert_not user.reload.access_locked?
end
@@ -92,13 +92,6 @@ class LockTest < ActionController::IntegrationTest
assert_not warden.authenticated?(:user)
end
test "user should not be able to sign in when locked" do
user = sign_in_as_user(:locked => true)
assert_template 'sessions/new'
assert_contain 'Your account is locked.'
assert_not warden.authenticated?(:user)
end
test "user should not send a new e-mail if already locked" do
user = create_user(:locked => true)
user.failed_attempts = User.maximum_attempts + 1
@@ -113,10 +106,29 @@ class LockTest < ActionController::IntegrationTest
test 'error message is configurable by resource name' do
store_translations :en, :devise => {
:failure => { :user => { :locked => "You are locked!" } }
:failure => {:user => {:locked => "You are locked!"}}
} do
user = sign_in_as_user(:locked => true)
assert_contain 'You are locked!'
user = create_user(:locked => true)
user.failed_attempts = User.maximum_attempts + 1
user.save!
sign_in_as_user(:password => "invalid")
assert_contain "You are locked!"
end
end
test "user should not be able to sign in when locked" do
store_translations :en, :devise => {
:failure => {:user => {:locked => "You are locked!"}}
} do
user = create_user(:locked => true)
user.failed_attempts = User.maximum_attempts + 1
user.save!
sign_in_as_user(:password => "123456")
assert_contain "You are locked!"
end
end
@@ -157,7 +169,7 @@ class LockTest < ActionController::IntegrationTest
test "when using json to ask a unlock request, should not return the user" do
user = create_user(:locked => true)
post user_unlock_path(:format => "json", :user => {:email => user.email})
post user_unlock_path(:format => "json", :user => {:email => user.email})
assert_response :success
assert_equal response.body, {}.to_json
end

View File

@@ -50,7 +50,7 @@ class RegistrationTest < ActionController::IntegrationTest
test 'a guest user should be able to sign up successfully and be blocked by confirmation' do
user_sign_up
assert_contain 'You have signed up successfully. However, we could not sign you in because your account is unconfirmed.'
assert_contain 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
assert_not_contain 'You have to confirm your account before continuing'
assert_current_url "/"

View File

@@ -41,7 +41,7 @@ class SessionTimeoutTest < ActionController::IntegrationTest
assert_not_nil last_request_at
get users_path
assert_redirected_to new_user_session_path
assert_redirected_to users_path
assert_not warden.authenticated?(:user)
end
@@ -68,7 +68,7 @@ class SessionTimeoutTest < ActionController::IntegrationTest
get expire_user_path(user)
get users_path
assert_redirected_to new_user_session_path
assert_redirected_to users_path
assert_not warden.authenticated?(:user)
end
end
@@ -80,17 +80,31 @@ class SessionTimeoutTest < ActionController::IntegrationTest
user = sign_in_as_user
get expire_user_path(user)
get users_path
get root_path
follow_redirect!
assert_contain 'Session expired!'
end
end
test 'error message with i18n with double redirect' do
store_translations :en, :devise => {
:failure => { :user => { :timeout => 'Session expired!' } }
} do
user = sign_in_as_user
get expire_user_path(user)
get users_path
follow_redirect!
follow_redirect!
assert_contain 'Session expired!'
end
end
test 'time out not triggered if remembered' do
user = sign_in_as_user :remember_me => true
get expire_user_path(user)
assert_not_nil last_request_at
get users_path
assert_response :success
assert warden.authenticated?(:user)

View File

@@ -112,7 +112,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
assert_not_equal user1, user2
visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token)
assert_nil warden.user(:user)
assert_nil warden.user(:user)
end
end
@@ -125,7 +125,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
options[:auth_token] ||= user.authentication_token
if options[:http_auth]
header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
header = "Basic #{Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
else
visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
@@ -145,4 +145,4 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
sign_in_as_new_user_with_token(:user => user)
end
end
end

View File

@@ -36,11 +36,11 @@ class TrackableHooksTest < ActionController::IntegrationTest
assert_equal "127.0.0.1", user.current_sign_in_ip
assert_equal "127.0.0.1", user.last_sign_in_ip
end
test "current remote ip returns original ip behind a non transparent proxy" do
user = create_user
arbitrary_ip = '192.168.1.69'
arbitrary_ip = '200.121.1.69'
sign_in_as_user do
header 'HTTP_X_FORWARDED_FOR', arbitrary_ip
end
@@ -72,7 +72,7 @@ class TrackableHooksTest < ActionController::IntegrationTest
assert_nil user.last_sign_in_at
end
end
test "do not track if devise.skip_trackable is set" do
user = create_user
sign_in_as_user do
@@ -81,7 +81,7 @@ class TrackableHooksTest < ActionController::IntegrationTest
user.reload
assert_equal 0, user.sign_in_count
visit destroy_user_session_path
sign_in_as_user do
header 'devise.skip_trackable', false
end

View File

@@ -238,6 +238,12 @@ class ConfirmableTest < ActiveSupport::TestCase
end
class ReconfirmableTest < ActiveSupport::TestCase
test 'should not worry about validations on confirm even with reconfirmable' do
admin = create_admin
admin.reset_password_token = "a"
assert admin.confirm!
end
test 'should generate confirmation token after changing email' do
admin = create_admin
assert admin.confirm!
@@ -246,6 +252,15 @@ class ReconfirmableTest < ActiveSupport::TestCase
assert_not_nil admin.confirmation_token
end
test 'should regenerate confirmation token after changing email' do
admin = create_admin
assert admin.confirm!
assert admin.update_attributes(:email => 'old_test@example.com')
token = admin.confirmation_token
assert admin.update_attributes(:email => 'new_test@example.com')
assert_not_equal token, admin.confirmation_token
end
test 'should send confirmation instructions by email after changing email' do
admin = create_admin
assert admin.confirm!

View File

@@ -28,6 +28,12 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
assert_equal( { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => "1..10" }, conditions)
end
test "param filter should not convert regular expressions to strings" do
conditions = { "regexp" => /expression/ }
conditions = Devise::ParamFilter.new([], []).filter(conditions)
assert_equal( { "regexp" => /expression/ }, conditions)
end
test 'should respond to password and password confirmation' do
user = new_user
assert user.respond_to?(:password)

View File

@@ -23,6 +23,19 @@ class LockableTest < ActiveSupport::TestCase
assert_equal 0, user.reload.failed_attempts
end
test "should increment failed_attempts on successfull validation if the user is already locked" do
user = create_user
user.confirm!
swap Devise, :maximum_attempts => 2 do
3.times { user.valid_for_authentication?{ false } }
assert user.reload.access_locked?
end
user.valid_for_authentication?{ true }
assert_equal 4, user.reload.failed_attempts
end
test "should not touch failed_attempts if lock_strategy is none" do
user = create_user
user.confirm!

View File

@@ -40,6 +40,6 @@ class User
field :unlock_token, :type => String # Only if unlock strategy is :email or :both
field :locked_at, :type => Time
# Token authenticatable
## Token authenticatable
field :authentication_token, :type => String
end

View File

@@ -12,9 +12,7 @@ Rails.application.routes.draw do
resources :admins, :only => [:index]
# Users scope
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
match "/devise_for/sign_in", :to => "devise/sessions#new"
end
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
as :user do
match "/as/sign_in", :to => "devise/sessions#new"
@@ -64,14 +62,14 @@ Rails.application.routes.draw do
devise_for :accounts, :class_name => "Admin", :path_names => { :sign_in => "get_in" }
end
scope ":locale" do
scope ":locale", :module => :invalid do
devise_for :accounts, :singular => "manager", :class_name => "Admin",
:path_names => {
:sign_in => "login", :sign_out => "logout",
:password => "secret", :confirmation => "verification",
:unlock => "unblock", :sign_up => "register",
:registration => "management", :cancel => "giveup"
}, :failure_app => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["Oops, not found"]] }
}, :failure_app => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["Oops, not found"]] }, :module => :devise
end
namespace :sign_out_via, :module => "devise" do

View File

@@ -36,7 +36,7 @@ class CreateTables < ActiveRecord::Migration
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
# Token authenticatable
## Token authenticatable
t.string :authentication_token
t.timestamps

View File

@@ -7,6 +7,7 @@ module SharedAdmin
:unlock_strategy => :time, :lock_strategy => :none,
:allow_unconfirmed_access_for => 2.weeks, :reconfirmable => true
validates_length_of :reset_password_token, :minimum => 3, :allow_blank => true
validates_uniqueness_of :email, :allow_blank => true, :if => :email_changed?
end

View File

@@ -67,21 +67,4 @@ class ActiveSupport::TestCase
end
end
end
def with_rails_version(constants)
saved_constants = {}
constants.each do |constant, val|
saved_constants[constant] = ::Rails::VERSION.const_get constant
Kernel::silence_warnings { ::Rails::VERSION.const_set(constant, val) }
end
begin
yield
ensure
constants.each do |constant, val|
Kernel::silence_warnings { ::Rails::VERSION.const_set(constant, saved_constants[constant]) }
end
end
end
end