devise 3.5.2 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +259 -1086
- data/MIT-LICENSE +1 -1
- data/README.md +254 -67
- data/app/controllers/devise/confirmations_controller.rb +3 -1
- data/app/controllers/devise/omniauth_callbacks_controller.rb +8 -6
- data/app/controllers/devise/passwords_controller.rb +8 -4
- data/app/controllers/devise/registrations_controller.rb +39 -18
- data/app/controllers/devise/sessions_controller.rb +9 -7
- data/app/controllers/devise/unlocks_controller.rb +4 -2
- data/app/controllers/devise_controller.rb +23 -10
- data/app/helpers/devise_helper.rb +12 -19
- data/app/mailers/devise/mailer.rb +10 -0
- data/app/views/devise/confirmations/new.html.erb +2 -2
- data/app/views/devise/mailer/email_changed.html.erb +7 -0
- data/app/views/devise/mailer/password_change.html.erb +3 -0
- data/app/views/devise/passwords/edit.html.erb +3 -3
- data/app/views/devise/passwords/new.html.erb +2 -2
- data/app/views/devise/registrations/edit.html.erb +9 -5
- data/app/views/devise/registrations/new.html.erb +4 -4
- data/app/views/devise/sessions/new.html.erb +4 -4
- data/app/views/devise/shared/_error_messages.html.erb +15 -0
- data/app/views/devise/shared/_links.html.erb +8 -8
- data/app/views/devise/unlocks/new.html.erb +2 -2
- data/config/locales/en.yml +6 -1
- data/lib/devise/controllers/helpers.rb +35 -26
- data/lib/devise/controllers/rememberable.rb +11 -2
- data/lib/devise/controllers/scoped_views.rb +2 -0
- data/lib/devise/controllers/sign_in_out.rb +34 -11
- data/lib/devise/controllers/store_location.rb +25 -7
- data/lib/devise/controllers/url_helpers.rb +2 -0
- data/lib/devise/delegator.rb +2 -0
- data/lib/devise/encryptor.rb +6 -4
- data/lib/devise/failure_app.rb +84 -32
- data/lib/devise/hooks/activatable.rb +2 -0
- data/lib/devise/hooks/csrf_cleaner.rb +2 -0
- data/lib/devise/hooks/forgetable.rb +2 -0
- data/lib/devise/hooks/lockable.rb +6 -1
- data/lib/devise/hooks/proxy.rb +3 -1
- data/lib/devise/hooks/rememberable.rb +2 -0
- data/lib/devise/hooks/timeoutable.rb +7 -3
- data/lib/devise/hooks/trackable.rb +2 -0
- data/lib/devise/mailers/helpers.rb +7 -4
- data/lib/devise/mapping.rb +2 -0
- data/lib/devise/models/authenticatable.rb +51 -26
- data/lib/devise/models/confirmable.rb +89 -27
- data/lib/devise/models/database_authenticatable.rb +97 -20
- data/lib/devise/models/lockable.rb +15 -5
- data/lib/devise/models/omniauthable.rb +2 -0
- data/lib/devise/models/recoverable.rb +32 -24
- data/lib/devise/models/registerable.rb +4 -0
- data/lib/devise/models/rememberable.rb +42 -26
- data/lib/devise/models/timeoutable.rb +2 -6
- data/lib/devise/models/trackable.rb +15 -1
- data/lib/devise/models/validatable.rb +10 -3
- data/lib/devise/models.rb +3 -1
- data/lib/devise/modules.rb +2 -0
- data/lib/devise/omniauth/config.rb +2 -0
- data/lib/devise/omniauth/url_helpers.rb +14 -5
- data/lib/devise/omniauth.rb +2 -0
- data/lib/devise/orm/active_record.rb +5 -1
- data/lib/devise/orm/mongoid.rb +6 -2
- data/lib/devise/parameter_filter.rb +4 -0
- data/lib/devise/parameter_sanitizer.rb +139 -65
- data/lib/devise/rails/routes.rb +59 -34
- data/lib/devise/rails/warden_compat.rb +3 -10
- data/lib/devise/rails.rb +7 -16
- data/lib/devise/secret_key_finder.rb +27 -0
- data/lib/devise/strategies/authenticatable.rb +4 -2
- data/lib/devise/strategies/base.rb +2 -0
- data/lib/devise/strategies/database_authenticatable.rb +11 -4
- data/lib/devise/strategies/rememberable.rb +5 -6
- data/lib/devise/test/controller_helpers.rb +165 -0
- data/lib/devise/test/integration_helpers.rb +63 -0
- data/lib/devise/test_helpers.rb +7 -124
- data/lib/devise/time_inflector.rb +2 -0
- data/lib/devise/token_generator.rb +3 -41
- data/lib/devise/version.rb +3 -1
- data/lib/devise.rb +72 -42
- data/lib/generators/active_record/devise_generator.rb +29 -10
- data/lib/generators/active_record/templates/migration.rb +4 -2
- data/lib/generators/active_record/templates/migration_existing.rb +4 -2
- data/lib/generators/devise/controllers_generator.rb +3 -1
- data/lib/generators/devise/devise_generator.rb +4 -2
- data/lib/generators/devise/install_generator.rb +17 -0
- data/lib/generators/devise/orm_helpers.rb +10 -21
- data/lib/generators/devise/views_generator.rb +21 -11
- data/lib/generators/mongoid/devise_generator.rb +7 -5
- data/lib/generators/templates/README +1 -8
- data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +2 -0
- data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +6 -4
- data/lib/generators/templates/controllers/sessions_controller.rb +4 -2
- data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
- data/lib/generators/templates/devise.rb +52 -19
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/email_changed.markerb +7 -0
- data/lib/generators/templates/markerb/password_change.markerb +3 -0
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
- data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
- metadata +27 -313
- data/.gitignore +0 -10
- data/.travis.yml +0 -45
- data/.yardopts +0 -9
- data/CONTRIBUTING.md +0 -14
- data/Gemfile +0 -29
- data/Gemfile.lock +0 -183
- data/Rakefile +0 -36
- data/devise.gemspec +0 -27
- data/devise.png +0 -0
- data/gemfiles/Gemfile.rails-3.2-stable +0 -29
- data/gemfiles/Gemfile.rails-3.2-stable.lock +0 -169
- data/gemfiles/Gemfile.rails-4.0-stable +0 -29
- data/gemfiles/Gemfile.rails-4.0-stable.lock +0 -163
- data/gemfiles/Gemfile.rails-4.1-stable +0 -29
- data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -169
- data/gemfiles/Gemfile.rails-4.2-stable +0 -29
- data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -191
- data/script/cached-bundle +0 -49
- data/script/s3-put +0 -71
- data/test/controllers/custom_registrations_controller_test.rb +0 -40
- data/test/controllers/custom_strategy_test.rb +0 -62
- data/test/controllers/helpers_test.rb +0 -316
- data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
- data/test/controllers/internal_helpers_test.rb +0 -129
- data/test/controllers/load_hooks_controller_test.rb +0 -19
- data/test/controllers/passwords_controller_test.rb +0 -31
- data/test/controllers/sessions_controller_test.rb +0 -103
- data/test/controllers/url_helpers_test.rb +0 -65
- data/test/delegator_test.rb +0 -19
- data/test/devise_test.rb +0 -107
- data/test/failure_app_test.rb +0 -298
- data/test/generators/active_record_generator_test.rb +0 -109
- data/test/generators/controllers_generator_test.rb +0 -48
- data/test/generators/devise_generator_test.rb +0 -39
- data/test/generators/install_generator_test.rb +0 -13
- data/test/generators/mongoid_generator_test.rb +0 -23
- data/test/generators/views_generator_test.rb +0 -96
- data/test/helpers/devise_helper_test.rb +0 -49
- data/test/integration/authenticatable_test.rb +0 -729
- data/test/integration/confirmable_test.rb +0 -324
- data/test/integration/database_authenticatable_test.rb +0 -95
- data/test/integration/http_authenticatable_test.rb +0 -105
- data/test/integration/lockable_test.rb +0 -239
- data/test/integration/omniauthable_test.rb +0 -133
- data/test/integration/recoverable_test.rb +0 -347
- data/test/integration/registerable_test.rb +0 -359
- data/test/integration/rememberable_test.rb +0 -176
- data/test/integration/timeoutable_test.rb +0 -172
- data/test/integration/trackable_test.rb +0 -92
- data/test/mailers/confirmation_instructions_test.rb +0 -115
- data/test/mailers/reset_password_instructions_test.rb +0 -96
- data/test/mailers/unlock_instructions_test.rb +0 -91
- data/test/mapping_test.rb +0 -134
- data/test/models/authenticatable_test.rb +0 -23
- data/test/models/confirmable_test.rb +0 -479
- data/test/models/database_authenticatable_test.rb +0 -249
- data/test/models/lockable_test.rb +0 -328
- data/test/models/omniauthable_test.rb +0 -7
- data/test/models/recoverable_test.rb +0 -228
- data/test/models/registerable_test.rb +0 -7
- data/test/models/rememberable_test.rb +0 -204
- data/test/models/serializable_test.rb +0 -49
- data/test/models/timeoutable_test.rb +0 -51
- data/test/models/trackable_test.rb +0 -41
- data/test/models/validatable_test.rb +0 -127
- data/test/models_test.rb +0 -144
- data/test/omniauth/config_test.rb +0 -57
- data/test/omniauth/url_helpers_test.rb +0 -54
- data/test/orm/active_record.rb +0 -10
- data/test/orm/mongoid.rb +0 -13
- data/test/parameter_sanitizer_test.rb +0 -81
- data/test/rails_app/Rakefile +0 -6
- data/test/rails_app/app/active_record/admin.rb +0 -6
- data/test/rails_app/app/active_record/shim.rb +0 -2
- data/test/rails_app/app/active_record/user.rb +0 -6
- data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
- data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
- data/test/rails_app/app/controllers/admins_controller.rb +0 -6
- data/test/rails_app/app/controllers/application_controller.rb +0 -12
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
- data/test/rails_app/app/controllers/home_controller.rb +0 -25
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
- data/test/rails_app/app/controllers/users_controller.rb +0 -31
- data/test/rails_app/app/helpers/application_helper.rb +0 -3
- data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
- data/test/rails_app/app/mongoid/admin.rb +0 -29
- data/test/rails_app/app/mongoid/shim.rb +0 -23
- data/test/rails_app/app/mongoid/user.rb +0 -39
- data/test/rails_app/app/mongoid/user_on_engine.rb +0 -39
- data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
- data/test/rails_app/app/views/admins/index.html.erb +0 -1
- data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/home/index.html.erb +0 -1
- data/test/rails_app/app/views/home/join.html.erb +0 -1
- data/test/rails_app/app/views/home/private.html.erb +0 -1
- data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/layouts/application.html.erb +0 -24
- data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
- data/test/rails_app/app/views/users/index.html.erb +0 -1
- data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
- data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
- data/test/rails_app/bin/bundle +0 -3
- data/test/rails_app/bin/rails +0 -4
- data/test/rails_app/bin/rake +0 -4
- data/test/rails_app/config/application.rb +0 -40
- data/test/rails_app/config/boot.rb +0 -14
- data/test/rails_app/config/database.yml +0 -18
- data/test/rails_app/config/environment.rb +0 -5
- data/test/rails_app/config/environments/development.rb +0 -30
- data/test/rails_app/config/environments/production.rb +0 -84
- data/test/rails_app/config/environments/test.rb +0 -41
- data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test/rails_app/config/initializers/devise.rb +0 -180
- data/test/rails_app/config/initializers/inflections.rb +0 -2
- data/test/rails_app/config/initializers/secret_token.rb +0 -8
- data/test/rails_app/config/initializers/session_store.rb +0 -1
- data/test/rails_app/config/routes.rb +0 -120
- data/test/rails_app/config.ru +0 -4
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
- data/test/rails_app/db/schema.rb +0 -55
- data/test/rails_app/lib/shared_admin.rb +0 -17
- data/test/rails_app/lib/shared_user.rb +0 -29
- data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
- data/test/rails_app/public/404.html +0 -26
- data/test/rails_app/public/422.html +0 -26
- data/test/rails_app/public/500.html +0 -26
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_test.rb +0 -9
- data/test/routes_test.rb +0 -264
- data/test/support/action_controller/record_identifier.rb +0 -10
- data/test/support/assertions.rb +0 -39
- data/test/support/helpers.rb +0 -73
- data/test/support/integration.rb +0 -92
- data/test/support/locale/en.yml +0 -8
- data/test/support/mongoid.yml +0 -6
- data/test/support/webrat/integrations/rails.rb +0 -24
- data/test/test_helper.rb +0 -34
- data/test/test_helpers_test.rb +0 -178
- data/test/test_models.rb +0 -33
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Test
|
5
|
+
# `Devise::Test::ControllerHelpers` provides a facility to test controllers
|
6
|
+
# in isolation when using `ActionController::TestCase` allowing you to
|
7
|
+
# quickly sign_in or sign_out a user. Do not use
|
8
|
+
# `Devise::Test::ControllerHelpers` in integration tests.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# class PostsTest < ActionController::TestCase
|
13
|
+
# include Devise::Test::ControllerHelpers
|
14
|
+
#
|
15
|
+
# test 'authenticated users can GET index' do
|
16
|
+
# sign_in users(:bob)
|
17
|
+
#
|
18
|
+
# get :index
|
19
|
+
# assert_response :success
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Important: you should not test Warden specific behavior (like callbacks)
|
24
|
+
# using `Devise::Test::ControllerHelpers` since it is a stub of the actual
|
25
|
+
# behavior. Such callbacks should be tested in your integration suite instead.
|
26
|
+
module ControllerHelpers
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
included do
|
30
|
+
setup :setup_controller_for_warden, :warden
|
31
|
+
end
|
32
|
+
|
33
|
+
# Override process to consider warden.
|
34
|
+
def process(*)
|
35
|
+
_catch_warden { super }
|
36
|
+
|
37
|
+
@response
|
38
|
+
end
|
39
|
+
|
40
|
+
# We need to set up the environment variables and the response in the controller.
|
41
|
+
def setup_controller_for_warden #:nodoc:
|
42
|
+
@request.env['action_controller.instance'] = @controller
|
43
|
+
end
|
44
|
+
|
45
|
+
# Quick access to Warden::Proxy.
|
46
|
+
def warden #:nodoc:
|
47
|
+
@request.env['warden'] ||= begin
|
48
|
+
manager = Warden::Manager.new(nil) do |config|
|
49
|
+
config.merge! Devise.warden_config
|
50
|
+
end
|
51
|
+
Warden::Proxy.new(@request.env, manager)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# sign_in a given resource by storing its keys in the session.
|
56
|
+
# This method bypass any warden authentication callback.
|
57
|
+
#
|
58
|
+
# * +resource+ - The resource that should be authenticated
|
59
|
+
# * +scope+ - An optional +Symbol+ with the scope where the resource
|
60
|
+
# should be signed in with.
|
61
|
+
# Examples:
|
62
|
+
#
|
63
|
+
# sign_in users(:alice)
|
64
|
+
# sign_in users(:alice), scope: :admin
|
65
|
+
def sign_in(resource, deprecated = nil, scope: nil)
|
66
|
+
if deprecated.present?
|
67
|
+
scope = resource
|
68
|
+
resource = deprecated
|
69
|
+
|
70
|
+
ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
|
71
|
+
[Devise] sign_in(:#{scope}, resource) on controller tests is deprecated and will be removed from Devise.
|
72
|
+
Please use sign_in(resource, scope: :#{scope}) instead.
|
73
|
+
DEPRECATION
|
74
|
+
end
|
75
|
+
|
76
|
+
scope ||= Devise::Mapping.find_scope!(resource)
|
77
|
+
|
78
|
+
warden.instance_variable_get(:@users).delete(scope)
|
79
|
+
warden.session_serializer.store(resource, scope)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Sign out a given resource or scope by calling logout on Warden.
|
83
|
+
# This method bypass any warden logout callback.
|
84
|
+
#
|
85
|
+
# Examples:
|
86
|
+
#
|
87
|
+
# sign_out :user # sign_out(scope)
|
88
|
+
# sign_out @user # sign_out(resource)
|
89
|
+
#
|
90
|
+
def sign_out(resource_or_scope)
|
91
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
92
|
+
@controller.instance_variable_set(:"@current_#{scope}", nil)
|
93
|
+
user = warden.instance_variable_get(:@users).delete(scope)
|
94
|
+
warden.session_serializer.delete(scope, user)
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
# Catch warden continuations and handle like the middleware would.
|
100
|
+
# Returns nil when interrupted, otherwise the normal result of the block.
|
101
|
+
def _catch_warden(&block)
|
102
|
+
result = catch(:warden, &block)
|
103
|
+
|
104
|
+
env = @controller.request.env
|
105
|
+
|
106
|
+
result ||= {}
|
107
|
+
|
108
|
+
# Set the response. In production, the rack result is returned
|
109
|
+
# from Warden::Manager#call, which the following is modelled on.
|
110
|
+
case result
|
111
|
+
when Array
|
112
|
+
if result.first == 401 && intercept_401?(env) # does this happen during testing?
|
113
|
+
_process_unauthenticated(env)
|
114
|
+
else
|
115
|
+
result
|
116
|
+
end
|
117
|
+
when Hash
|
118
|
+
_process_unauthenticated(env, result)
|
119
|
+
else
|
120
|
+
result
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def _process_unauthenticated(env, options = {})
|
125
|
+
options[:action] ||= :unauthenticated
|
126
|
+
proxy = request.env['warden']
|
127
|
+
result = options[:result] || proxy.result
|
128
|
+
|
129
|
+
ret = case result
|
130
|
+
when :redirect
|
131
|
+
body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
|
132
|
+
[proxy.status, proxy.headers, [body]]
|
133
|
+
when :custom
|
134
|
+
proxy.custom_response
|
135
|
+
else
|
136
|
+
request.env["PATH_INFO"] = "/#{options[:action]}"
|
137
|
+
request.env["warden.options"] = options
|
138
|
+
Warden::Manager._run_callbacks(:before_failure, env, options)
|
139
|
+
|
140
|
+
status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
|
141
|
+
@controller.response.headers.merge!(headers)
|
142
|
+
@controller.response.content_type = headers["Content-Type"] unless Rails::VERSION::MAJOR >= 5
|
143
|
+
@controller.status = status
|
144
|
+
@controller.response.body = response.body
|
145
|
+
nil # causes process return @response
|
146
|
+
end
|
147
|
+
|
148
|
+
# ensure that the controller response is set up. In production, this is
|
149
|
+
# not necessary since warden returns the results to rack. However, at
|
150
|
+
# testing time, we want the response to be available to the testing
|
151
|
+
# framework to verify what would be returned to rack.
|
152
|
+
if ret.is_a?(Array)
|
153
|
+
status, headers, body = *ret
|
154
|
+
# ensure the controller response is set to our response.
|
155
|
+
@controller.response ||= @response
|
156
|
+
@response.status = status
|
157
|
+
@response.headers.merge!(headers)
|
158
|
+
@response.body = body
|
159
|
+
end
|
160
|
+
|
161
|
+
ret
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
# Devise::Test::IntegrationHelpers is a helper module for facilitating
|
5
|
+
# authentication on Rails integration tests to bypass the required steps for
|
6
|
+
# signin in or signin out a record.
|
7
|
+
#
|
8
|
+
# Examples
|
9
|
+
#
|
10
|
+
# class PostsTest < ActionDispatch::IntegrationTest
|
11
|
+
# include Devise::Test::IntegrationHelpers
|
12
|
+
#
|
13
|
+
# test 'authenticated users can see posts' do
|
14
|
+
# sign_in users(:bob)
|
15
|
+
#
|
16
|
+
# get '/posts'
|
17
|
+
# assert_response :success
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
module Test
|
21
|
+
module IntegrationHelpers
|
22
|
+
def self.included(base)
|
23
|
+
base.class_eval do
|
24
|
+
include Warden::Test::Helpers
|
25
|
+
|
26
|
+
setup :setup_integration_for_devise
|
27
|
+
teardown :teardown_integration_for_devise
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Signs in a specific resource, mimicking a successfull sign in
|
32
|
+
# operation through +Devise::SessionsController#create+.
|
33
|
+
#
|
34
|
+
# * +resource+ - The resource that should be authenticated
|
35
|
+
# * +scope+ - An optional +Symbol+ with the scope where the resource
|
36
|
+
# should be signed in with.
|
37
|
+
def sign_in(resource, scope: nil)
|
38
|
+
scope ||= Devise::Mapping.find_scope!(resource)
|
39
|
+
|
40
|
+
login_as(resource, scope: scope)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Signs out a specific scope from the session.
|
44
|
+
#
|
45
|
+
# * +resource_or_scope+ - The resource or scope that should be signed out.
|
46
|
+
def sign_out(resource_or_scope)
|
47
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
48
|
+
|
49
|
+
logout scope
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def setup_integration_for_devise
|
55
|
+
Warden.test_mode!
|
56
|
+
end
|
57
|
+
|
58
|
+
def teardown_integration_for_devise
|
59
|
+
Warden.test_reset!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/devise/test_helpers.rb
CHANGED
@@ -1,132 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
|
-
# Devise::TestHelpers provides a facility to test controllers in isolation
|
3
|
-
# when using ActionController::TestCase allowing you to quickly sign_in or
|
4
|
-
# sign_out a user. Do not use Devise::TestHelpers in integration tests.
|
5
|
-
#
|
6
|
-
# Notice you should not test Warden specific behavior (like Warden callbacks)
|
7
|
-
# using Devise::TestHelpers since it is a stub of the actual behavior. Such
|
8
|
-
# callbacks should be tested in your integration suite instead.
|
9
4
|
module TestHelpers
|
10
5
|
def self.included(base)
|
11
6
|
base.class_eval do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def process(*)
|
18
|
-
# Make sure we always return @response, a la ActionController::TestCase::Behaviour#process, even if warden interrupts
|
19
|
-
_catch_warden { super } || @response
|
20
|
-
end
|
21
|
-
|
22
|
-
# We need to setup the environment variables and the response in the controller.
|
23
|
-
def setup_controller_for_warden #:nodoc:
|
24
|
-
@request.env['action_controller.instance'] = @controller
|
25
|
-
end
|
26
|
-
|
27
|
-
# Quick access to Warden::Proxy.
|
28
|
-
def warden #:nodoc:
|
29
|
-
@request.env['warden'] ||= begin
|
30
|
-
manager = Warden::Manager.new(nil) do |config|
|
31
|
-
config.merge! Devise.warden_config
|
32
|
-
end
|
33
|
-
Warden::Proxy.new(@request.env, manager)
|
7
|
+
ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
|
8
|
+
[Devise] including `Devise::TestHelpers` is deprecated and will be removed from Devise.
|
9
|
+
For controller tests, please include `Devise::Test::ControllerHelpers` instead.
|
10
|
+
DEPRECATION
|
11
|
+
include Devise::Test::ControllerHelpers
|
34
12
|
end
|
35
13
|
end
|
36
|
-
|
37
|
-
# sign_in a given resource by storing its keys in the session.
|
38
|
-
# This method bypass any warden authentication callback.
|
39
|
-
#
|
40
|
-
# Examples:
|
41
|
-
#
|
42
|
-
# sign_in :user, @user # sign_in(scope, resource)
|
43
|
-
# sign_in @user # sign_in(resource)
|
44
|
-
#
|
45
|
-
def sign_in(resource_or_scope, resource=nil)
|
46
|
-
scope ||= Devise::Mapping.find_scope!(resource_or_scope)
|
47
|
-
resource ||= resource_or_scope
|
48
|
-
warden.instance_variable_get(:@users).delete(scope)
|
49
|
-
warden.session_serializer.store(resource, scope)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Sign out a given resource or scope by calling logout on Warden.
|
53
|
-
# This method bypass any warden logout callback.
|
54
|
-
#
|
55
|
-
# Examples:
|
56
|
-
#
|
57
|
-
# sign_out :user # sign_out(scope)
|
58
|
-
# sign_out @user # sign_out(resource)
|
59
|
-
#
|
60
|
-
def sign_out(resource_or_scope)
|
61
|
-
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
62
|
-
@controller.instance_variable_set(:"@current_#{scope}", nil)
|
63
|
-
user = warden.instance_variable_get(:@users).delete(scope)
|
64
|
-
warden.session_serializer.delete(scope, user)
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
# Catch warden continuations and handle like the middleware would.
|
70
|
-
# Returns nil when interrupted, otherwise the normal result of the block.
|
71
|
-
def _catch_warden(&block)
|
72
|
-
result = catch(:warden, &block)
|
73
|
-
|
74
|
-
env = @controller.request.env
|
75
|
-
|
76
|
-
result ||= {}
|
77
|
-
|
78
|
-
# Set the response. In production, the rack result is returned
|
79
|
-
# from Warden::Manager#call, which the following is modelled on.
|
80
|
-
case result
|
81
|
-
when Array
|
82
|
-
if result.first == 401 && intercept_401?(env) # does this happen during testing?
|
83
|
-
_process_unauthenticated(env)
|
84
|
-
else
|
85
|
-
result
|
86
|
-
end
|
87
|
-
when Hash
|
88
|
-
_process_unauthenticated(env, result)
|
89
|
-
else
|
90
|
-
result
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def _process_unauthenticated(env, options = {})
|
95
|
-
options[:action] ||= :unauthenticated
|
96
|
-
proxy = env['warden']
|
97
|
-
result = options[:result] || proxy.result
|
98
|
-
|
99
|
-
ret = case result
|
100
|
-
when :redirect
|
101
|
-
body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
|
102
|
-
[proxy.status, proxy.headers, [body]]
|
103
|
-
when :custom
|
104
|
-
proxy.custom_response
|
105
|
-
else
|
106
|
-
env["PATH_INFO"] = "/#{options[:action]}"
|
107
|
-
env["warden.options"] = options
|
108
|
-
Warden::Manager._run_callbacks(:before_failure, env, options)
|
109
|
-
|
110
|
-
status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
|
111
|
-
@controller.response.headers.merge!(headers)
|
112
|
-
@controller.send :render, status: status, text: response.body,
|
113
|
-
content_type: headers["Content-Type"], location: headers["Location"]
|
114
|
-
nil # causes process return @response
|
115
|
-
end
|
116
|
-
|
117
|
-
# ensure that the controller response is set up. In production, this is
|
118
|
-
# not necessary since warden returns the results to rack. However, at
|
119
|
-
# testing time, we want the response to be available to the testing
|
120
|
-
# framework to verify what would be returned to rack.
|
121
|
-
if ret.is_a?(Array)
|
122
|
-
# ensure the controller response is set to our response.
|
123
|
-
@controller.response ||= @response
|
124
|
-
@response.status = ret.first
|
125
|
-
@response.headers = ret.second
|
126
|
-
@response.body = ret.third
|
127
|
-
end
|
128
|
-
|
129
|
-
ret
|
130
|
-
end
|
131
14
|
end
|
132
15
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require 'openssl'
|
4
|
-
require 'securerandom'
|
5
4
|
|
6
5
|
module Devise
|
7
6
|
class TokenGenerator
|
8
|
-
def initialize(key_generator, digest="SHA256")
|
7
|
+
def initialize(key_generator, digest = "SHA256")
|
9
8
|
@key_generator = key_generator
|
10
9
|
@digest = digest
|
11
10
|
end
|
@@ -30,41 +29,4 @@ module Devise
|
|
30
29
|
@key_generator.generate_key("Devise #{column}")
|
31
30
|
end
|
32
31
|
end
|
33
|
-
|
34
|
-
# KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
|
35
|
-
# It can be used to derive a number of keys for various purposes from a given secret.
|
36
|
-
# This lets Rails applications have a single secure secret, but avoid reusing that
|
37
|
-
# key in multiple incompatible contexts.
|
38
|
-
class KeyGenerator
|
39
|
-
def initialize(secret, options = {})
|
40
|
-
@secret = secret
|
41
|
-
# The default iterations are higher than required for our key derivation uses
|
42
|
-
# on the off chance someone uses this for password storage
|
43
|
-
@iterations = options[:iterations] || 2**16
|
44
|
-
end
|
45
|
-
|
46
|
-
# Returns a derived key suitable for use. The default key_size is chosen
|
47
|
-
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
48
|
-
# i.e. OpenSSL::Digest::SHA1#block_length
|
49
|
-
def generate_key(salt, key_size=64)
|
50
|
-
OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
|
55
|
-
# re-executing the key generation process when it's called using the same salt and
|
56
|
-
# key_size
|
57
|
-
class CachingKeyGenerator
|
58
|
-
def initialize(key_generator)
|
59
|
-
@key_generator = key_generator
|
60
|
-
@cache_keys = ThreadSafe::Cache.new
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns a derived key suitable for use. The default key_size is chosen
|
64
|
-
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
65
|
-
# i.e. OpenSSL::Digest::SHA1#block_length
|
66
|
-
def generate_key(salt, key_size=64)
|
67
|
-
@cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
|
68
|
-
end
|
69
|
-
end
|
70
32
|
end
|
data/lib/devise/version.rb
CHANGED
data/lib/devise.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails'
|
2
4
|
require 'active_support/core_ext/numeric/time'
|
3
5
|
require 'active_support/dependencies'
|
@@ -12,19 +14,19 @@ module Devise
|
|
12
14
|
autoload :FailureApp, 'devise/failure_app'
|
13
15
|
autoload :OmniAuth, 'devise/omniauth'
|
14
16
|
autoload :ParameterFilter, 'devise/parameter_filter'
|
15
|
-
autoload :BaseSanitizer, 'devise/parameter_sanitizer'
|
16
17
|
autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
|
17
18
|
autoload :TestHelpers, 'devise/test_helpers'
|
18
19
|
autoload :TimeInflector, 'devise/time_inflector'
|
19
20
|
autoload :TokenGenerator, 'devise/token_generator'
|
21
|
+
autoload :SecretKeyFinder, 'devise/secret_key_finder'
|
20
22
|
|
21
23
|
module Controllers
|
22
|
-
autoload :Helpers,
|
23
|
-
autoload :Rememberable,
|
24
|
-
autoload :ScopedViews,
|
25
|
-
autoload :SignInOut,
|
26
|
-
autoload :StoreLocation,
|
27
|
-
autoload :UrlHelpers,
|
24
|
+
autoload :Helpers, 'devise/controllers/helpers'
|
25
|
+
autoload :Rememberable, 'devise/controllers/rememberable'
|
26
|
+
autoload :ScopedViews, 'devise/controllers/scoped_views'
|
27
|
+
autoload :SignInOut, 'devise/controllers/sign_in_out'
|
28
|
+
autoload :StoreLocation, 'devise/controllers/store_location'
|
29
|
+
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
28
30
|
end
|
29
31
|
|
30
32
|
module Hooks
|
@@ -36,17 +38,22 @@ module Devise
|
|
36
38
|
end
|
37
39
|
|
38
40
|
module Strategies
|
39
|
-
autoload :Base,
|
41
|
+
autoload :Base, 'devise/strategies/base'
|
40
42
|
autoload :Authenticatable, 'devise/strategies/authenticatable'
|
41
43
|
end
|
42
44
|
|
45
|
+
module Test
|
46
|
+
autoload :ControllerHelpers, 'devise/test/controller_helpers'
|
47
|
+
autoload :IntegrationHelpers, 'devise/test/integration_helpers'
|
48
|
+
end
|
49
|
+
|
43
50
|
# Constants which holds devise configuration for extensions. Those should
|
44
51
|
# not be modified by the "end user" (this is why they are constants).
|
45
52
|
ALL = []
|
46
|
-
CONTROLLERS =
|
47
|
-
ROUTES =
|
48
|
-
STRATEGIES =
|
49
|
-
URL_HELPERS =
|
53
|
+
CONTROLLERS = {}
|
54
|
+
ROUTES = {}
|
55
|
+
STRATEGIES = {}
|
56
|
+
URL_HELPERS = {}
|
50
57
|
|
51
58
|
# Strategies that do not require user input.
|
52
59
|
NO_INPUT = []
|
@@ -62,9 +69,9 @@ module Devise
|
|
62
69
|
mattr_accessor :rememberable_options
|
63
70
|
@@rememberable_options = {}
|
64
71
|
|
65
|
-
# The number of times to
|
72
|
+
# The number of times to hash the password.
|
66
73
|
mattr_accessor :stretches
|
67
|
-
@@stretches =
|
74
|
+
@@stretches = 11
|
68
75
|
|
69
76
|
# The default key used when authenticating over http auth.
|
70
77
|
mattr_accessor :http_authentication_key
|
@@ -84,7 +91,7 @@ module Devise
|
|
84
91
|
|
85
92
|
# Keys that should have whitespace stripped.
|
86
93
|
mattr_accessor :strip_whitespace_keys
|
87
|
-
@@strip_whitespace_keys = []
|
94
|
+
@@strip_whitespace_keys = [:email]
|
88
95
|
|
89
96
|
# If http authentication is enabled by default.
|
90
97
|
mattr_accessor :http_authenticatable
|
@@ -102,11 +109,11 @@ module Devise
|
|
102
109
|
mattr_accessor :http_authentication_realm
|
103
110
|
@@http_authentication_realm = "Application"
|
104
111
|
|
105
|
-
# Email regex used to validate email formats. It
|
106
|
-
#
|
107
|
-
#
|
112
|
+
# Email regex used to validate email formats. It asserts that there are no
|
113
|
+
# @ symbols or whitespaces in either the localpart or the domain, and that
|
114
|
+
# there is a single @ symbol separating the localpart and the domain.
|
108
115
|
mattr_accessor :email_regexp
|
109
|
-
@@email_regexp = /\A[^@\s]+@
|
116
|
+
@@email_regexp = /\A[^@\s]+@[^@\s]+\z/
|
110
117
|
|
111
118
|
# Range validation for password length
|
112
119
|
mattr_accessor :password_length
|
@@ -138,18 +145,25 @@ module Devise
|
|
138
145
|
@@confirmation_keys = [:email]
|
139
146
|
|
140
147
|
# Defines if email should be reconfirmable.
|
141
|
-
# False by default for backwards compatibility.
|
142
148
|
mattr_accessor :reconfirmable
|
143
|
-
@@reconfirmable =
|
149
|
+
@@reconfirmable = true
|
144
150
|
|
145
151
|
# Time interval to timeout the user session without activity.
|
146
152
|
mattr_accessor :timeout_in
|
147
153
|
@@timeout_in = 30.minutes
|
148
154
|
|
149
|
-
# Used to
|
155
|
+
# Used to hash the password. Please generate one with rails secret.
|
150
156
|
mattr_accessor :pepper
|
151
157
|
@@pepper = nil
|
152
158
|
|
159
|
+
# Used to send notification to the original user email when their email is changed.
|
160
|
+
mattr_accessor :send_email_changed_notification
|
161
|
+
@@send_email_changed_notification = false
|
162
|
+
|
163
|
+
# Used to enable sending notification to user when their password is changed.
|
164
|
+
mattr_accessor :send_password_change_notification
|
165
|
+
@@send_password_change_notification = false
|
166
|
+
|
153
167
|
# Scoped views. Since it relies on fallbacks to render default views, it's
|
154
168
|
# turned off by default.
|
155
169
|
mattr_accessor :scoped_views
|
@@ -199,7 +213,7 @@ module Devise
|
|
199
213
|
|
200
214
|
# Skip session storage for the following strategies
|
201
215
|
mattr_accessor :skip_session_storage
|
202
|
-
@@skip_session_storage = []
|
216
|
+
@@skip_session_storage = [:http_auth]
|
203
217
|
|
204
218
|
# Which formats should be treated as navigational.
|
205
219
|
mattr_accessor :navigational_formats
|
@@ -211,7 +225,7 @@ module Devise
|
|
211
225
|
|
212
226
|
# The default method used while signing out
|
213
227
|
mattr_accessor :sign_out_via
|
214
|
-
@@sign_out_via = :
|
228
|
+
@@sign_out_via = :delete
|
215
229
|
|
216
230
|
# The parent controller all Devise controllers inherits from.
|
217
231
|
# Defaults to ApplicationController. This should be set early
|
@@ -240,15 +254,22 @@ module Devise
|
|
240
254
|
mattr_accessor :clean_up_csrf_token_on_authentication
|
241
255
|
@@clean_up_csrf_token_on_authentication = true
|
242
256
|
|
257
|
+
# When false, Devise will not attempt to reload routes on eager load.
|
258
|
+
# This can reduce the time taken to boot the app but if your application
|
259
|
+
# requires the Devise mappings to be loaded during boot time the application
|
260
|
+
# won't boot properly.
|
261
|
+
mattr_accessor :reload_routes
|
262
|
+
@@reload_routes = true
|
263
|
+
|
243
264
|
# PRIVATE CONFIGURATION
|
244
265
|
|
245
266
|
# Store scopes mappings.
|
246
267
|
mattr_reader :mappings
|
247
|
-
@@mappings =
|
268
|
+
@@mappings = {}
|
248
269
|
|
249
270
|
# OmniAuth configurations.
|
250
271
|
mattr_reader :omniauth_configs
|
251
|
-
@@omniauth_configs =
|
272
|
+
@@omniauth_configs = {}
|
252
273
|
|
253
274
|
# Define a set of modules that are called when a mapping is added.
|
254
275
|
mattr_reader :helpers
|
@@ -272,14 +293,26 @@ module Devise
|
|
272
293
|
mattr_accessor :token_generator
|
273
294
|
@@token_generator = nil
|
274
295
|
|
275
|
-
#
|
296
|
+
# When set to false, changing a password does not automatically sign in a user
|
297
|
+
mattr_accessor :sign_in_after_change_password
|
298
|
+
@@sign_in_after_change_password = true
|
299
|
+
|
300
|
+
def self.rails51? # :nodoc:
|
301
|
+
Rails.gem_version >= Gem::Version.new("5.1.x")
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.activerecord51? # :nodoc:
|
305
|
+
defined?(ActiveRecord) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
|
306
|
+
end
|
307
|
+
|
308
|
+
# Default way to set up Devise. Run rails generate devise_install to create
|
276
309
|
# a fresh initializer with all configuration values.
|
277
310
|
def self.setup
|
278
311
|
yield self
|
279
312
|
end
|
280
313
|
|
281
314
|
class Getter
|
282
|
-
def initialize
|
315
|
+
def initialize(name)
|
283
316
|
@name = name
|
284
317
|
end
|
285
318
|
|
@@ -289,12 +322,8 @@ module Devise
|
|
289
322
|
end
|
290
323
|
|
291
324
|
def self.ref(arg)
|
292
|
-
|
293
|
-
|
294
|
-
Getter.new(arg)
|
295
|
-
else
|
296
|
-
ActiveSupport::Dependencies.ref(arg)
|
297
|
-
end
|
325
|
+
ActiveSupport::Dependencies.reference(arg)
|
326
|
+
Getter.new(arg)
|
298
327
|
end
|
299
328
|
|
300
329
|
def self.available_router_name
|
@@ -325,7 +354,12 @@ module Devise
|
|
325
354
|
mapping
|
326
355
|
end
|
327
356
|
|
328
|
-
#
|
357
|
+
# Register available devise modules. For the standard modules that Devise provides, this method is
|
358
|
+
# called from lib/devise/modules.rb. Third-party modules need to be added explicitly using this method.
|
359
|
+
#
|
360
|
+
# Note that adding a module using this method does not cause it to be used in the authentication
|
361
|
+
# process. That requires that the module be listed in the arguments passed to the 'devise' method
|
362
|
+
# in the model class definition.
|
329
363
|
#
|
330
364
|
# == Options:
|
331
365
|
#
|
@@ -410,7 +444,6 @@ module Devise
|
|
410
444
|
# config.omniauth :github, APP_ID, APP_SECRET
|
411
445
|
#
|
412
446
|
def self.omniauth(provider, *args)
|
413
|
-
@@helpers << Devise::OmniAuth::UrlHelpers
|
414
447
|
config = Devise::OmniAuth::Config.new(provider, args)
|
415
448
|
@@omniauth_configs[config.strategy_name.to_sym] = config
|
416
449
|
end
|
@@ -433,8 +466,8 @@ module Devise
|
|
433
466
|
Devise::Controllers::UrlHelpers.generate_helpers!
|
434
467
|
end
|
435
468
|
|
436
|
-
# A method used internally to setup warden manager
|
437
|
-
#
|
469
|
+
# A method used internally to complete the setup of warden manager after routes are loaded.
|
470
|
+
# See lib/devise/rails/routes.rb - ActionDispatch::Routing::RouteSet#finalize_with_devise!
|
438
471
|
def self.configure_warden! #:nodoc:
|
439
472
|
@@warden_configured ||= begin
|
440
473
|
warden_config.failure_app = Devise::Delegator.new
|
@@ -448,10 +481,7 @@ module Devise
|
|
448
481
|
mapping.to.serialize_into_session(record)
|
449
482
|
end
|
450
483
|
|
451
|
-
warden_config.serialize_from_session(mapping.name) do |
|
452
|
-
# Previous versions contained an additional entry at the beginning of
|
453
|
-
# key with the record's class name.
|
454
|
-
args = key[-2, 2]
|
484
|
+
warden_config.serialize_from_session(mapping.name) do |args|
|
455
485
|
mapping.to.serialize_from_session(*args)
|
456
486
|
end
|
457
487
|
end
|