Compare commits

...

61 Commits

Author SHA1 Message Date
José Valim
0efcba3627 Release v3.1.1 2013-10-01 17:11:42 +02:00
José Valim
07e77eb4b3 Make it clear a restart is required when setting the secret key 2013-10-01 17:10:42 +02:00
Greg Gates
e3d0a2ba45 Tweaks confirmation flow for signed_in users
For #2627

When allow_unconfirmed_access_for > 0, users may
be already signed in at the time they confirm
their account. Consequently, the default
confirmation should be compatible with this
possibility. Additionally, they should not be
redirected to the sign in form after confirmation
in this case. So I've changed
ConfirmationsController#after_confirmation_path_for
to send the user to the root path when signed in,
or the sign in form otherwise.

Conflicts:
	app/controllers/devise/confirmations_controller.rb
	config/locales/en.yml
2013-10-01 17:00:27 +02:00
José Valim
08edcc10fe Release 3.1.0 2013-09-02 19:02:48 -03:00
José Valim
2d919fba32 Merge pull request #2582 from tod-uma/master
Allowed updating of attributes without a password if password_required? resolves to false.
2013-09-02 14:46:08 -07:00
José Valim
843168d5c7 Merge pull request #2605 from sekrett/master
Handle nil failed_attempts
2013-09-02 04:44:48 -07:00
Alexander Zubkov
095572b6fd Add nulls to migration generator 2013-09-02 15:00:12 +04:00
Alexander Zubkov
b9112d4308 Handle nil failed_attempts 2013-09-02 14:48:19 +04:00
Vasiliy Ermolovich
23c5517009 add test for fc251c306c 2013-08-31 15:25:49 +03:00
José Valim
32e60fade5 Merge pull request #2604 from gregates/revise_locale_messages
Fixes incorrect flash message on confirmation
2013-08-31 02:49:02 -07:00
Greg Gates
fc251c306c Fixes incorrect flash message on confirmation
The :confirmed default message in devise.en.yml
used to say "You are now signed in." This is no
longer the default behavior in v3.1.0.

This commit renames that message to
:confirmed_and_signed_in and changes the :confirmed
message to be appropriate for the default post-
confirmation location (which is now the new session
page). The new :confirmed message reads:

"Your account was successfully confirmed. Please
sign in."
2013-08-30 17:16:56 -04:00
Rafael Mendonça França
f6a74e90e5 Merge pull request #2603 from rwz/patch-1
Consistent single quotes in devise.rb generator
2013-08-30 09:28:43 -07:00
Pavel Pravosud
91f2bce08e Consistent single quotes in devise.rb generator 2013-08-30 22:21:12 +07:00
Rafael Mendonça França
5e81210400 Merge pull request #2601 from theodorton/patch-1
Typo
2013-08-30 07:39:27 -07:00
Theodor Tonum
4b7fcac23a Typo 2013-08-30 16:38:34 +02:00
José Valim
213ed81641 Update CHANGELOG.md 2013-08-27 07:05:54 -03:00
José Valim
3232d14b20 token authenticatable mentions 2013-08-21 17:33:38 +02:00
José Valim
949c9e5ded Remove gem version from README (because it doesn't work when branched) 2013-08-21 17:30:01 +02:00
Tod Detre
66c829eef4 created update_resource method to allow subclass overwritting 2013-08-21 11:04:32 -04:00
Tod Detre
6a22e88dfa Allowed updating of attributes without a password if password_required? resolves to false 2013-08-20 16:36:35 -04:00
José Valim
605924a921 Add a test related to remember token generation 2013-08-19 20:48:36 +02:00
José Valim
72c3472fe1 Generate remember token 2013-08-19 20:33:21 +02:00
José Valim
ea870e0636 Credit where credit is due [ci skip] 2013-08-18 10:46:00 +02:00
José Valim
3f00d735a4 Mention the security announcement [ci skip] 2013-08-18 10:17:51 +02:00
José Valim
1437ae2ce3 Release v3.1.0.rc2 2013-08-18 10:13:53 +02:00
Andri Möll
052cbef205 Don't confirm email after password reset.
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2013-08-18 10:13:35 +02:00
José Valim
b1754074e5 Only raise on missing secret key after a route is defined 2013-08-18 09:55:05 +02:00
José Valim
e8b70bb04d Include registration on docs 2013-08-17 09:19:28 +02:00
José Valim
58cbd91512 Do not do double redirect on after confirmation path 2013-08-13 18:55:50 +02:00
Carlos Antonio da Silva
177ed8a356 Bump up lock dependencies 2013-08-13 13:43:40 -03:00
Carlos Antonio da Silva
a5e63d7a28 Update Gemfile.lock with new Devise version
Also bump master with latest mongoid
2013-08-13 13:43:21 -03:00
José Valim
5ecbbdf260 Update version.rb 2013-08-13 18:22:19 +02:00
José Valim
efe34219a9 Fix the build on Rails 3.2 2013-08-12 15:36:41 +02:00
José Valim
bc0cab8d60 Update README.md
Remove unnecessary maintainers list
2013-08-12 15:25:44 +02:00
José Valim
7e855eddef Credit where credit is due 2013-08-11 22:30:19 +02:00
José Valim
8541c465d7 Convert CHANGELOG to markdown 2013-08-11 22:20:59 +02:00
José Valim
4e318b5167 Simplify parameter sanitization proposal 2013-08-11 22:20:59 +02:00
Alex Peattie
5e7caffc9e Extend params sanitizer, to make it easier to add/remove permitted params
- Move the default permitted parameters into ParameterSanitizer::PermittedParameters
- Add devise_permitted_parameters helper
- devise_permitted_parameters.add to add permitted parameters
- devise_permitted_parameters.remove to remove Devise's defaults
- devise_permitted_parameters.for to access the parameters for a given action
- Update 'Strong Parameters' section of README

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2013-08-11 22:20:59 +02:00
José Valim
87edf0fbcf Merge pull request #2564 from glebm/doc-confirmable-fix
fix doc typo
2013-08-09 23:49:44 -07:00
Gleb Mazovetskiy
e7de0d4c4c fix doc typo 2013-08-10 04:43:25 +02:00
José Valim
2a8d0f9bee Update CHANGELOG 2013-08-09 10:30:29 +02:00
José Valim
4681f81ce6 Document the :store option for sign in 2013-08-09 08:37:27 +02:00
José Valim
86f2696b84 Merge pull request #2529 from papercavalier/lang-edit
Grammar
2013-08-08 13:39:50 -07:00
José Valim
20cf73facf Merge pull request #2549 from joaomilho/master
Using urlsafe_base64 cause it already handle url sensitive chars, keepin...
2013-08-08 13:38:05 -07:00
José Valim
d0219d914f Merge pull request #2560 from aarvay/patch-1
Added an extra validation to shared links
2013-08-08 13:37:45 -07:00
José Valim
50d17bbb8e Update CHANGELOG 2013-08-08 22:37:15 +02:00
José Valim
3dccf3c6ff Do not sign in after confirmation 2013-08-08 22:33:58 +02:00
Vignesh Rajagopalan
acd33174fc Added an extra validation to shared links 2013-08-08 18:05:19 +05:30
José Valim
d56641f514 Move to SHA256 2013-08-06 12:14:51 +02:00
José Valim
354e5022bf Only allow insecure token lookup if a flag is given 2013-08-06 11:55:13 +02:00
José Valim
3cdbf15fe9 Update OTHER lock 2013-08-05 19:24:04 +02:00
José Valim
143794d701 Use HMAC on tokens stored in the DB 2013-08-05 18:56:07 +02:00
Juan Lulkin
4048545151 Using urlsafe_base64 cause it already handle url sensitive chars, keeping the replacement of the confusing chars, though 2013-08-05 14:54:56 +03:00
José Valim
32648027e2 Add Devise::KeyGenerator 2013-08-05 11:47:36 +02:00
José Valim
7e96bac6a4 Get rid of deprecated code 2013-08-05 11:24:04 +02:00
José Valim
f5a77ac598 Skip storage for cookies on unverified requests 2013-08-05 10:24:11 +02:00
José Valim
591f4a97f7 Update the OTHER gemfile 2013-08-02 23:57:43 +02:00
José Valim
cf1989e1da Update Gemfile.lock 2013-08-02 23:43:07 +02:00
hakanensari
9a60415e2e Fix assertion 2013-07-26 19:31:49 +01:00
hakanensari
b861a65e72 Fix run-on sentence 2013-07-26 14:24:19 +01:00
hakanensari
1ab7792beb Fix grammar 2013-07-26 14:24:13 +01:00
62 changed files with 668 additions and 565 deletions

View File

@@ -1,5 +1,41 @@
== 3.1.1
* bug fix
* Improve default message which asked users to sign in even when they were already signed (by @gregates)
* Improve error message for when the `config.secret_key` is missing
== 3.1.0
Security announcement: http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/
* backwards incompatible changes
* Do not store confirmation, unlock and reset password tokens directly in the database. This means tokens previously stored in the database are no longer valid. You can reenable this temporarily by setting `config.allow_insecure_tokens_lookup = true` in your configuration file. It is recommended to keep this configuration set to true just temporarily in your production servers only to aid migration
* The Devise mailer and its views were changed to explicitly receive a token argument as `@token`. You will need to update your mailers and re-copy the views to your application with `rails g devise:views`
* Sanitization of parameters should be done by calling `devise_parameter_sanitizer.sanitize(:action)` instead of `devise_parameter_sanitizer.for(:action)`
* deprecations
* Token authentication is deprecated
* enhancements
* Better security defaults
* Allow easier customization of parameter sanitizer (by @alexpeattie)
* bug fix
* Do not confirm e-mail after password reset (by @moll)
* Do not sign in after confirmation
* Do not store confirmation, unlock and reset password tokens directly in the database
* Do not compare directly against confirmation, unlock and reset password tokens
* Skip storage for cookies on unverified requests
== 3.0.2
* bug fix
* Skip storage for cookies on unverified requests
== 3.0.1
Security announcement: http://blog.plataformatec.com.br/2013/08/csrf-token-fixation-attacks-in-devise/
* enhancements
* Add after_confirmation callback
@@ -12,11 +48,14 @@
* enhancements
* Rails 4 and Strong Parameters compatibility (by @carlosantoniodasilva, @josevalim, @latortuga, @lucasmazza, @nashby, @rafaelfranca, @spastorino)
* Drop support for Rails < 3.2 and Ruby < 1.9.3
* Enable to skip sending reconfirmation email when reconfirmable is on and skip_confirmation_notification! is invoked (by @tkhr)
* Enable to skip sending reconfirmation email when reconfirmable is on and `skip_confirmation_notification!` is invoked (by @tkhr)
* bug fix
* Errors on unlock are now properly reflected on the first `unlock_keys`
* backwards incompatible changes
* Changes on session storage will expire all existing sessions on upgrade
== 2.2.4
* enhancements
@@ -633,7 +672,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Added Registerable
* Added Http Basic Authentication support
* Allow scoped_views to be customized per controller/mailer class
* [#99] Allow authenticatable to used in change_table statements
* Allow authenticatable to used in change_table statements
== 0.9.2
@@ -773,19 +812,19 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Added DataMapper support
* Remove store_location from authenticatable strategy and add it to failure app
* Allow a strategy to be placed after authenticatable
* [#45] Do not rely attribute? methods, since they are not added on Datamapper
* Do not rely attribute? methods, since they are not added on Datamapper
== 0.5.6
* enhancements
* [#42] Do not send nil to build (DataMapper compatibility)
* [#44] Allow to have scoped views
* Do not send nil to build (DataMapper compatibility)
* Allow to have scoped views
== 0.5.5
* enhancements
* Allow overwriting find for authentication method
* [#38] Remove Ruby 1.8.7 dependency
* Remove Ruby 1.8.7 dependency
== 0.5.4
@@ -793,7 +832,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Deprecate :singular in devise_for and use :scope instead
* enhancements
* [#37] Create after_sign_in_path_for and after_sign_out_path_for hooks to be
* Create after_sign_in_path_for and after_sign_out_path_for hooks to be
overwriten in ApplicationController
* Create sign_in_and_redirect and sign_out_and_redirect helpers
* Warden::Manager.default_scope is automatically configured to the first given scope
@@ -805,7 +844,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Ensure all controllers are unloadable
* enhancements
* [#35] Moved friendly_token to Devise
* Moved friendly_token to Devise
* Added Devise.all, so you can freeze your app strategies
* Added Devise.apply_schema, so you can turn it to false in Datamapper or MongoMapper
in cases you don't want it be handlded automatically
@@ -813,9 +852,9 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.5.2
* enhancements
* [#28] Improved sign_in and sign_out helpers to accepts resources
* [#28] Added stored_location_for as a helper
* [#20] Added test helpers
* Improved sign_in and sign_out helpers to accepts resources
* Added stored_location_for as a helper
* Added test helpers
== 0.5.1
@@ -836,7 +875,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.4.3
* bug fix
* [#29] Authentication just fails if user cannot be serialized from session, without raising errors;
* Authentication just fails if user cannot be serialized from session, without raising errors;
* Default configuration values should not overwrite user values;
== 0.4.2
@@ -854,7 +893,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.4.1
* bug fix
* [#21] Ensure options can be set even if models were not loaded
* Ensure options can be set even if models were not loaded
== 0.4.0
@@ -865,25 +904,25 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* :authenticable calls are deprecated, use :authenticatable instead
* enhancements
* [#16] Allow devise to be more agnostic and do not require ActiveRecord to be loaded
* Allow devise to be more agnostic and do not require ActiveRecord to be loaded
* Allow Warden::Manager to be configured through Devise
* Created a generator which creates an initializer
== 0.3.0
* bug fix
* [#15] Allow yml messages to be configured by not using engine locales
* Allow yml messages to be configured by not using engine locales
* deprecations
* Renamed confirm_in to confirm_within
* [#14] Do not send confirmation messages when user changes his e-mail
* [#13] Renamed authenticable to authenticatable and added deprecation warnings
* Do not send confirmation messages when user changes his e-mail
* Renamed authenticable to authenticatable and added deprecation warnings
== 0.2.3
* enhancements
* Ensure fail! works inside strategies
* [#12] Make unauthenticated message (when you haven't signed in) different from invalid message
* Make unauthenticated message (when you haven't signed in) different from invalid message
* bug fix
* Do not redirect on invalid authenticate
@@ -892,7 +931,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
== 0.2.2
* bug fix
* [#9] Fix a bug when using customized resources
* Fix a bug when using customized resources
== 0.2.1
@@ -900,17 +939,17 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Clean devise_views generator to use devise existing views
* enhancements
* [#7] Create instance variables (like @user) for each devise controller
* Create instance variables (like @user) for each devise controller
* Use Devise::Controller::Helpers only internally
* bug fix
* [#6] Fix a bug with Mongrel and Ruby 1.8.6
* Fix a bug with Mongrel and Ruby 1.8.6
== 0.2.0
* enhancements
* [#4] Allow option :null => true in authenticable migration
* [#3] Remove attr_accessible calls from devise modules
* Allow option :null => true in authenticable migration
* Remove attr_accessible calls from devise modules
* Customizable time frame for rememberable with :remember_for config
* Customizable time frame for confirmable with :confirm_in config
* Generators for creating a resource and copy views
@@ -919,12 +958,12 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
* Do not load hooks or strategies if they are not used
* bug fixes
* [#2] Fixed requiring devise strategies
* Fixed requiring devise strategies
== 0.1.1
* bug fixes
* [#1] Fixed requiring devise mapping
* Fixed requiring devise mapping
== 0.1.0

View File

@@ -1,21 +1,22 @@
GIT
remote: git://github.com/mongoid/mongoid.git
revision: fe7f43430580860db6d1d89cea27eda24ab60ab1
revision: 346a79a7d01aa194de80e649916239a18d38ce13
branch: master
specs:
mongoid (4.0.0)
activemodel (~> 4.0.0.rc1)
moped (~> 1.4.2)
activemodel (~> 4.0.0)
moped (~> 1.5)
origin (~> 1.0)
tzinfo (~> 0.3.22)
PATH
remote: .
specs:
devise (3.0.0)
devise (3.1.1)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
thread_safe (~> 0.1)
warden (~> 1.2.3)
GEM
@@ -46,17 +47,17 @@ GEM
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
arel (4.0.0)
atomic (1.1.10)
bcrypt-ruby (3.1.1)
atomic (1.1.12)
bcrypt-ruby (3.1.2)
builder (3.1.4)
erubis (2.7.0)
faraday (0.8.7)
multipart-post (~> 1.1)
faraday (0.8.8)
multipart-post (~> 1.2.0)
hashie (1.2.0)
hike (1.2.3)
httpauth (0.2.0)
i18n (0.6.4)
json (1.7.7)
i18n (0.6.5)
json (1.8.0)
jwt (0.1.8)
multi_json (>= 1.5)
mail (2.5.4)
@@ -67,8 +68,8 @@ GEM
minitest (4.7.5)
mocha (0.13.3)
metaclass (~> 0.0.1)
moped (1.4.5)
multi_json (1.7.7)
moped (1.5.1)
multi_json (1.7.9)
multipart-post (1.2.0)
nokogiri (1.5.9)
oauth2 (0.8.1)
@@ -125,7 +126,7 @@ GEM
sprockets (~> 2.8)
sqlite3 (1.3.7)
thor (0.18.1)
thread_safe (0.1.0)
thread_safe (0.1.2)
atomic
tilt (1.4.1)
treetop (1.4.14)

View File

@@ -2,7 +2,6 @@
By [Plataformatec](http://plataformatec.com.br/).
[![Gem Version](https://fury-badge.herokuapp.com/rb/devise.png)](http://badge.fury.io/rb/devise)
[![Build Status](https://api.travis-ci.org/plataformatec/devise.png?branch=master)](http://travis-ci.org/plataformatec/devise)
[![Code Climate](https://codeclimate.com/github/plataformatec/devise.png)](https://codeclimate.com/github/plataformatec/devise)
@@ -15,10 +14,9 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
* Allows you to have multiple models signed in at the same time;
* Is based on a modularity concept: use just what you really need.
It's composed of 11 modules:
It's composed of 10 modules:
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
* [Token Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable): signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://github.com/intridea/omniauth) support;
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
@@ -188,7 +186,7 @@ There are just three actions in Devise that allows any set of parameters to be p
* `sign_up` (`Devise::RegistrationsController#create`) - Permits authentication keys plus `password` and `password_confirmation`
* `account_update` (`Devise::RegistrationsController#update`) - Permits authentication keys plus `password`, `password_confirmation` and `current_password`
In case you want to customize the permitted parameters (the lazy way™) you can do with a simple before filter in your `ApplicationController`:
In case you want to permit additional parameters (the lazy way™) you can do with a simple before filter in your `ApplicationController`:
```ruby
class ApplicationController < ActionController::Base
@@ -197,11 +195,19 @@ class ApplicationController < ActionController::Base
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
```
To completely change Devise defaults or invoke custom behaviour, you can also pass a block:
```ruby
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
end
```
If you have multiple Devise models, you may want to set up different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and add your own logic:
```ruby
@@ -252,7 +258,7 @@ rails generate devise:views users
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`:
1. Create your custom controller, for example a `Admins::SessionsController`:
```ruby
class Admins::SessionsController < Devise::SessionsController
@@ -441,12 +447,6 @@ We have a long list of valued contributors. Check them all at:
https://github.com/plataformatec/devise/contributors
### Maintainers
* José Valim (https://github.com/josevalim)
* Carlos Antônio da Silva (https://github.com/carlosantoniodasilva)
* Rodrigo Flores (https://github.com/rodrigoflores)
## License
MIT License. Copyright 2009-2013 Plataformatec. http://plataformatec.com.br

View File

@@ -20,8 +20,12 @@ class Devise::ConfirmationsController < DeviseController
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
if Devise.allow_insecure_sign_in_after_confirmation
set_flash_message(:notice, :confirmed_and_signed_in) if is_navigational_format?
sign_in(resource_name, resource)
else
set_flash_message(:notice, :confirmed) if is_navigational_format?
end
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
@@ -37,6 +41,12 @@ class Devise::ConfirmationsController < DeviseController
# The path used after confirmation.
def after_confirmation_path_for(resource_name, resource)
after_sign_in_path_for(resource)
if Devise.allow_insecure_sign_in_after_confirmation
after_sign_in_path_for(resource)
elsif signed_in?
signed_in_root_path(resource)
else
new_session_path(resource_name)
end
end
end

View File

@@ -40,7 +40,7 @@ class Devise::RegistrationsController < DeviseController
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if resource.update_with_password(account_update_params)
if update_resource(resource, account_update_params)
if is_navigational_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
@@ -80,6 +80,12 @@ class Devise::RegistrationsController < DeviseController
previous != resource.unconfirmed_email
end
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
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)
@@ -117,10 +123,10 @@ class Devise::RegistrationsController < DeviseController
end
def sign_up_params
devise_parameter_sanitizer.for(:sign_up)
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.for(:account_update)
devise_parameter_sanitizer.sanitize(:account_update)
end
end

View File

@@ -35,7 +35,7 @@ class Devise::SessionsController < DeviseController
protected
def sign_in_params
devise_parameter_sanitizer.for(:sign_in)
devise_parameter_sanitizer.sanitize(:sign_in)
end
def serialize_options(resource)

View File

@@ -1,15 +1,18 @@
class Devise::Mailer < Devise.parent_mailer.constantize
include Devise::Mailers::Helpers
def confirmation_instructions(record, opts={})
def confirmation_instructions(record, token, opts={})
@token = token
devise_mail(record, :confirmation_instructions, opts)
end
def reset_password_instructions(record, opts={})
def reset_password_instructions(record, token, opts={})
@token = token
devise_mail(record, :reset_password_instructions, opts)
end
def unlock_instructions(record, opts={})
def unlock_instructions(record, token, opts={})
@token = token
devise_mail(record, :unlock_instructions, opts)
end
end

View File

@@ -1,3 +0,0 @@
<% ActiveSupport::Deprecation.warn "Rendering partials devise/_links.erb is deprecated" \
"please use devise/shared/_links.erb instead."%>
<%= render "shared/links" %>

View File

@@ -2,4 +2,4 @@
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %></p>

View File

@@ -2,7 +2,7 @@
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p>
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>

View File

@@ -4,4 +4,4 @@
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %></p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @token) %></p>

View File

@@ -6,7 +6,7 @@
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>
@@ -22,4 +22,4 @@
<%- 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 -%>
<% end -%>

View File

@@ -3,17 +3,18 @@
en:
devise:
confirmations:
confirmed: "Your account was successfully confirmed. You are now signed in."
confirmed: "Your account was successfully confirmed."
confirmed_and_signed_in: "Your account was successfully confirmed. You are now signed in."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account was not activated yet."
inactive: "Your account is not activated yet."
invalid: "Invalid email or password."
invalid_token: "Invalid authentication token."
locked: "Your account is locked."
not_found_in_database: "Invalid email or password."
timeout: "Your session expired, please sign in again to continue."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your account before continuing."
mailer:

View File

@@ -22,5 +22,6 @@ Gem::Specification.new do |s|
s.add_dependency("warden", "~> 1.2.3")
s.add_dependency("orm_adapter", "~> 0.1")
s.add_dependency("bcrypt-ruby", "~> 3.0")
s.add_dependency("thread_safe", "~> 0.1")
s.add_dependency("railties", ">= 3.2.6", "< 5")
end

View File

@@ -1,21 +1,22 @@
PATH
remote: ..
specs:
devise (3.0.0)
devise (3.1.1)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
thread_safe (~> 0.1)
warden (~> 1.2.3)
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
actionmailer (3.2.14)
actionpack (= 3.2.14)
mail (~> 2.5.4)
actionpack (3.2.14)
activemodel (= 3.2.14)
activesupport (= 3.2.14)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
@@ -23,49 +24,49 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
activemodel (3.2.14)
activesupport (= 3.2.14)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activerecord (3.2.14)
activemodel (= 3.2.14)
activesupport (= 3.2.14)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
activeresource (3.2.14)
activemodel (= 3.2.14)
activesupport (= 3.2.14)
activesupport (3.2.14)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
arel (3.0.2)
bcrypt-ruby (3.1.1)
atomic (1.1.13)
bcrypt-ruby (3.1.2)
builder (3.0.4)
erubis (2.7.0)
faraday (0.8.7)
multipart-post (~> 1.1)
faraday (0.8.8)
multipart-post (~> 1.2.0)
hashie (1.2.0)
hike (1.2.2)
hike (1.2.3)
httpauth (0.2.0)
i18n (0.6.1)
i18n (0.6.5)
journey (1.0.4)
json (1.7.7)
json (1.8.0)
jwt (0.1.8)
multi_json (>= 1.5)
mail (2.5.3)
i18n (>= 0.4.0)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metaclass (0.0.1)
mime-types (1.23)
mocha (0.13.3)
metaclass (~> 0.0.1)
mongoid (3.1.3)
mongoid (3.1.4)
activemodel (~> 3.2)
moped (~> 1.4.2)
moped (~> 1.4)
origin (~> 1.0)
tzinfo (~> 0.3.22)
moped (1.4.5)
multi_json (1.7.3)
moped (1.5.1)
multi_json (1.7.9)
multipart-post (1.2.0)
nokogiri (1.5.9)
oauth2 (0.8.1)
@@ -98,22 +99,22 @@ GEM
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
rails (3.2.14)
actionmailer (= 3.2.14)
actionpack (= 3.2.14)
activerecord (= 3.2.14)
activeresource (= 3.2.14)
activesupport (= 3.2.14)
bundler (~> 1.0)
railties (= 3.2.13)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
railties (= 3.2.14)
railties (3.2.14)
actionpack (= 3.2.14)
activesupport (= 3.2.14)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.0.4)
rake (10.1.0)
rdoc (3.12.2)
json (~> 1.4)
ruby-openid (2.2.3)
@@ -124,8 +125,10 @@ GEM
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.7)
thor (0.18.1)
tilt (1.4.0)
treetop (1.4.12)
thread_safe (0.1.2)
atomic
tilt (1.4.1)
treetop (1.4.14)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.37)

View File

@@ -14,6 +14,7 @@ module Devise
autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
autoload :TestHelpers, 'devise/test_helpers'
autoload :TimeInflector, 'devise/time_inflector'
autoload :TokenGenerator, 'devise/token_generator'
module Controllers
autoload :Helpers, 'devise/controllers/helpers'
@@ -45,6 +46,20 @@ module Devise
# True values used to check params
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
# Secret key used by the key generator
mattr_accessor :secret_key
@@secret_key = nil
# Allow insecure token lookup. Must be used
# temporarily just for migration.
mattr_accessor :allow_insecure_token_lookup
@@allow_insecure_tokens_lookup = false
# Allow insecure sign in after confirmation. Must be used
# temporarily just for migration.
mattr_accessor :allow_insecure_sign_in_after_confirmation
@@allow_insecure_sign_in_after_confirmation = false
# Custom domain or key for cookies. Not set by default
mattr_accessor :rememberable_options
@@rememberable_options = {}
@@ -227,18 +242,6 @@ module Devise
mattr_accessor :clean_up_csrf_token_on_authentication
@@clean_up_csrf_token_on_authentication = true
def self.encryptor=(value)
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
end
def self.use_salt_as_remember_token=(value)
warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
end
def self.apply_schema=(value)
warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
end
# PRIVATE CONFIGURATION
# Store scopes mappings.
@@ -263,6 +266,10 @@ module Devise
mattr_accessor :paranoid
@@paranoid = false
# Stores the token generator
mattr_accessor :token_generator
@@token_generator = nil
# Default way to setup Devise. Run rails generate devise_install to create
# a fresh initializer with all configuration values.
def self.setup
@@ -451,7 +458,7 @@ module Devise
# Generate a friendly string randomly to be used as token.
def self.friendly_token
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
end
# constant-time comparison algorithm to prevent timing attacks

View File

@@ -117,6 +117,7 @@ module Devise
# sign_in :user, @user # sign_in(scope, resource)
# sign_in @user # sign_in(resource)
# sign_in @user, :event => :authentication # sign_in(resource, options)
# sign_in @user, :store => false # sign_in(resource, options)
# sign_in @user, :bypass => true # sign_in(resource, options)
#
def sign_in(resource_or_scope, *args)

View File

@@ -21,6 +21,7 @@ module Devise
# Remembers the given resource by setting up a cookie
def remember_me(resource)
return if env["devise.skip_storage"]
scope = Devise::Mapping.find_scope!(resource)
resource.remember_me!(resource.extend_remember_period)
cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)

View File

@@ -2,6 +2,6 @@
# This is only triggered when the user is explicitly set (with set_user)
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.zero?
record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
end
end

View File

@@ -1,6 +1,7 @@
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
scope = options[:scope]
if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
if record.respond_to?(:remember_me) && options[:store] != false &&
record.remember_me && warden.authenticated?(scope)
Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
end
end

View File

@@ -35,12 +35,6 @@ module Devise
:template_name => action
}.merge(opts)
if resource.respond_to?(:headers_for)
ActiveSupport::Deprecation.warn "Calling headers_for in the model is no longer supported. " <<
"Please customize your mailer instead."
headers.merge!(resource.headers_for(action))
end
@email = headers[:to]
headers
end

View File

@@ -56,14 +56,8 @@ module Devise
klass.devise_modules.each do |mod|
constant = const_get(mod.to_s.classify)
if constant.respond_to?(:required_fields)
constant.required_fields(klass).each do |field|
failed_attributes << field unless instance.respond_to?(field)
end
else
ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
"Devise uses required_fields to warn developers of any missing fields in their models. " \
"Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
constant.required_fields(klass).each do |field|
failed_attributes << field unless instance.respond_to?(field)
end
end
@@ -89,11 +83,13 @@ module Devise
devise_modules_hook! do
include Devise::Models::Authenticatable
selected_modules.each do |m|
if m == :encryptable && !(defined?(Devise::Models::Encryptable))
warn "[DEVISE] You're trying to include :encryptable in your model but it is not bundled with the Devise gem anymore. Please add `devise-encryptable` to your Gemfile to proceed.\n"
end
if selected_modules.include?(:token_authenticatable)
ActiveSupport::Deprecation.warn "devise :token_authenticatable is deprecated. " \
"Please check Devise 3.1 release notes for more information on how to upgrade."
end
selected_modules.each do |m|
mod = Devise::Models.const_get(m.to_s.classify)
if mod.const_defined?("ClassMethods")

View File

@@ -144,20 +144,20 @@ module Devise
#
# protected
#
# def send_devise_notification(notification, opts = {})
# # if the record is new or changed then delay the
# def send_devise_notification(notification, *args)
# # If the record is new or changed then delay the
# # delivery until the after_commit callback otherwise
# # send now because after_commit will not be called.
# if new_record? || changed?
# pending_notifications << [notification, opts]
# pending_notifications << [notification, args]
# else
# devise_mailer.send(notification, self, opts).deliver
# devise_mailer.send(notification, self, *args).deliver
# end
# end
#
# def send_pending_notifications
# pending_notifications.each do |n, opts|
# devise_mailer.send(n, self, opts).deliver
# pending_notifications.each do |notification, args|
# devise_mailer.send(notification, self, *args).deliver
# end
#
# # Empty the pending notifications array because the
@@ -171,8 +171,8 @@ module Devise
# end
# end
#
def send_devise_notification(notification, opts={})
devise_mailer.send(notification, self, opts).deliver
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver
end
def downcase_keys
@@ -279,14 +279,6 @@ module Devise
def devise_parameter_filter
@devise_parameter_filter ||= Devise::ParameterFilter.new(case_insensitive_keys, strip_whitespace_keys)
end
# Generate a token by looping and ensuring does not already exist.
def generate_token(column)
loop do
token = Devise.friendly_token
break token unless to_adapter.find_first({ column => token })
end
end
end
end
end

View File

@@ -7,7 +7,7 @@ module Devise
#
# == Options
#
# Confirmable adds the following options to devise_for:
# Confirmable adds the following options to +devise+:
#
# * +allow_unconfirmed_access_for+: the time you want to allow the user to access his account
# before confirming it. After this period, the user access is denied. You can
@@ -40,9 +40,10 @@ module Devise
end
def initialize(*args, &block)
@bypass_postpone = false
@bypass_confirmation_postpone = false
@reconfirmation_required = false
@skip_confirmation_notification = false
@raw_confirmation_token = nil
super
end
@@ -93,10 +94,12 @@ module Devise
# Send confirmation instructions by email
def send_confirmation_instructions
ensure_confirmation_token!
unless @raw_confirmation_token
generate_confirmation_token!
end
opts = pending_reconfirmation? ? { :to => unconfirmed_email } : { }
send_devise_notification(:confirmation_instructions, opts)
send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
end
def send_reconfirmation_instructions
@@ -109,17 +112,11 @@ module Devise
# Resend confirmation token.
# Regenerates the token if the period is expired.
def resend_confirmation_token
def resend_confirmation_instructions
pending_any_confirmation do
regenerate_confirmation_token! if confirmation_period_expired?
send_confirmation_instructions
end
end
# Generate a confirmation token unless already exists and save the record.
def ensure_confirmation_token!
generate_confirmation_token! if should_generate_confirmation_token?
end
# Overwrites active_for_authentication? for confirmation
# by verifying whether a user is active to sign in or not. If the user
@@ -149,19 +146,16 @@ module Devise
# If you don't want reconfirmation to be sent, neither a code
# to be generated, call skip_reconfirmation!
def skip_reconfirmation!
@bypass_postpone = true
@bypass_confirmation_postpone = true
end
protected
def should_generate_confirmation_token?
confirmation_token.nil? || confirmation_period_expired?
end
# 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
send_devise_notification(:confirmation_instructions)
send_confirmation_instructions
end
# Callback to overwrite if confirmation is required or not.
@@ -221,10 +215,12 @@ module Devise
end
end
# Generates a new random token for confirmation, and stores the time
# this token is being generated
# Generates a new random token for confirmation, and stores
# the time this token is being generated
def generate_confirmation_token
self.confirmation_token = self.class.confirmation_token
raw, enc = Devise.token_generator.generate(self.class, :confirmation_token)
@raw_confirmation_token = raw
self.confirmation_token = enc
self.confirmation_sent_at = Time.now.utc
end
@@ -232,30 +228,16 @@ module Devise
generate_confirmation_token && save(:validate => false)
end
# Regenerates a new token.
def regenerate_confirmation_token
generate_confirmation_token
end
def regenerate_confirmation_token!
regenerate_confirmation_token && save(:validate => false)
end
def after_password_reset
super
confirm! unless confirmed?
end
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
@reconfirmation_required = true
self.unconfirmed_email = self.email
self.email = self.email_was
regenerate_confirmation_token
generate_confirmation_token
end
def postpone_email_change?
postpone = self.class.reconfirmable && email_changed? && !@bypass_postpone && !self.email.blank?
@bypass_postpone = false
postpone = self.class.reconfirmable && email_changed? && !@bypass_confirmation_postpone && !self.email.blank?
@bypass_confirmation_postpone = false
postpone
end
@@ -280,7 +262,7 @@ module Devise
unless confirmable.try(:persisted?)
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
end
confirmable.resend_confirmation_token if confirmable.persisted?
confirmable.resend_confirmation_instructions if confirmable.persisted?
confirmable
end
@@ -289,14 +271,17 @@ module Devise
# If the user is already confirmed, create an error for the user
# Options must have the confirmation_token
def confirm_by_token(confirmation_token)
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
confirmable.confirm! if confirmable.persisted?
confirmable
end
original_token = confirmation_token
confirmation_token = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
# Generate a token checking if one does not already exist in the database.
def confirmation_token
generate_token(:confirmation_token)
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
if !confirmable.persisted? && Devise.allow_insecure_token_lookup
confirmable = find_or_initialize_with_error_by(:confirmation_token, original_token)
end
confirmable.confirm! if confirmable.persisted?
confirmable.confirmation_token = original_token
confirmable
end
# Find a record for confirmation by unconfirmed email field

View File

@@ -38,7 +38,6 @@ module Devise
self.locked_at = Time.now.utc
if unlock_strategy_enabled?(:email)
generate_unlock_token!
send_unlock_instructions
else
save(:validate => false)
@@ -60,11 +59,15 @@ module Devise
# Send unlock instructions by email
def send_unlock_instructions
send_devise_notification(:unlock_instructions)
raw, enc = Devise.token_generator.generate(self.class, :unlock_token)
self.unlock_token = enc
self.save(:validate => false)
send_devise_notification(:unlock_instructions, raw, {})
raw
end
# Resend the unlock instructions if the user is locked.
def resend_unlock_token
def resend_unlock_instructions
if_access_locked { send_unlock_instructions }
end
@@ -122,15 +125,6 @@ module Devise
self.failed_attempts > self.class.maximum_attempts
end
# Generates unlock token
def generate_unlock_token
self.unlock_token = self.class.unlock_token
end
def generate_unlock_token!
generate_unlock_token && save(:validate => false)
end
# Tells if the lock is expired if :time unlock strategy is active
def lock_expired?
if unlock_strategy_enabled?(:time)
@@ -158,7 +152,7 @@ module Devise
# Options must contain the user's unlock keys
def send_unlock_instructions(attributes={})
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
lockable.resend_unlock_token if lockable.persisted?
lockable.resend_unlock_instructions if lockable.persisted?
lockable
end
@@ -167,8 +161,16 @@ module Devise
# If the user is not locked, creates an error for the user
# Options must have the unlock_token
def unlock_access_by_token(unlock_token)
original_token = unlock_token
unlock_token = Devise.token_generator.digest(self, :unlock_token, unlock_token)
lockable = find_or_initialize_with_error_by(:unlock_token, unlock_token)
if !lockable.persisted? && Devise.allow_insecure_token_lookup
lockable = find_or_initialize_with_error_by(:unlock_token, original_token)
end
lockable.unlock_access! if lockable.persisted?
lockable.unlock_token = original_token
lockable
end
@@ -182,10 +184,6 @@ module Devise
self.lock_strategy == strategy
end
def unlock_token
Devise.friendly_token
end
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in, :unlock_keys)
end
end

View File

@@ -42,17 +42,19 @@ module Devise
save
end
# Resets reset password token and send reset password instructions by email
# Resets reset password token and send reset password instructions by email.
# Returns the token sent in the e-mail.
def send_reset_password_instructions
ensure_reset_password_token!
send_devise_notification(:reset_password_instructions)
raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)
self.reset_password_token = enc
self.reset_password_sent_at = Time.now.utc
self.save(:validate => false)
send_devise_notification(:reset_password_instructions, raw, {})
raw
end
# Generate reset password token unless already exists and save the record.
def ensure_reset_password_token!
generate_reset_password_token! if should_generate_reset_token?
end
# Checks if the reset password token sent is within the limit time.
# We do this by calculating if the difference between today and the
# sending date does not exceed the confirm in time configured.
@@ -79,23 +81,6 @@ module Devise
protected
def should_generate_reset_token?
reset_password_token.nil? || !reset_password_period_valid?
end
# Generates a new random token for reset password
def generate_reset_password_token
self.reset_password_token = self.class.reset_password_token
self.reset_password_sent_at = Time.now.utc
self.reset_password_token
end
# Resets the reset password token with and save the record without
# validating
def generate_reset_password_token!
generate_reset_password_token && save(:validate => false)
end
# Removes reset_password token
def clear_reset_password_token
self.reset_password_token = nil
@@ -127,7 +112,14 @@ module Devise
# containing an error in reset_password_token attribute.
# Attributes must contain reset_password_token, password and confirmation
def reset_password_by_token(attributes={})
recoverable = find_or_initialize_with_error_by(:reset_password_token, attributes[:reset_password_token])
original_token = attributes[:reset_password_token]
reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
recoverable = find_or_initialize_with_error_by(:reset_password_token, reset_password_token)
if !recoverable.persisted? && Devise.allow_insecure_token_lookup
recoverable = find_or_initialize_with_error_by(:reset_password_token, original_token)
end
if recoverable.persisted?
if recoverable.reset_password_period_valid?
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
@@ -135,6 +127,8 @@ module Devise
recoverable.errors.add(:reset_password_token, :expired)
end
end
recoverable.reset_password_token = original_token
recoverable
end

View File

@@ -110,12 +110,16 @@ module Devise
# Recreate the user based on the stored cookie
def serialize_from_cookie(id, remember_token)
record = to_adapter.get(id)
record if record && record.rememberable_value == remember_token && !record.remember_expired?
record if record && !record.remember_expired? &&
Devise.secure_compare(record.rememberable_value, remember_token)
end
# Generate a token checking if one does not already exist in the database.
def remember_token #:nodoc:
generate_token(:remember_token)
loop do
token = Devise.friendly_token
break token unless to_adapter.find_first({ :remember_token => token })
end
end
Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options)

View File

@@ -79,7 +79,10 @@ module Devise
# Generate a token checking if one does not already exist in the database.
def authentication_token
generate_token(:authentication_token)
loop do
token = Devise.friendly_token
break token unless to_adapter.find_first({ :authentication_token => token })
end
end
Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)

View File

@@ -13,14 +13,25 @@ module Devise
if block_given?
@blocks[kind] = block
else
block = @blocks[kind]
block ? block.call(default_params) : fallback_for(kind)
default_for(kind)
end
end
def sanitize(kind)
if block = @blocks[kind]
block.call(default_params)
else
default_sanitize(kind)
end
end
private
def fallback_for(kind)
def default_for(kind)
raise ArgumentError, "a block is expected in Devise base sanitizer"
end
def default_sanitize(kind)
default_params
end
@@ -30,34 +41,53 @@ module Devise
end
class ParameterSanitizer < BaseSanitizer
private
def fallback_for(kind)
if respond_to?(kind, true)
send(kind)
else
raise NotImplementedError, "Devise Parameter Sanitizer doesn't know how to sanitize parameters for #{kind}"
end
def initialize(*)
super
@permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
end
# These are the params used to sign in a user so we don't need to
# mass-assign the password param in order to authenticate. Excluding it
# here allows us to construct a new user without sensitive information if
# authentication fails.
def sign_in
default_params.permit(*auth_keys + [:password, :remember_me])
default_params.permit self.for(:sign_in)
end
def sign_up
default_params.permit(*(auth_keys + [:password, :password_confirmation]))
default_params.permit self.for(:sign_up)
end
def account_update
default_params.permit(*(auth_keys + [:password, :password_confirmation, :current_password]))
default_params.permit self.for(:account_update)
end
private
# Change for(kind) to return the values in the @permitted
# hash, allowing the developer to customize at runtime.
def default_for(kind)
@permitted[kind] || raise("No sanitizer provided for #{kind}")
end
def default_sanitize(kind)
if respond_to?(kind, true)
send(kind)
else
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
end
end
def attributes_for(kind)
case kind
when :sign_in
auth_keys + [:password, :remember_me]
when :sign_up
auth_keys + [:password, :password_confirmation]
when :account_update
auth_keys + [:password, :password_confirmation, :current_password]
end
end
def auth_keys
resource_class.authentication_keys.respond_to?(:keys) ? resource_class.authentication_keys.keys : resource_class.authentication_keys
@auth_keys ||= @resource_class.authentication_keys.respond_to?(:keys) ?
@resource_class.authentication_keys.keys : @resource_class.authentication_keys
end
end
end

View File

@@ -29,21 +29,17 @@ module Devise
end
end
initializer "devise.mongoid_version_warning" do
if defined?(Mongoid)
require 'mongoid/version'
if Mongoid::VERSION.to_f < 2.1
puts "\n[DEVISE] Please note that Mongoid versions prior to 2.1 handle dirty model " \
"object attributes in such a way that the Devise `validatable` module will not apply " \
"its usual uniqueness and format validations for the email field. It is recommended " \
"that you upgrade to Mongoid 2.1+ for this and other fixes, but if for some reason you " \
"are unable to do so, you should add these validations manually.\n"
initializer "devise.secret_key" do
Devise.token_generator ||=
if secret_key = Devise.secret_key
Devise::TokenGenerator.new(
Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
)
end
end
end
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
# We can get rid of this once we support only Rails > 3.2
# Deprecate: Remove once we move to Rails 4 only.
ActionDispatch::Routing::RoutesProxy.class_eval do
def respond_to?(method, include_private = false)
super || routes.url_helpers.respond_to?(method)

View File

@@ -80,7 +80,8 @@ module ActionDispatch::Routing
# * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
# :password, :confirmation, :unlock.
#
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout',
# :password => 'secret', :confirmation => 'verification', registration: 'register }
#
# * :controllers => the controller which should be used. All routes by default points to Devise controllers.
# However, if you want them to point to custom controller, you should do:
@@ -191,6 +192,7 @@ module ActionDispatch::Routing
#
def devise_for(*resources)
@devise_finalized = false
raise_no_secret_key unless Devise.secret_key
options = resources.extract_options!
options[:as] ||= @scope[:as] if @scope[:as].present?
@@ -222,14 +224,6 @@ module ActionDispatch::Routing
routes = mapping.used_routes
devise_scope mapping.name do
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
@@ -442,6 +436,16 @@ module ActionDispatch::Routing
end
end
def raise_no_secret_key #:nodoc:
raise <<-ERROR
Devise.secret_key was not set. Please add the following to your Devise initializer:
config.secret_key = '#{SecureRandom.hex(64)}'
Please ensure you restarted your application after installing Devise or setting the key.
ERROR
end
def raise_no_devise_method_error!(klass) #:nodoc:
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " \
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " \

View File

@@ -3,9 +3,17 @@ module Warden::Mixins::Common
@request ||= ActionDispatch::Request.new(env)
end
# This is called internally by Warden on logout
# Deprecate: Remove this check once we move to Rails 4 only.
NULL_STORE =
defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
def reset_session!
request.reset_session
# Calling reset_session on NULL_STORE causes it fail.
# This is a bug that needs to be fixed in Rails.
unless NULL_STORE && request.session.is_a?(NULL_STORE)
request.reset_session
end
end
def cookies

View File

@@ -26,20 +26,8 @@ module Devise
# In case the resource can't be validated, it will fail with the given
# unauthenticated_message.
def validate(resource, &block)
unless resource
ActiveSupport::Deprecation.warn "an empty resource was given to #{self.class.name}#validate. " \
"Please ensure the resource is not nil", caller
end
result = resource && resource.valid_for_authentication?(&block)
case result
when Symbol, String
ActiveSupport::Deprecation.warn "valid_for_authentication? should return a boolean value"
fail!(result)
return false
end
if result
decorate(resource)
true

View File

@@ -0,0 +1,70 @@
# Deprecate: Copied verbatim from Rails source, remove once we move to Rails 4 only.
require 'thread_safe'
require 'openssl'
require 'securerandom'
module Devise
class TokenGenerator
def initialize(key_generator, digest="SHA256")
@key_generator = key_generator
@digest = digest
end
def digest(klass, column, value)
value.present? && OpenSSL::HMAC.hexdigest(@digest, key_for(column), value.to_s)
end
def generate(klass, column)
key = key_for(column)
loop do
raw = Devise.friendly_token
enc = OpenSSL::HMAC.hexdigest(@digest, key, raw)
break [raw, enc] unless klass.to_adapter.find_first({ column => enc })
end
end
private
def key_for(column)
@key_generator.generate_key("Devise #{column}")
end
end
# KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
# It can be used to derive a number of keys for various purposes from a given secret.
# This lets Rails applications have a single secure secret, but avoid reusing that
# key in multiple incompatible contexts.
class KeyGenerator
def initialize(secret, options = {})
@secret = secret
# The default iterations are higher than required for our key derivation uses
# on the off chance someone uses this for password storage
@iterations = options[:iterations] || 2**16
end
# Returns a derived key suitable for use. The default key_size is chosen
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
# i.e. OpenSSL::Digest::SHA1#block_length
def generate_key(salt, key_size=64)
OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
end
end
# CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
# re-executing the key generation process when it's called using the same salt and
# key_size
class CachingKeyGenerator
def initialize(key_generator)
@key_generator = key_generator
@cache_keys = ThreadSafe::Cache.new
end
# Returns a derived key suitable for use. The default key_size is chosen
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
# i.e. OpenSSL::Digest::SHA1#block_length
def generate_key(salt, key_size=64)
@cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
end
end
end

View File

@@ -1,3 +1,3 @@
module Devise
VERSION = "3.0.1".freeze
VERSION = "3.1.1".freeze
end

View File

@@ -50,7 +50,7 @@ module ActiveRecord
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.integer :sign_in_count, :default => 0, :null => false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
@@ -63,12 +63,9 @@ module ActiveRecord
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
# t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
RUBY
end
end

View File

@@ -14,6 +14,5 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
add_index :<%= table_name %>, :reset_password_token, :unique => true
# add_index :<%= table_name %>, :confirmation_token, :unique => true
# add_index :<%= table_name %>, :unlock_token, :unique => true
# add_index :<%= table_name %>, :authentication_token, :unique => true
end
end

View File

@@ -15,7 +15,6 @@ class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
add_index :<%= table_name %>, :reset_password_token, :unique => true
# add_index :<%= table_name %>, :confirmation_token, :unique => true
# add_index :<%= table_name %>, :unlock_token, :unique => true
# add_index :<%= table_name %>, :authentication_token, :unique => true
end
def self.down

View File

@@ -4,8 +4,7 @@ module Devise
def model_contents
buffer = <<-CONTENT
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

View File

@@ -1,13 +1,19 @@
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
config.secret_key = '<%= SecureRandom.hex(64) %>'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
# Configure the class responsible to send e-mails.
# config.mailer = "Devise::Mailer"
# config.mailer = 'Devise::Mailer'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
@@ -61,8 +67,8 @@ Devise.setup do |config|
# If http headers should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. "Application" by default.
# config.http_authentication_realm = "Application"
# The realm used in Http Basic Authentication. 'Application' by default.
# config.http_authentication_realm = 'Application'
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
@@ -92,7 +98,7 @@ Devise.setup do |config|
config.stretches = Rails.env.test? ? 1 : 10
# Setup a pepper to generate the encrypted password.
# config.pepper = <%= SecureRandom.hex(64).inspect %>
# config.pepper = '<%= SecureRandom.hex(64) %>'
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
@@ -217,7 +223,7 @@ Devise.setup do |config|
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ["*/*", :html]
# config.navigational_formats = ['*/*', :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
@@ -241,12 +247,12 @@ Devise.setup do |config|
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: "/my_engine"
# mount MyEngine, at: '/my_engine'
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using omniauth, Devise cannot automatically set Omniauth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = "/my_engine/users/auth"
# config.omniauth_path_prefix = '/my_engine/users/auth'
end

View File

@@ -202,7 +202,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
test 'sign in and redirect uses the stored location' do
user = User.new
@controller.session[:"user_return_to"] = "/foo.bar"
@controller.session[:user_return_to] = "/foo.bar"
@mock_warden.expects(:user).with(:user).returns(nil)
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
@controller.expects(:redirect_to).with("/foo.bar")

View File

@@ -4,16 +4,15 @@ class PasswordsControllerTest < ActionController::TestCase
tests Devise::PasswordsController
include Devise::TestHelpers
def setup
setup do
request.env["devise.mapping"] = Devise.mappings[:user]
@user = create_user
@user.send_reset_password_instructions
@user = create_user.tap(&:confirm!)
@raw = @user.send_reset_password_instructions
end
def put_update_with_params
put :update, "user" => {
"reset_password_token" => @user.reset_password_token, "password" => "123456", "password_confirmation" => "123456"
"reset_password_token" => @raw, "password" => "123456", "password_confirmation" => "123456"
}
end

View File

@@ -215,7 +215,7 @@ class FailureTest < ActiveSupport::TestCase
}
call_failure(env)
assert @response.third.body.include?('<h2>Sign in</h2>')
assert @response.third.body.include?('Your account was not activated yet.')
assert @response.third.body.include?('Your account is not activated yet.')
end
end
end

View File

@@ -433,7 +433,7 @@ end
class AuthenticationOthersTest < ActionDispatch::IntegrationTest
test 'handles unverified requests gets rid of caches' do
swap UsersController, :allow_forgery_protection => true do
swap ApplicationController, :allow_forgery_protection => true do
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)

View File

@@ -28,9 +28,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
test 'user should receive a confirmation from a custom mailer' do
User.any_instance.stubs(:devise_mailer).returns(Users::Mailer)
resend_confirmation
assert_equal ['custom@example.com'], ActionMailer::Base.deliveries.first.from
end
@@ -40,21 +38,11 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
assert_contain /Confirmation token(.*)invalid/
end
test 'user with valid confirmation token should be able to confirm an account' do
user = create_user(:confirm => false)
assert_not user.confirmed?
visit_user_confirmation_with_token(user.confirmation_token)
assert_contain 'Your account was successfully confirmed.'
assert_current_url '/'
assert user.reload.confirmed?
end
test 'user with valid confirmation token should not be able to confirm an account after the token has expired' do
swap Devise, :confirm_within => 3.days do
user = create_user(:confirm => false, :confirmation_sent_at => 4.days.ago)
assert_not user.confirmed?
visit_user_confirmation_with_token(user.confirmation_token)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_have_selector '#error_explanation'
assert_contain /needs to be confirmed within 3 days/
@@ -66,10 +54,22 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
swap Devise, :confirm_within => 3.days do
user = create_user(:confirm => false, :confirmation_sent_at => 2.days.ago)
assert_not user.confirmed?
visit_user_confirmation_with_token(user.confirmation_token)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_contain 'Your account was successfully confirmed.'
assert_current_url '/'
assert_current_url '/users/sign_in'
assert user.reload.confirmed?
end
end
test 'user should be signed in after confirmation if allow_insecure_sign_in_after_confirmation is enabled' do
swap Devise, :confirm_within => 3.days, :allow_insecure_sign_in_after_confirmation => true do
user = create_user(:confirm => false, :confirmation_sent_at => 2.days.ago)
assert_not user.confirmed?
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_contain 'Your account was successfully confirmed. You are now signed in.'
assert_current_url root_url
assert user.reload.confirmed?
end
end
@@ -78,7 +78,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
Devise::ConfirmationsController.any_instance.stubs(:after_confirmation_path_for).returns("/?custom=1")
user = create_user(:confirm => false)
visit_user_confirmation_with_token(user.confirmation_token)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_current_url "/?custom=1"
end
@@ -87,7 +87,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
user = create_user(:confirm => false)
user.confirmed_at = Time.now
user.save
visit_user_confirmation_with_token(user.confirmation_token)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_have_selector '#error_explanation'
assert_contain 'already confirmed'
@@ -98,7 +98,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
user.confirmed_at = Time.now
user.save
visit_user_confirmation_with_token(user.confirmation_token)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_contain 'already confirmed'
fill_in 'email', :with => user.email
@@ -106,21 +106,6 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
assert_contain 'already confirmed'
end
test 'sign in user automatically after confirming its email' do
user = create_user(:confirm => false)
visit_user_confirmation_with_token(user.confirmation_token)
assert warden.authenticated?(:user)
end
test 'increases sign count when signed in through confirmation' do
user = create_user(:confirm => false)
visit_user_confirmation_with_token(user.confirmation_token)
user.reload
assert_equal 1, user.sign_in_count
end
test 'not confirmed user with setup to block without confirmation should not be able to sign in' do
swap Devise, :allow_unconfirmed_access_for => 0.days do
sign_in_as_user(:confirm => false)
@@ -150,6 +135,16 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
end
end
test 'unconfirmed but signed in user should be redirected to their root path' do
swap Devise, :allow_unconfirmed_access_for => 1.day do
user = sign_in_as_user(:confirm => false)
visit_user_confirmation_with_token(user.raw_confirmation_token)
assert_contain 'Your account was successfully confirmed.'
assert_current_url '/'
end
end
test 'error message is configurable by resource name' do
store_translations :en, :devise => {
:failure => { :user => { :unconfirmed => "Not confirmed user" } }
@@ -175,7 +170,7 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
test 'confirm account with valid confirmation token in XML format should return valid response' do
user = create_user(:confirm => false)
get user_confirmation_path(:confirmation_token => user.confirmation_token, :format => 'xml')
get user_confirmation_path(:confirmation_token => user.raw_confirmation_token, :format => 'xml')
assert_response :success
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
end
@@ -256,10 +251,10 @@ class ConfirmationOnChangeTest < ActionDispatch::IntegrationTest
admin = create_admin
admin.update_attributes(:email => 'new_test@example.com')
assert_equal 'new_test@example.com', admin.unconfirmed_email
visit_admin_confirmation_with_token(admin.confirmation_token)
visit_admin_confirmation_with_token(admin.raw_confirmation_token)
assert_contain 'Your account was successfully confirmed.'
assert_current_url '/admin_area/home'
assert_current_url '/admin_area/sign_in'
assert admin.reload.confirmed?
assert_not admin.reload.pending_reconfirmation?
end
@@ -269,17 +264,19 @@ class ConfirmationOnChangeTest < ActionDispatch::IntegrationTest
admin.update_attributes(:email => 'first_test@example.com')
assert_equal 'first_test@example.com', admin.unconfirmed_email
confirmation_token = admin.confirmation_token
raw_confirmation_token = admin.raw_confirmation_token
admin = Admin.find(admin.id)
admin.update_attributes(:email => 'second_test@example.com')
assert_equal 'second_test@example.com', admin.unconfirmed_email
visit_admin_confirmation_with_token(confirmation_token)
visit_admin_confirmation_with_token(raw_confirmation_token)
assert_have_selector '#error_explanation'
assert_contain(/Confirmation token(.*)invalid/)
visit_admin_confirmation_with_token(admin.confirmation_token)
visit_admin_confirmation_with_token(admin.raw_confirmation_token)
assert_contain 'Your account was successfully confirmed.'
assert_current_url '/admin_area/home'
assert_current_url '/admin_area/sign_in'
assert admin.reload.confirmed?
assert_not admin.reload.pending_reconfirmation?
end
@@ -291,7 +288,7 @@ class ConfirmationOnChangeTest < ActionDispatch::IntegrationTest
create_second_admin(:email => "new_admin_test@example.com")
visit_admin_confirmation_with_token(admin.confirmation_token)
visit_admin_confirmation_with_token(admin.raw_confirmation_token)
assert_have_selector '#error_explanation'
assert_contain(/Email.*already.*taken/)
assert admin.reload.pending_reconfirmation?

View File

@@ -2,7 +2,7 @@ require 'test_helper'
class HttpAuthenticationTest < ActionDispatch::IntegrationTest
test 'handles unverified requests gets rid of caches but continues signed in' do
swap UsersController, :allow_forgery_protection => true do
swap ApplicationController, :allow_forgery_protection => true do
create_user
post exhibit_user_url(1), {}, "HTTP_AUTHORIZATION" => "Basic #{Base64.encode64("user@test.com:12345678")}"
assert warden.authenticated?(:user)

View File

@@ -13,6 +13,7 @@ class LockTest < ActionDispatch::IntegrationTest
visit new_user_session_path
click_link "Didn't receive unlock instructions?"
Devise.stubs(:friendly_token).returns("abcdef")
fill_in 'email', :with => user.email
click_button 'Resend unlock instructions'
end
@@ -22,8 +23,11 @@ class LockTest < ActionDispatch::IntegrationTest
assert_template 'sessions/new'
assert_contain 'You will receive an email with instructions about how to unlock your account in a few minutes'
mail = ActionMailer::Base.deliveries.last
assert_equal 1, ActionMailer::Base.deliveries.size
assert_equal ['please-change-me@config-initializers-devise.com'], ActionMailer::Base.deliveries.first.from
assert_equal ['please-change-me@config-initializers-devise.com'], mail.from
assert_match user_unlock_path(unlock_token: 'abcdef'), mail.body.encoded
end
test 'user should receive the instructions from a custom mailer' do
@@ -75,23 +79,15 @@ class LockTest < ActionDispatch::IntegrationTest
end
test "locked user should be able to unlock account" do
user = create_user(:locked => true)
assert user.access_locked?
visit_user_unlock_with_token(user.unlock_token)
user = create_user
raw = user.lock_access!
visit_user_unlock_with_token(raw)
assert_current_url "/users/sign_in"
assert_contain 'Your account has been unlocked successfully. Please sign in to continue.'
assert_not user.reload.access_locked?
end
test "redirect user to sign in page after unlocking its account" do
user = create_user(:locked => true)
visit_user_unlock_with_token(user.unlock_token)
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
@@ -153,9 +149,10 @@ class LockTest < ActionDispatch::IntegrationTest
end
test 'user with valid unlock token should be able to unlock account via XML request' do
user = create_user(:locked => true)
user = create_user()
raw = user.lock_access!
assert user.access_locked?
get user_unlock_path(:format => 'xml', :unlock_token => user.unlock_token)
get user_unlock_path(:format => 'xml', :unlock_token => raw)
assert_response :success
assert response.body.include? %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>)
end

View File

@@ -14,12 +14,16 @@ class PasswordTest < ActionDispatch::IntegrationTest
fill_in 'email', :with => 'user@test.com'
yield if block_given?
Devise.stubs(:friendly_token).returns("abcdef")
click_button 'Send me reset password instructions'
end
def reset_password(options={}, &block)
visit edit_user_password_path(:reset_password_token => options[:reset_password_token]) unless options[:visit] == false
assert_response :success
unless options[:visit] == false
visit edit_user_password_path(:reset_password_token => options[:reset_password_token] || "abcdef")
assert_response :success
end
fill_in 'New password', :with => '987654321'
fill_in 'Confirm new password', :with => '987654321'
@@ -45,7 +49,10 @@ class PasswordTest < ActionDispatch::IntegrationTest
request_forgot_password do
fill_in 'email', :with => 'foo@bar.com'
end
assert_equal ['custom@example.com'], ActionMailer::Base.deliveries.last.from
mail = ActionMailer::Base.deliveries.last
assert_equal ['custom@example.com'], mail.from
assert_match edit_user_password_path(reset_password_token: 'abcdef'), mail.body.encoded
end
test 'reset password with email of different case should fail when email is NOT the list of case insensitive keys' do
@@ -146,7 +153,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
test 'not authenticated user with valid reset password token but invalid password should not be able to change his password' do
user = create_user
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token do
reset_password do
fill_in 'Confirm new password', :with => 'other_password'
end
@@ -161,7 +168,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
test 'not authenticated user with valid data should be able to change his password' do
user = create_user
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert_current_url '/'
assert_contain 'Your password was changed successfully. You are now signed in.'
@@ -171,14 +178,13 @@ class PasswordTest < ActionDispatch::IntegrationTest
test 'after entering invalid data user should still be able to change his password' do
user = create_user
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token do
fill_in 'Confirm new password', :with => 'other_password'
end
reset_password { fill_in 'Confirm new password', :with => 'other_password' }
assert_response :success
assert_have_selector '#error_explanation'
assert_not user.reload.valid_password?('987654321')
reset_password :reset_password_token => user.reload.reset_password_token, :visit => false
reset_password :visit => false
assert_contain 'Your password was changed successfully.'
assert user.reload.valid_password?('987654321')
end
@@ -186,7 +192,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
test 'sign in user automatically after changing its password' do
user = create_user
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert warden.authenticated?(:user)
end
@@ -196,7 +202,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
swap Devise, :unlock_strategy => strategy do
user = create_user(:locked => true)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert_contain 'Your password was changed successfully.'
assert_not_contain 'You are now signed in.'
@@ -210,7 +216,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
swap Devise, :unlock_strategy => :email do
user = create_user(:locked => true)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert_contain 'Your password was changed successfully.'
assert !user.reload.access_locked?
@@ -222,7 +228,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
swap Devise, :unlock_strategy => :both do
user = create_user(:locked => true)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert_contain 'Your password was changed successfully.'
assert !user.reload.access_locked?
@@ -230,15 +236,6 @@ class PasswordTest < ActionDispatch::IntegrationTest
end
end
test 'sign in user automatically and confirm after changing its password if it\'s not confirmed' do
user = create_user(:confirm => false)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
assert warden.authenticated?(:user)
assert user.reload.confirmed?
end
test 'reset password request with valid E-Mail in XML format should return valid response' do
create_user
post user_password_path(:format => 'xml'), :user => {:email => "user@test.com"}
@@ -265,7 +262,9 @@ class PasswordTest < ActionDispatch::IntegrationTest
test 'change password with valid parameters in XML format should return valid response' do
user = create_user
request_forgot_password
put user_password_path(:format => 'xml'), :user => {:reset_password_token => user.reload.reset_password_token, :password => '987654321', :password_confirmation => '987654321'}
put user_password_path(:format => 'xml'), :user => {
:reset_password_token => 'abcdef', :password => '987654321', :password_confirmation => '987654321'
}
assert_response :success
assert warden.authenticated?(:user)
end
@@ -326,7 +325,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
assert_equal 10, user.failed_attempts
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
reset_password
assert warden.authenticated?(:user)
user.reload

View File

@@ -30,8 +30,8 @@ class RememberMeTest < ActionDispatch::IntegrationTest
assert_nil request.cookies["remember_user_cookie"]
end
test 'handles unverified requests gets rid of caches' do
swap UsersController, :allow_forgery_protection => true do
test 'handle unverified requests gets rid of caches' do
swap ApplicationController, :allow_forgery_protection => true do
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
@@ -42,9 +42,21 @@ class RememberMeTest < ActionDispatch::IntegrationTest
end
end
test 'handle unverified requests does not create cookies on sign in' do
swap ApplicationController, :allow_forgery_protection => true do
get new_user_session_path
assert request.session[:_csrf_token]
post user_session_path, :authenticity_token => "oops", :user =>
{ email: "jose.valim@gmail.com", password: "123456", :remember_me => "1" }
assert_not warden.authenticated?(:user)
assert_not request.cookies['remember_user_token']
end
end
test 'generate remember token after sign in' do
sign_in_as_user :remember_me => true
assert request.cookies["remember_user_token"]
assert request.cookies['remember_user_token']
end
test 'generate remember token after sign in setting cookie options' do
@@ -90,16 +102,6 @@ class RememberMeTest < ActionDispatch::IntegrationTest
assert_redirected_to root_path
end
test 'cookies are destroyed on unverified requests' do
swap ApplicationController, :allow_forgery_protection => true do
create_user_and_remember
get users_path
assert warden.authenticated?(:user)
post root_path, :authenticity_token => 'INVALID'
assert_not warden.authenticated?(:user)
end
end
test 'does not extend remember period through sign in' do
swap Devise, :extend_remember_period => true, :remember_for => 1.year do
user = create_user

View File

@@ -84,8 +84,12 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
test 'body should have link to confirm the account' do
host = ActionMailer::Base.default_url_options[:host]
confirmation_url_regexp = %r{<a href=\"http://#{host}/users/confirmation\?confirmation_token=#{user.confirmation_token}">}
assert_match confirmation_url_regexp, mail.body.encoded
if mail.body.encoded =~ %r{<a href=\"http://#{host}/users/confirmation\?confirmation_token=([^"]+)">}
assert_equal Devise.token_generator.digest(user.class, :confirmation_token, $1), user.confirmation_token
else
flunk "expected confirmation url regex to match"
end
end
test 'renders a scoped if scoped_views is set to true' do

View File

@@ -80,8 +80,12 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
test 'body should have link to confirm the account' do
host = ActionMailer::Base.default_url_options[:host]
reset_url_regexp = %r{<a href=\"http://#{host}/users/password/edit\?reset_password_token=#{user.reset_password_token}">}
assert_match reset_url_regexp, mail.body.encoded
if mail.body.encoded =~ %r{<a href=\"http://#{host}/users/password/edit\?reset_password_token=([^"]+)">}
assert_equal Devise.token_generator.digest(user.class, :reset_password_token, $1), user.reset_password_token
else
flunk "expected reset password url regex to match"
end
end
test 'mailer sender accepts a proc' do

View File

@@ -81,7 +81,11 @@ class UnlockInstructionsTest < ActionMailer::TestCase
test 'body should have link to unlock the account' do
host = ActionMailer::Base.default_url_options[:host]
unlock_url_regexp = %r{<a href=\"http://#{host}/users/unlock\?unlock_token=#{user.unlock_token}">}
assert_match unlock_url_regexp, mail.body.encoded
if mail.body.encoded =~ %r{<a href=\"http://#{host}/users/unlock\?unlock_token=([^"]+)">}
assert_equal Devise.token_generator.digest(user.class, :unlock_token, $1), user.unlock_token
else
flunk "expected unlock url regex to match"
end
end
end

View File

@@ -51,9 +51,19 @@ class ConfirmableTest < ActiveSupport::TestCase
assert_equal "was already confirmed, please try signing in", user.errors[:email].join
end
test 'should find and confirm a user automatically' do
test 'DEPRECATED: should find and confirm a user automatically' do
swap Devise, allow_insecure_token_lookup: true do
user = create_user
confirmed_user = User.confirm_by_token(user.confirmation_token)
assert_equal confirmed_user, user
assert user.reload.confirmed?
end
end
test 'should find and confirm a user automatically based on the raw token' do
user = create_user
confirmed_user = User.confirm_by_token(user.confirmation_token)
raw = user.raw_confirmation_token
confirmed_user = User.confirm_by_token(raw)
assert_equal confirmed_user, user
assert user.reload.confirmed?
end
@@ -74,7 +84,7 @@ class ConfirmableTest < ActiveSupport::TestCase
user = create_user
user.confirmed_at = Time.now
user.save
confirmed_user = User.confirm_by_token(user.confirmation_token)
confirmed_user = User.confirm_by_token(user.raw_confirmation_token)
assert confirmed_user.confirmed?
assert_equal "was already confirmed, please try signing in", confirmed_user.errors[:email].join
end
@@ -176,7 +186,7 @@ class ConfirmableTest < ActiveSupport::TestCase
test 'should not be able to send instructions if the user is already confirmed' do
user = create_user
user.confirm!
assert_not user.resend_confirmation_token
assert_not user.resend_confirmation_instructions
assert user.confirmed?
assert_equal 'was already confirmed, please try signing in', user.errors[:email].join
end
@@ -264,7 +274,7 @@ class ConfirmableTest < ActiveSupport::TestCase
def confirm_user_by_token_with_confirmation_sent_at(confirmation_sent_at)
user = create_user
user.update_attribute(:confirmation_sent_at, confirmation_sent_at)
confirmed_user = User.confirm_by_token(user.confirmation_token)
confirmed_user = User.confirm_by_token(user.raw_confirmation_token)
assert_equal confirmed_user, user
user.reload.confirmed?
end
@@ -285,32 +295,12 @@ class ConfirmableTest < ActiveSupport::TestCase
end
end
test 'should generate a new token if the previous one has expired' do
swap Devise, :confirm_within => 3.days do
user = create_user
user.update_attribute(:confirmation_sent_at, 4.days.ago)
old = user.confirmation_token
user.resend_confirmation_token
assert_not_equal user.confirmation_token, old
end
end
test 'should generate a new token when a valid one does not exist' do
swap Devise, :confirm_within => 3.days do
user = create_user
user.update_attribute(:confirmation_sent_at, 4.days.ago)
old = user.confirmation_token
user.ensure_confirmation_token!
assert_not_equal user.confirmation_token, old
end
end
test 'should not generate a new token when a valid one exists' do
test 'always generate a new token on resend' do
user = create_user
assert_not_nil user.confirmation_token
old = user.confirmation_token
user.ensure_confirmation_token!
assert_equal user.confirmation_token, old
old = user.confirmation_token
user = User.find(user.id)
user.resend_confirmation_instructions
assert_not_equal user.confirmation_token, old
end
test 'should call after_confirmation if confirmed' do

View File

@@ -139,10 +139,20 @@ class LockableTest < ActiveSupport::TestCase
end
end
test 'should find and unlock a user automatically' do
test 'DEPRECATED: should find and unlock a user automatically' do
swap Devise, allow_insecure_token_lookup: true do
user = create_user
user.lock_access!
locked_user = User.unlock_access_by_token(user.unlock_token)
assert_equal locked_user, user
assert_not user.reload.access_locked?
end
end
test 'should find and unlock a user automatically based on raw token' do
user = create_user
user.lock_access!
locked_user = User.unlock_access_by_token(user.unlock_token)
raw = user.send_unlock_instructions
locked_user = User.unlock_access_by_token(raw)
assert_equal locked_user, user
assert_not user.reload.access_locked?
end
@@ -195,7 +205,7 @@ class LockableTest < ActiveSupport::TestCase
test 'should not be able to send instructions if the user is not locked' do
user = create_user
assert_not user.resend_unlock_token
assert_not user.resend_unlock_instructions
assert_not user.access_locked?
assert_equal 'was not locked', user.errors[:email].join
end
@@ -203,7 +213,7 @@ class LockableTest < ActiveSupport::TestCase
test 'should not be able to send instructions if the user if not locked and have username as unlock key' do
swap Devise, :unlock_keys => [:username] do
user = create_user
assert_not user.resend_unlock_token
assert_not user.resend_unlock_instructions
assert_not user.access_locked?
assert_equal 'was not locked', user.errors[:username].join
end

View File

@@ -108,11 +108,21 @@ class RecoverableTest < ActiveSupport::TestCase
end
end
test 'should find a user to reset his password based on reset_password_token' do
user = create_user
user.ensure_reset_password_token!
test 'DEPRECATED: should find a user to reset his password based on reset_password_token' do
swap Devise, allow_insecure_token_lookup: true do
user = create_user
user.send_reset_password_instructions
reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token)
reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token)
assert_equal reset_password_user, user
end
end
test 'should find a user to reset his password based on the raw token' do
user = create_user
raw = user.send_reset_password_instructions
reset_password_user = User.reset_password_by_token(:reset_password_token => raw)
assert_equal reset_password_user, user
end
@@ -130,9 +140,9 @@ class RecoverableTest < ActiveSupport::TestCase
test 'should return a new record with errors if password is blank' do
user = create_user
user.ensure_reset_password_token!
raw = user.send_reset_password_instructions
reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token, :password => '')
reset_password_user = User.reset_password_by_token(:reset_password_token => raw, :password => '')
assert_not reset_password_user.errors.empty?
assert_match "can't be blank", reset_password_user.errors[:password].join
end
@@ -140,10 +150,10 @@ class RecoverableTest < ActiveSupport::TestCase
test 'should reset successfully user password given the new password and confirmation' do
user = create_user
old_password = user.password
user.ensure_reset_password_token!
raw = user.send_reset_password_instructions
User.reset_password_by_token(
:reset_password_token => user.reset_password_token,
:reset_password_token => raw,
:password => 'new_password',
:password_confirmation => 'new_password'
)
@@ -153,38 +163,17 @@ class RecoverableTest < ActiveSupport::TestCase
assert user.valid_password?('new_password')
end
test 'should not reset reset password token during reset_password_within time' do
swap Devise, :reset_password_within => 1.hour do
user = create_user
user.send_reset_password_instructions
3.times do
token = user.reset_password_token
user.send_reset_password_instructions
assert_equal token, user.reset_password_token
end
end
end
test 'should reset reset password token after reset_password_within time' do
swap Devise, :reset_password_within => 1.hour do
user = create_user
user.reset_password_sent_at = 2.days.ago
token = user.reset_password_token
user.send_reset_password_instructions
assert_not_equal token, user.reset_password_token
end
end
test 'should not reset password after reset_password_within time' do
swap Devise, :reset_password_within => 1.hour do
user = create_user
raw = user.send_reset_password_instructions
old_password = user.password
user.ensure_reset_password_token!
user.reset_password_sent_at = 2.days.ago
user.save!
reset_password_user = User.reset_password_by_token(
:reset_password_token => user.reset_password_token,
:reset_password_token => raw,
:password => 'new_password',
:password_confirmation => 'new_password'
)
@@ -201,22 +190,5 @@ class RecoverableTest < ActiveSupport::TestCase
:reset_password_sent_at,
:reset_password_token
]
end
test 'should generate a new token when a valid one does not exist' do
user = create_user
assert_nil user.reset_password_token
user.ensure_reset_password_token!
assert_not_nil user.reset_password_token
end
test 'should not generate a new token when a valid one exists' do
user = create_user
user.send :generate_reset_password_token!
assert_not_nil user.reset_password_token
old = user.reset_password_token
user.ensure_reset_password_token!
assert_equal user.reset_password_token, old
end
end

View File

@@ -22,6 +22,14 @@ class RememberableTest < ActiveSupport::TestCase
user.forget_me!
end
test 'can generate remember token' do
user = create_user
user.singleton_class.send(:attr_accessor, :remember_token)
User.to_adapter.expects(:find_first).returns(nil)
user.remember_me!
assert user.remember_token
end
test 'serialize into cookie' do
user = create_user
user.remember_me!

View File

@@ -141,23 +141,4 @@ class CheckFieldsTest < ActiveSupport::TestCase
Devise::Models.check_fields!(Magician)
end
end
test "doesn't raise a NoMethodError exception when the module doesn't have a required_field(klass) class method" do
driver = Class.new do
extend Devise::Models
def self.before_validation(instance)
end
attr_accessor :encrypted_password, :email
devise :database_authenticatable
end
swap_module_method_existence Devise::Models::DatabaseAuthenticatable, :required_fields do
assert_deprecated do
Devise::Models.check_fields!(driver)
end
end
end
end

View File

@@ -2,12 +2,13 @@ require 'test_helper'
require 'devise/parameter_sanitizer'
class BaseSanitizerTest < ActiveSupport::TestCase
def sanitizer
Devise::BaseSanitizer.new(User, :user, { user: { "email" => "jose" } })
def sanitizer(params)
Devise::BaseSanitizer.new(User, :user, params)
end
test 'returns chosen params' do
assert_equal({ "email" => "jose" }, sanitizer.for(:sign_in))
sanitizer = sanitizer(user: { "email" => "jose" })
assert_equal({ "email" => "jose" }, sanitizer.sanitize(:sign_in))
end
end
@@ -22,36 +23,49 @@ if defined?(ActionController::StrongParameters)
test 'filters some parameters on sign in by default' do
sanitizer = sanitizer(user: { "email" => "jose", "password" => "invalid", "remember_me" => "1" })
assert_equal({ "email" => "jose", "password" => "invalid", "remember_me" => "1" }, sanitizer.for(:sign_in))
assert_equal({ "email" => "jose", "password" => "invalid", "remember_me" => "1" }, sanitizer.sanitize(:sign_in))
end
test 'handles auth keys as a hash' do
swap Devise, :authentication_keys => {:email => true} do
sanitizer = sanitizer(user: { "email" => "jose", "password" => "invalid" })
assert_equal({ "email" => "jose", "password" => "invalid" }, sanitizer.for(:sign_in))
assert_equal({ "email" => "jose", "password" => "invalid" }, sanitizer.sanitize(:sign_in))
end
end
test 'filters some parameters on sign up by default' do
sanitizer = sanitizer(user: { "email" => "jose", "role" => "invalid" })
assert_equal({ "email" => "jose" }, sanitizer.for(:sign_up))
assert_equal({ "email" => "jose" }, sanitizer.sanitize(:sign_up))
end
test 'filters some parameters on account update by default' do
sanitizer = sanitizer(user: { "email" => "jose", "role" => "invalid" })
assert_equal({ "email" => "jose" }, sanitizer.for(:account_update))
assert_equal({ "email" => "jose" }, sanitizer.sanitize(:account_update))
end
test 'allows custom hooks' do
sanitizer = sanitizer(user: { "email" => "jose", "password" => "invalid" })
sanitizer.for(:sign_in) { |user| user.permit(:email, :password) }
assert_equal({ "email" => "jose", "password" => "invalid" }, sanitizer.for(:sign_in))
assert_equal({ "email" => "jose", "password" => "invalid" }, sanitizer.sanitize(:sign_in))
end
test 'adding multiple permitted parameters' do
sanitizer = sanitizer(user: { "email" => "jose", "username" => "jose1", "role" => "valid" })
sanitizer.for(:sign_in).concat([:username, :role])
assert_equal({ "email" => "jose", "username" => "jose1", "role" => "valid" }, sanitizer.sanitize(:sign_in))
end
test 'removing multiple default parameters' do
sanitizer = sanitizer(user: { "email" => "jose", "password" => "invalid", "remember_me" => "1" })
sanitizer.for(:sign_in).delete(:email)
sanitizer.for(:sign_in).delete(:password)
assert_equal({ "remember_me" => "1" }, sanitizer.sanitize(:sign_in))
end
test 'raises on unknown hooks' do
sanitizer = sanitizer(user: { "email" => "jose", "password" => "invalid" })
assert_raise NotImplementedError do
sanitizer.for(:unknown)
sanitizer.sanitize(:unknown)
end
end
end

View File

@@ -4,6 +4,9 @@ require "omniauth-openid"
# Use this hook to configure devise mailer, warden hooks and so forth. The first
# four configuration values can also be set straight in your models.
Devise.setup do |config|
config.secret_key = "d9eb5171c59a4c817f68b0de27b8c1e340c2341b52cdbc60d3083d4e8958532" \
"18dcc5f589cafde048faec956b61f864b9b5513ff9ce29bf9e5d58b0f234f8e3b"
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.

View File

@@ -11,4 +11,7 @@ module SharedAdmin
validates_uniqueness_of :email, :allow_blank => true, :if => :email_changed?
end
def raw_confirmation_token
@raw_confirmation_token
end
end

View File

@@ -12,6 +12,10 @@ module SharedUser
extend ExtendMethods
end
def raw_confirmation_token
@raw_confirmation_token
end
module ExtendMethods
def new_with_session(params, session)
super.tap do |user|

View File

@@ -67,25 +67,4 @@ class ActiveSupport::TestCase
end
end
end
def swap_module_method_existence(klass, method)
klass.module_eval %Q[
class << self
alias #{method}_referenced #{method}
undef #{method}
end
]
begin
yield if block_given?
ensure
klass.module_eval %Q[
class << self
alias #{method} #{method}_referenced
undef #{method}_referenced
end
]
end
end
end