devise 3.2.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/app/controllers/devise/confirmations_controller.rb +2 -0
- data/app/controllers/devise/passwords_controller.rb +2 -0
- data/app/controllers/devise/registrations_controller.rb +3 -0
- data/app/controllers/devise/sessions_controller.rb +2 -0
- data/app/controllers/devise/unlocks_controller.rb +2 -0
- data/gemfiles/Gemfile.rails-3.2.x.lock +1 -1
- data/lib/devise.rb +1 -0
- data/lib/devise/controllers/helpers.rb +1 -17
- data/lib/devise/controllers/store_location.rb +47 -0
- data/lib/devise/failure_app.rb +3 -1
- data/lib/devise/models/database_authenticatable.rb +10 -1
- data/lib/devise/rails/routes.rb +17 -2
- data/lib/devise/strategies/database_authenticatable.rb +6 -3
- data/lib/devise/version.rb +1 -1
- data/test/controllers/helpers_test.rb +17 -0
- data/test/models/database_authenticatable_test.rb +5 -0
- data/test/rails_app/config/boot.rb +7 -1
- data/test/rails_app/config/environments/development.rb +0 -4
- data/test/rails_app/config/environments/production.rb +0 -4
- data/test/rails_app/db/schema.rb +21 -17
- data/test/test_helper.rb +0 -7
- data/test/test_models.rb +7 -0
- metadata +3 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
### 3.2.1
|
2
|
+
|
3
|
+
Security announcement: http://blog.plataformatec.com.br/2013/11/e-mail-enumeration-in-devise-in-paranoid-mode
|
4
|
+
|
5
|
+
* enhancements
|
6
|
+
* Add `store_location_for` helper and ensure it is safe (by @matthewrudy and @homakov)
|
7
|
+
* Add `yield` around resource methods in Devise controllers (by @edelpero)
|
8
|
+
|
9
|
+
* bug fix
|
10
|
+
* Bring `password_digest` back to fix compatibility with `devise-encryptable`
|
11
|
+
* Avoid e-mail enumeration on sign in when in paranoid mode
|
12
|
+
|
1
13
|
### 3.2.0
|
2
14
|
|
3
15
|
* enhancements
|
data/Gemfile.lock
CHANGED
@@ -7,6 +7,7 @@ class Devise::ConfirmationsController < DeviseController
|
|
7
7
|
# POST /resource/confirmation
|
8
8
|
def create
|
9
9
|
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
10
|
+
yield resource if block_given?
|
10
11
|
|
11
12
|
if successfully_sent?(resource)
|
12
13
|
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
@@ -18,6 +19,7 @@ class Devise::ConfirmationsController < DeviseController
|
|
18
19
|
# GET /resource/confirmation?confirmation_token=abcdef
|
19
20
|
def show
|
20
21
|
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
22
|
+
yield resource if block_given?
|
21
23
|
|
22
24
|
if resource.errors.empty?
|
23
25
|
set_flash_message(:notice, :confirmed) if is_flashing_format?
|
@@ -11,6 +11,7 @@ class Devise::PasswordsController < DeviseController
|
|
11
11
|
# POST /resource/password
|
12
12
|
def create
|
13
13
|
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
14
|
+
yield resource if block_given?
|
14
15
|
|
15
16
|
if successfully_sent?(resource)
|
16
17
|
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
@@ -28,6 +29,7 @@ class Devise::PasswordsController < DeviseController
|
|
28
29
|
# PUT /resource/password
|
29
30
|
def update
|
30
31
|
self.resource = resource_class.reset_password_by_token(resource_params)
|
32
|
+
yield resource if block_given?
|
31
33
|
|
32
34
|
if resource.errors.empty?
|
33
35
|
resource.unlock_access! if unlockable?(resource)
|
@@ -13,6 +13,7 @@ class Devise::RegistrationsController < DeviseController
|
|
13
13
|
build_resource(sign_up_params)
|
14
14
|
|
15
15
|
if resource.save
|
16
|
+
yield resource if block_given?
|
16
17
|
if resource.active_for_authentication?
|
17
18
|
set_flash_message :notice, :signed_up if is_flashing_format?
|
18
19
|
sign_up(resource_name, resource)
|
@@ -41,6 +42,7 @@ class Devise::RegistrationsController < DeviseController
|
|
41
42
|
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
|
42
43
|
|
43
44
|
if update_resource(resource, account_update_params)
|
45
|
+
yield resource if block_given?
|
44
46
|
if is_flashing_format?
|
45
47
|
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
|
46
48
|
:update_needs_confirmation : :updated
|
@@ -59,6 +61,7 @@ class Devise::RegistrationsController < DeviseController
|
|
59
61
|
resource.destroy
|
60
62
|
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
61
63
|
set_flash_message :notice, :destroyed if is_flashing_format?
|
64
|
+
yield resource if block_given?
|
62
65
|
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
|
63
66
|
end
|
64
67
|
|
@@ -15,6 +15,7 @@ class Devise::SessionsController < DeviseController
|
|
15
15
|
self.resource = warden.authenticate!(auth_options)
|
16
16
|
set_flash_message(:notice, :signed_in) if is_flashing_format?
|
17
17
|
sign_in(resource_name, resource)
|
18
|
+
yield resource if block_given?
|
18
19
|
respond_with resource, :location => after_sign_in_path_for(resource)
|
19
20
|
end
|
20
21
|
|
@@ -23,6 +24,7 @@ class Devise::SessionsController < DeviseController
|
|
23
24
|
redirect_path = after_sign_out_path_for(resource_name)
|
24
25
|
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
25
26
|
set_flash_message :notice, :signed_out if signed_out && is_flashing_format?
|
27
|
+
yield resource if block_given?
|
26
28
|
|
27
29
|
# We actually need to hardcode this as Rails default responder doesn't
|
28
30
|
# support returning empty response on GET request
|
@@ -9,6 +9,7 @@ class Devise::UnlocksController < DeviseController
|
|
9
9
|
# POST /resource/unlock
|
10
10
|
def create
|
11
11
|
self.resource = resource_class.send_unlock_instructions(resource_params)
|
12
|
+
yield resource if block_given?
|
12
13
|
|
13
14
|
if successfully_sent?(resource)
|
14
15
|
respond_with({}, :location => after_sending_unlock_instructions_path_for(resource))
|
@@ -20,6 +21,7 @@ class Devise::UnlocksController < DeviseController
|
|
20
21
|
# GET /resource/unlock?unlock_token=abcdef
|
21
22
|
def show
|
22
23
|
self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
|
24
|
+
yield resource if block_given?
|
23
25
|
|
24
26
|
if resource.errors.empty?
|
25
27
|
set_flash_message :notice, :unlocked if is_flashing_format?
|
data/lib/devise.rb
CHANGED
@@ -21,6 +21,7 @@ module Devise
|
|
21
21
|
autoload :Rememberable, 'devise/controllers/rememberable'
|
22
22
|
autoload :ScopedViews, 'devise/controllers/scoped_views'
|
23
23
|
autoload :SignInOut, 'devise/controllers/sign_in_out'
|
24
|
+
autoload :StoreLocation, 'devise/controllers/store_location'
|
24
25
|
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
25
26
|
end
|
26
27
|
|
@@ -4,6 +4,7 @@ module Devise
|
|
4
4
|
module Helpers
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
include Devise::Controllers::SignInOut
|
7
|
+
include Devise::Controllers::StoreLocation
|
7
8
|
|
8
9
|
included do
|
9
10
|
helper_method :warden, :signed_in?, :devise_controller?
|
@@ -97,23 +98,6 @@ module Devise
|
|
97
98
|
request.env["devise.allow_params_authentication"] = true
|
98
99
|
end
|
99
100
|
|
100
|
-
# Returns and delete (if it's navigational format) the url stored in the session for
|
101
|
-
# the given scope. Useful for giving redirect backs after sign up:
|
102
|
-
#
|
103
|
-
# Example:
|
104
|
-
#
|
105
|
-
# redirect_to stored_location_for(:user) || root_path
|
106
|
-
#
|
107
|
-
def stored_location_for(resource_or_scope)
|
108
|
-
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
109
|
-
|
110
|
-
if is_navigational_format?
|
111
|
-
session.delete("#{scope}_return_to")
|
112
|
-
else
|
113
|
-
session["#{scope}_return_to"]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
101
|
# The scope root url to be used when he's signed in. By default, it first
|
118
102
|
# tries to find a resource_root_path, otherwise it uses the root_path.
|
119
103
|
def signed_in_root_path(resource_or_scope)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Controllers
|
5
|
+
# Provide the ability to store a location.
|
6
|
+
# Used to redirect back to a desired path after sign in.
|
7
|
+
# Included by default in all controllers.
|
8
|
+
module StoreLocation
|
9
|
+
# Returns and delete (if it's navigational format) the url stored in the session for
|
10
|
+
# the given scope. Useful for giving redirect backs after sign up:
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# redirect_to stored_location_for(:user) || root_path
|
15
|
+
#
|
16
|
+
def stored_location_for(resource_or_scope)
|
17
|
+
session_key = stored_location_key_for(resource_or_scope)
|
18
|
+
|
19
|
+
if is_navigational_format?
|
20
|
+
session.delete(session_key)
|
21
|
+
else
|
22
|
+
session[session_key]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Stores the provided location to redirect the user after signing in.
|
27
|
+
# Useful in combination with the `stored_location_for` helper.
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
#
|
31
|
+
# store_location_for(:user, dashboard_path)
|
32
|
+
# redirect_to user_omniauth_authorize_path(:facebook)
|
33
|
+
#
|
34
|
+
def store_location_for(resource_or_scope, location)
|
35
|
+
session_key = stored_location_key_for(resource_or_scope)
|
36
|
+
session[session_key] = URI.parse(location).path if location
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def stored_location_key_for(resource_or_scope)
|
42
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
43
|
+
"#{scope}_return_to"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/devise/failure_app.rb
CHANGED
@@ -13,6 +13,8 @@ module Devise
|
|
13
13
|
include Rails.application.routes.url_helpers
|
14
14
|
include Rails.application.routes.mounted_helpers
|
15
15
|
|
16
|
+
include Devise::Controllers::StoreLocation
|
17
|
+
|
16
18
|
delegate :flash, :to => :request
|
17
19
|
|
18
20
|
def self.call(env)
|
@@ -189,7 +191,7 @@ module Devise
|
|
189
191
|
# yet, but we still need to store the uri based on scope, so different scopes
|
190
192
|
# would never use the same uri to redirect.
|
191
193
|
def store_location!
|
192
|
-
|
194
|
+
store_location_for(scope, attempted_path) if request.get? && !http_auth?
|
193
195
|
end
|
194
196
|
|
195
197
|
def is_navigational_format?
|
@@ -39,7 +39,7 @@ module Devise
|
|
39
39
|
# Generates password encryption based on the given value.
|
40
40
|
def password=(new_password)
|
41
41
|
@password = new_password
|
42
|
-
self.encrypted_password =
|
42
|
+
self.encrypted_password = password_digest(@password) if @password.present?
|
43
43
|
end
|
44
44
|
|
45
45
|
# Verifies whether an password (ie from sign in) is the user password.
|
@@ -135,6 +135,15 @@ module Devise
|
|
135
135
|
|
136
136
|
protected
|
137
137
|
|
138
|
+
# Digests the password using bcrypt. Custom encryption should override
|
139
|
+
# this method to apply their own algorithm.
|
140
|
+
#
|
141
|
+
# See https://github.com/plataformatec/devise-encryptable for examples
|
142
|
+
# of other encryption engines.
|
143
|
+
def password_digest(password)
|
144
|
+
Devise.bcrypt(self.class, password)
|
145
|
+
end
|
146
|
+
|
138
147
|
module ClassMethods
|
139
148
|
Devise::Models.config(self, :pepper, :stretches)
|
140
149
|
|
data/lib/devise/rails/routes.rb
CHANGED
@@ -387,8 +387,23 @@ module ActionDispatch::Routing
|
|
387
387
|
|
388
388
|
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
389
389
|
if mapping.fullpath =~ /:[a-zA-Z_]/
|
390
|
-
raise
|
391
|
-
|
390
|
+
raise <<-ERROR
|
391
|
+
Devise does not support scoping omniauth callbacks under a dynamic segment
|
392
|
+
and you have set #{mapping.fullpath.inspect}. You can work around by passing
|
393
|
+
`skip: :omniauth_callbacks` and manually defining the routes. Here is an example:
|
394
|
+
|
395
|
+
match "/users/auth/:provider",
|
396
|
+
:constraints => { :provider => /\Agoogle|facebook\z/ },
|
397
|
+
:to => "devise/omniauth_callbacks#passthru",
|
398
|
+
:as => :omniauth_authorize,
|
399
|
+
:via => [:get, :post]
|
400
|
+
|
401
|
+
match "/users/auth/:action/callback",
|
402
|
+
:constraints => { :action => /\Agoogle|facebook\z/ },
|
403
|
+
:to => "devise/omniauth_callbacks",
|
404
|
+
:as => :omniauth_callback,
|
405
|
+
:via => [:get, :post]
|
406
|
+
ERROR
|
392
407
|
end
|
393
408
|
|
394
409
|
path, @scope[:path] = @scope[:path], nil
|
@@ -5,13 +5,16 @@ module Devise
|
|
5
5
|
# Default strategy for signing in a user, based on his email and password in the database.
|
6
6
|
class DatabaseAuthenticatable < Authenticatable
|
7
7
|
def authenticate!
|
8
|
-
resource
|
9
|
-
|
8
|
+
resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
|
9
|
+
encrypted = false
|
10
10
|
|
11
|
-
if validate(resource){ resource.valid_password?(password) }
|
11
|
+
if validate(resource){ encrypted = true; resource.valid_password?(password) }
|
12
12
|
resource.after_database_authentication
|
13
13
|
success!(resource)
|
14
14
|
end
|
15
|
+
|
16
|
+
mapping.to.new.password = password if !encrypted && Devise.paranoid
|
17
|
+
fail(:not_found_in_database) unless resource
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
data/lib/devise/version.rb
CHANGED
@@ -187,6 +187,23 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
|
187
187
|
assert_nil @controller.session[:"user_return_to"]
|
188
188
|
end
|
189
189
|
|
190
|
+
test 'store location for stores a location to redirect back to' do
|
191
|
+
assert_nil @controller.stored_location_for(:user)
|
192
|
+
@controller.store_location_for(:user, "/foo.bar")
|
193
|
+
assert_equal "/foo.bar", @controller.stored_location_for(:user)
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'store location for accepts a resource as argument' do
|
197
|
+
@controller.store_location_for(User.new, "/foo.bar")
|
198
|
+
assert_equal "/foo.bar", @controller.stored_location_for(User.new)
|
199
|
+
end
|
200
|
+
|
201
|
+
test 'store location for stores only paths' do
|
202
|
+
assert_nil @controller.stored_location_for(:user)
|
203
|
+
@controller.store_location_for(:user, "//host/foo.bar")
|
204
|
+
assert_equal "/foo.bar", @controller.stored_location_for(:user)
|
205
|
+
end
|
206
|
+
|
190
207
|
test 'after sign in path defaults to root path if none by was specified for the given scope' do
|
191
208
|
assert_equal root_path, @controller.after_sign_in_path_for(:user)
|
192
209
|
end
|
@@ -93,6 +93,11 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
|
93
93
|
assert_present user.encrypted_password
|
94
94
|
end
|
95
95
|
|
96
|
+
test 'should support custom encryption methods' do
|
97
|
+
user = UserWithCustomEncryption.new(:password => '654321')
|
98
|
+
assert_equal user.encrypted_password, '123456'
|
99
|
+
end
|
100
|
+
|
96
101
|
test 'allow authenticatable_salt to work even with nil encrypted password' do
|
97
102
|
user = User.new
|
98
103
|
user.encrypted_password = nil
|
@@ -2,7 +2,13 @@ unless defined?(DEVISE_ORM)
|
|
2
2
|
DEVISE_ORM = (ENV["DEVISE_ORM"] || :active_record).to_sym
|
3
3
|
end
|
4
4
|
|
5
|
+
module Devise
|
6
|
+
# Detection for minor differences between Rails 3.2 and 4 in tests.
|
7
|
+
def self.rails4?
|
8
|
+
Rails.version.start_with? '4'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
5
12
|
# Set up gems listed in the Gemfile.
|
6
13
|
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
|
7
|
-
|
8
14
|
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
@@ -22,10 +22,6 @@ RailsApp::Application.configure do
|
|
22
22
|
# Only use best-standards-support built into browsers.
|
23
23
|
config.action_dispatch.best_standards_support = :builtin
|
24
24
|
|
25
|
-
# Log the query plan for queries taking more than this (works
|
26
|
-
# with SQLite, MySQL, and PostgreSQL).
|
27
|
-
config.active_record.auto_explain_threshold_in_seconds = 0.5
|
28
|
-
|
29
25
|
# Raise an error on page load if there are pending migrations
|
30
26
|
config.active_record.migration_error = :page_load
|
31
27
|
|
@@ -72,10 +72,6 @@ RailsApp::Application.configure do
|
|
72
72
|
# Send deprecation notices to registered listeners.
|
73
73
|
config.active_support.deprecation = :notify
|
74
74
|
|
75
|
-
# Log the query plan for queries taking more than this (works
|
76
|
-
# with SQLite, MySQL, and PostgreSQL).
|
77
|
-
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
78
|
-
|
79
75
|
# Disable automatic flushing of the log to improve performance.
|
80
76
|
# config.autoflush_log = false
|
81
77
|
|
data/test/rails_app/db/schema.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
# This file is auto-generated from the current state of the database. Instead
|
2
3
|
# of editing this file, please use the migrations feature of Active Record to
|
3
4
|
# incrementally modify your database, and then regenerate this schema definition.
|
@@ -8,40 +9,43 @@
|
|
8
9
|
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
9
10
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
10
11
|
#
|
11
|
-
# It's strongly recommended
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
12
13
|
|
13
|
-
ActiveRecord::Schema.define(:
|
14
|
+
ActiveRecord::Schema.define(version: 20100401102949) do
|
14
15
|
|
15
|
-
create_table "admins", :
|
16
|
+
create_table "admins", force: true do |t|
|
16
17
|
t.string "email"
|
17
|
-
t.string "encrypted_password"
|
18
|
-
t.string "password_salt"
|
19
|
-
t.string "remember_token"
|
20
|
-
t.datetime "remember_created_at"
|
18
|
+
t.string "encrypted_password"
|
21
19
|
t.string "reset_password_token"
|
22
|
-
t.
|
23
|
-
t.
|
20
|
+
t.datetime "reset_password_sent_at"
|
21
|
+
t.datetime "remember_created_at"
|
22
|
+
t.string "confirmation_token"
|
23
|
+
t.datetime "confirmed_at"
|
24
|
+
t.datetime "confirmation_sent_at"
|
25
|
+
t.string "unconfirmed_email"
|
24
26
|
t.datetime "locked_at"
|
27
|
+
t.boolean "active", default: false
|
25
28
|
t.datetime "created_at"
|
26
29
|
t.datetime "updated_at"
|
27
30
|
end
|
28
31
|
|
29
|
-
create_table "users", :
|
32
|
+
create_table "users", force: true do |t|
|
30
33
|
t.string "username"
|
31
34
|
t.string "facebook_token"
|
32
|
-
t.string "email",
|
33
|
-
t.string "encrypted_password",
|
34
|
-
t.string "confirmation_token"
|
35
|
-
t.datetime "confirmed_at"
|
36
|
-
t.datetime "confirmation_sent_at"
|
35
|
+
t.string "email", default: "", null: false
|
36
|
+
t.string "encrypted_password", default: "", null: false
|
37
37
|
t.string "reset_password_token"
|
38
|
+
t.datetime "reset_password_sent_at"
|
38
39
|
t.datetime "remember_created_at"
|
39
|
-
t.integer "sign_in_count",
|
40
|
+
t.integer "sign_in_count", default: 0
|
40
41
|
t.datetime "current_sign_in_at"
|
41
42
|
t.datetime "last_sign_in_at"
|
42
43
|
t.string "current_sign_in_ip"
|
43
44
|
t.string "last_sign_in_ip"
|
44
|
-
t.
|
45
|
+
t.string "confirmation_token"
|
46
|
+
t.datetime "confirmed_at"
|
47
|
+
t.datetime "confirmation_sent_at"
|
48
|
+
t.integer "failed_attempts", default: 0
|
45
49
|
t.string "unlock_token"
|
46
50
|
t.datetime "locked_at"
|
47
51
|
t.datetime "created_at"
|
data/test/test_helper.rb
CHANGED
@@ -4,13 +4,6 @@ DEVISE_ORM = (ENV["DEVISE_ORM"] || :active_record).to_sym
|
|
4
4
|
$:.unshift File.dirname(__FILE__)
|
5
5
|
puts "\n==> Devise.orm = #{DEVISE_ORM.inspect}"
|
6
6
|
|
7
|
-
module Devise
|
8
|
-
# Detection for minor differences between Rails 3.2 and 4 in tests.
|
9
|
-
def self.rails4?
|
10
|
-
Rails.version.start_with? '4'
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
7
|
require "rails_app/config/environment"
|
15
8
|
require "rails/test_help"
|
16
9
|
require "orm/#{DEVISE_ORM}"
|
data/test/test_models.rb
CHANGED
@@ -12,6 +12,13 @@ class UserWithValidation < User
|
|
12
12
|
validates_presence_of :username
|
13
13
|
end
|
14
14
|
|
15
|
+
class UserWithCustomEncryption < User
|
16
|
+
protected
|
17
|
+
def password_digest(password)
|
18
|
+
password.reverse
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
15
22
|
class UserWithVirtualAttributes < User
|
16
23
|
devise :case_insensitive_keys => [ :email, :email_confirmation ]
|
17
24
|
validates :email, :presence => true, :confirmation => {:on => :create}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-11-
|
13
|
+
date: 2013-11-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: warden
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- lib/devise/controllers/rememberable.rb
|
145
145
|
- lib/devise/controllers/scoped_views.rb
|
146
146
|
- lib/devise/controllers/sign_in_out.rb
|
147
|
+
- lib/devise/controllers/store_location.rb
|
147
148
|
- lib/devise/controllers/url_helpers.rb
|
148
149
|
- lib/devise/delegator.rb
|
149
150
|
- lib/devise/failure_app.rb
|