deviseOne 1.0.0
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 +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +38 -0
- data/.yardopts +9 -0
- data/CHANGELOG.md +1117 -0
- data/CONTRIBUTING.md +14 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +199 -0
- data/MIT-LICENSE +20 -0
- data/README.md +529 -0
- data/Rakefile +35 -0
- data/app/controllers/devise/confirmations_controller.rb +47 -0
- data/app/controllers/devise/omniauth_callbacks_controller.rb +30 -0
- data/app/controllers/devise/passwords_controller.rb +71 -0
- data/app/controllers/devise/registrations_controller.rb +143 -0
- data/app/controllers/devise/sessions_controller.rb +166 -0
- data/app/controllers/devise/unlocks_controller.rb +46 -0
- data/app/controllers/devise_controller.rb +193 -0
- data/app/helpers/devise_helper.rb +25 -0
- data/app/mailers/devise/mailer.rb +20 -0
- data/app/views/devise/confirmations/new.html.erb +16 -0
- data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/devise/passwords/edit.html.erb +25 -0
- data/app/views/devise/passwords/new.html.erb +16 -0
- data/app/views/devise/registrations/edit.html.erb +39 -0
- data/app/views/devise/registrations/new.html.erb +29 -0
- data/app/views/devise/sessions/new.html.erb +27 -0
- data/app/views/devise/shared/_links.html.erb +21 -0
- data/app/views/devise/unlocks/new.html.erb +16 -0
- data/config/locales/en.yml +70 -0
- data/devise.gemspec +33 -0
- data/devise.png +0 -0
- data/gemfiles/Gemfile.rails-3.2-stable +29 -0
- data/gemfiles/Gemfile.rails-3.2-stable.lock +169 -0
- data/gemfiles/Gemfile.rails-4.0-stable +29 -0
- data/gemfiles/Gemfile.rails-4.0-stable.lock +165 -0
- data/gemfiles/Gemfile.rails-4.1-stable +29 -0
- data/gemfiles/Gemfile.rails-4.1-stable.lock +170 -0
- data/lib/devise.rb +499 -0
- data/lib/devise/controllers/helpers.rb +284 -0
- data/lib/devise/controllers/rememberable.rb +47 -0
- data/lib/devise/controllers/scoped_views.rb +17 -0
- data/lib/devise/controllers/sign_in_out.rb +102 -0
- data/lib/devise/controllers/store_location.rb +58 -0
- data/lib/devise/controllers/url_helpers.rb +69 -0
- data/lib/devise/delegator.rb +16 -0
- data/lib/devise/failure_app.rb +212 -0
- data/lib/devise/hooks/activatable.rb +10 -0
- data/lib/devise/hooks/csrf_cleaner.rb +7 -0
- data/lib/devise/hooks/forgetable.rb +9 -0
- data/lib/devise/hooks/lockable.rb +7 -0
- data/lib/devise/hooks/proxy.rb +21 -0
- data/lib/devise/hooks/rememberable.rb +7 -0
- data/lib/devise/hooks/timeoutable.rb +35 -0
- data/lib/devise/hooks/trackable.rb +9 -0
- data/lib/devise/mailers/helpers.rb +90 -0
- data/lib/devise/mapping.rb +175 -0
- data/lib/devise/models.rb +119 -0
- data/lib/devise/models/authenticatable.rb +290 -0
- data/lib/devise/models/confirmable.rb +305 -0
- data/lib/devise/models/database_authenticatable.rb +164 -0
- data/lib/devise/models/lockable.rb +196 -0
- data/lib/devise/models/omniauthable.rb +27 -0
- data/lib/devise/models/recoverable.rb +157 -0
- data/lib/devise/models/registerable.rb +25 -0
- data/lib/devise/models/rememberable.rb +142 -0
- data/lib/devise/models/timeoutable.rb +49 -0
- data/lib/devise/models/trackable.rb +38 -0
- data/lib/devise/models/validatable.rb +66 -0
- data/lib/devise/modules.rb +28 -0
- data/lib/devise/omniauth.rb +28 -0
- data/lib/devise/omniauth/config.rb +45 -0
- data/lib/devise/omniauth/url_helpers.rb +18 -0
- data/lib/devise/orm/active_record.rb +3 -0
- data/lib/devise/orm/mongoid.rb +3 -0
- data/lib/devise/parameter_filter.rb +40 -0
- data/lib/devise/parameter_sanitizer.rb +99 -0
- data/lib/devise/rails.rb +56 -0
- data/lib/devise/rails/routes.rb +495 -0
- data/lib/devise/rails/warden_compat.rb +22 -0
- data/lib/devise/strategies/authenticatable.rb +173 -0
- data/lib/devise/strategies/base.rb +20 -0
- data/lib/devise/strategies/database_authenticatable.rb +24 -0
- data/lib/devise/strategies/rememberable.rb +59 -0
- data/lib/devise/test_helpers.rb +132 -0
- data/lib/devise/time_inflector.rb +14 -0
- data/lib/devise/token_generator.rb +70 -0
- data/lib/devise/version.rb +3 -0
- data/lib/generators/active_record/devise_generator.rb +91 -0
- data/lib/generators/active_record/templates/migration.rb +18 -0
- data/lib/generators/active_record/templates/migration_existing.rb +25 -0
- data/lib/generators/devise/controllers_generator.rb +44 -0
- data/lib/generators/devise/devise_generator.rb +26 -0
- data/lib/generators/devise/install_generator.rb +29 -0
- data/lib/generators/devise/orm_helpers.rb +51 -0
- data/lib/generators/devise/views_generator.rb +135 -0
- data/lib/generators/mongoid/devise_generator.rb +55 -0
- data/lib/generators/templates/README +35 -0
- data/lib/generators/templates/controllers/README +14 -0
- data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
- data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
- data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
- data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
- data/lib/generators/templates/devise.rb +263 -0
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +5 -0
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +8 -0
- data/lib/generators/templates/markerb/unlock_instructions.markerb +7 -0
- data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +16 -0
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +19 -0
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +15 -0
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +27 -0
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +17 -0
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +15 -0
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +16 -0
- data/script/cached-bundle +49 -0
- data/script/s3-put +71 -0
- data/test/controllers/custom_registrations_controller_test.rb +35 -0
- data/test/controllers/custom_strategy_test.rb +62 -0
- data/test/controllers/helpers_test.rb +316 -0
- data/test/controllers/internal_helpers_test.rb +129 -0
- data/test/controllers/load_hooks_controller_test.rb +19 -0
- data/test/controllers/passwords_controller_test.rb +31 -0
- data/test/controllers/sessions_controller_test.rb +102 -0
- data/test/controllers/url_helpers_test.rb +65 -0
- data/test/delegator_test.rb +19 -0
- data/test/devise_test.rb +107 -0
- data/test/failure_app_test.rb +275 -0
- data/test/generators/active_record_generator_test.rb +109 -0
- data/test/generators/controllers_generator_test.rb +48 -0
- data/test/generators/devise_generator_test.rb +39 -0
- data/test/generators/install_generator_test.rb +13 -0
- data/test/generators/mongoid_generator_test.rb +23 -0
- data/test/generators/views_generator_test.rb +96 -0
- data/test/helpers/devise_helper_test.rb +49 -0
- data/test/integration/authenticatable_test.rb +731 -0
- data/test/integration/confirmable_test.rb +324 -0
- data/test/integration/database_authenticatable_test.rb +94 -0
- data/test/integration/http_authenticatable_test.rb +105 -0
- data/test/integration/lockable_test.rb +239 -0
- data/test/integration/omniauthable_test.rb +133 -0
- data/test/integration/recoverable_test.rb +334 -0
- data/test/integration/registerable_test.rb +361 -0
- data/test/integration/rememberable_test.rb +176 -0
- data/test/integration/timeoutable_test.rb +189 -0
- data/test/integration/trackable_test.rb +92 -0
- data/test/mailers/confirmation_instructions_test.rb +115 -0
- data/test/mailers/reset_password_instructions_test.rb +96 -0
- data/test/mailers/unlock_instructions_test.rb +91 -0
- data/test/mapping_test.rb +128 -0
- data/test/models/authenticatable_test.rb +23 -0
- data/test/models/confirmable_test.rb +461 -0
- data/test/models/database_authenticatable_test.rb +249 -0
- data/test/models/lockable_test.rb +328 -0
- data/test/models/omniauthable_test.rb +7 -0
- data/test/models/recoverable_test.rb +205 -0
- data/test/models/registerable_test.rb +7 -0
- data/test/models/rememberable_test.rb +198 -0
- data/test/models/serializable_test.rb +49 -0
- data/test/models/timeoutable_test.rb +51 -0
- data/test/models/trackable_test.rb +41 -0
- data/test/models/validatable_test.rb +127 -0
- data/test/models_test.rb +144 -0
- data/test/omniauth/config_test.rb +57 -0
- data/test/omniauth/url_helpers_test.rb +54 -0
- data/test/orm/active_record.rb +10 -0
- data/test/orm/mongoid.rb +13 -0
- data/test/parameter_sanitizer_test.rb +81 -0
- data/test/rails_app/Rakefile +6 -0
- data/test/rails_app/app/active_record/admin.rb +6 -0
- data/test/rails_app/app/active_record/shim.rb +2 -0
- data/test/rails_app/app/active_record/user.rb +6 -0
- data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
- data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +6 -0
- data/test/rails_app/app/controllers/admins_controller.rb +11 -0
- data/test/rails_app/app/controllers/application_controller.rb +12 -0
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +21 -0
- data/test/rails_app/app/controllers/home_controller.rb +25 -0
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +14 -0
- data/test/rails_app/app/controllers/users_controller.rb +31 -0
- data/test/rails_app/app/helpers/application_helper.rb +3 -0
- data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
- data/test/rails_app/app/mailers/users/mailer.rb +3 -0
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
- data/test/rails_app/app/mongoid/admin.rb +29 -0
- data/test/rails_app/app/mongoid/shim.rb +23 -0
- data/test/rails_app/app/mongoid/user.rb +39 -0
- data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
- data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
- data/test/rails_app/app/views/admins/index.html.erb +1 -0
- data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -0
- data/test/rails_app/app/views/home/index.html.erb +1 -0
- data/test/rails_app/app/views/home/join.html.erb +1 -0
- data/test/rails_app/app/views/home/private.html.erb +1 -0
- data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -0
- data/test/rails_app/app/views/layouts/application.html.erb +24 -0
- data/test/rails_app/app/views/users/edit_form.html.erb +1 -0
- data/test/rails_app/app/views/users/index.html.erb +1 -0
- data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
- data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
- data/test/rails_app/bin/bundle +3 -0
- data/test/rails_app/bin/rails +4 -0
- data/test/rails_app/bin/rake +4 -0
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/config/application.rb +40 -0
- data/test/rails_app/config/boot.rb +14 -0
- data/test/rails_app/config/database.yml +18 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +30 -0
- data/test/rails_app/config/environments/production.rb +80 -0
- data/test/rails_app/config/environments/test.rb +36 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/devise.rb +180 -0
- data/test/rails_app/config/initializers/inflections.rb +2 -0
- data/test/rails_app/config/initializers/secret_token.rb +8 -0
- data/test/rails_app/config/initializers/session_store.rb +1 -0
- data/test/rails_app/config/routes.rb +122 -0
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +71 -0
- data/test/rails_app/db/schema.rb +55 -0
- data/test/rails_app/lib/shared_admin.rb +17 -0
- data/test/rails_app/lib/shared_user.rb +29 -0
- data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
- data/test/rails_app/public/404.html +26 -0
- data/test/rails_app/public/422.html +26 -0
- data/test/rails_app/public/500.html +26 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/routes_test.rb +264 -0
- data/test/support/action_controller/record_identifier.rb +10 -0
- data/test/support/assertions.rb +39 -0
- data/test/support/helpers.rb +73 -0
- data/test/support/integration.rb +92 -0
- data/test/support/locale/en.yml +8 -0
- data/test/support/mongoid.yml +6 -0
- data/test/support/webrat/integrations/rails.rb +24 -0
- data/test/test_helper.rb +34 -0
- data/test/test_helpers_test.rb +163 -0
- data/test/test_models.rb +33 -0
- metadata +531 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Warden::Mixins::Common
|
|
2
|
+
def request
|
|
3
|
+
@request ||= ActionDispatch::Request.new(env)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# Deprecate: Remove this check once we move to Rails 4 only.
|
|
7
|
+
NULL_STORE =
|
|
8
|
+
defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
|
|
9
|
+
ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
|
|
10
|
+
|
|
11
|
+
def reset_session!
|
|
12
|
+
# Calling reset_session on NULL_STORE causes it fail.
|
|
13
|
+
# This is a bug that needs to be fixed in Rails.
|
|
14
|
+
unless NULL_STORE && request.session.is_a?(NULL_STORE)
|
|
15
|
+
request.reset_session
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def cookies
|
|
20
|
+
request.cookie_jar
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require 'devise/strategies/base'
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
module Strategies
|
|
5
|
+
# This strategy should be used as basis for authentication strategies. It retrieves
|
|
6
|
+
# parameters both from params or from http authorization headers. See database_authenticatable
|
|
7
|
+
# for an example.
|
|
8
|
+
class Authenticatable < Base
|
|
9
|
+
attr_accessor :authentication_hash, :authentication_type, :password
|
|
10
|
+
|
|
11
|
+
def store?
|
|
12
|
+
super && !mapping.to.skip_session_storage.include?(authentication_type)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def valid?
|
|
16
|
+
valid_for_params_auth? || valid_for_http_auth?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Override and set to false for things like OmniAuth that technically
|
|
20
|
+
# run through Authentication (user_set) very often, which would normally
|
|
21
|
+
# reset CSRF data in the session
|
|
22
|
+
def clean_up_csrf?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# Receives a resource and check if it is valid by calling valid_for_authentication?
|
|
29
|
+
# An optional block that will be triggered while validating can be optionally
|
|
30
|
+
# given as parameter. Check Devise::Models::Authenticable.valid_for_authentication?
|
|
31
|
+
# for more information.
|
|
32
|
+
#
|
|
33
|
+
# In case the resource can't be validated, it will fail with the given
|
|
34
|
+
# unauthenticated_message.
|
|
35
|
+
def validate(resource, &block)
|
|
36
|
+
result = resource && resource.valid_for_authentication?(&block)
|
|
37
|
+
|
|
38
|
+
if result
|
|
39
|
+
true
|
|
40
|
+
else
|
|
41
|
+
if resource
|
|
42
|
+
fail!(resource.unauthenticated_message)
|
|
43
|
+
end
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Get values from params and set in the resource.
|
|
49
|
+
def remember_me(resource)
|
|
50
|
+
resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Should this resource be marked to be remembered?
|
|
54
|
+
def remember_me?
|
|
55
|
+
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Check if this is a valid strategy for http authentication by:
|
|
59
|
+
#
|
|
60
|
+
# * Validating if the model allows params authentication;
|
|
61
|
+
# * If any of the authorization headers were sent;
|
|
62
|
+
# * If all authentication keys are present;
|
|
63
|
+
#
|
|
64
|
+
def valid_for_http_auth?
|
|
65
|
+
http_authenticatable? && request.authorization && with_authentication_hash(:http_auth, http_auth_hash)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Check if this is a valid strategy for params authentication by:
|
|
69
|
+
#
|
|
70
|
+
# * Validating if the model allows params authentication;
|
|
71
|
+
# * If the request hits the sessions controller through POST;
|
|
72
|
+
# * If the params[scope] returns a hash with credentials;
|
|
73
|
+
# * If all authentication keys are present;
|
|
74
|
+
#
|
|
75
|
+
def valid_for_params_auth?
|
|
76
|
+
params_authenticatable? && valid_params_request? &&
|
|
77
|
+
valid_params? && with_authentication_hash(:params_auth, params_auth_hash)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Check if the model accepts this strategy as http authenticatable.
|
|
81
|
+
def http_authenticatable?
|
|
82
|
+
mapping.to.http_authenticatable?(authenticatable_name)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Check if the model accepts this strategy as params authenticatable.
|
|
86
|
+
def params_authenticatable?
|
|
87
|
+
mapping.to.params_authenticatable?(authenticatable_name)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Extract the appropriate subhash for authentication from params.
|
|
91
|
+
def params_auth_hash
|
|
92
|
+
params[scope]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Extract a hash with attributes:values from the http params.
|
|
96
|
+
def http_auth_hash
|
|
97
|
+
keys = [http_authentication_key, :password]
|
|
98
|
+
Hash[*keys.zip(decode_credentials).flatten]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# By default, a request is valid if the controller set the proper env variable.
|
|
102
|
+
def valid_params_request?
|
|
103
|
+
!!env["devise.allow_params_authentication"]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# If the request is valid, finally check if params_auth_hash returns a hash.
|
|
107
|
+
def valid_params?
|
|
108
|
+
params_auth_hash.is_a?(Hash)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Check if password is present.
|
|
112
|
+
def valid_password?
|
|
113
|
+
password.present?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Helper to decode credentials from HTTP.
|
|
117
|
+
def decode_credentials
|
|
118
|
+
return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m
|
|
119
|
+
Base64.decode64($1).split(/:/, 2)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
|
|
123
|
+
def with_authentication_hash(auth_type, auth_values)
|
|
124
|
+
self.authentication_hash, self.authentication_type = {}, auth_type
|
|
125
|
+
self.password = auth_values[:password]
|
|
126
|
+
|
|
127
|
+
parse_authentication_key_values(auth_values, authentication_keys) &&
|
|
128
|
+
parse_authentication_key_values(request_values, request_keys)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def authentication_keys
|
|
132
|
+
@authentication_keys ||= mapping.to.authentication_keys
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def http_authentication_key
|
|
136
|
+
@http_authentication_key ||= mapping.to.http_authentication_key || case authentication_keys
|
|
137
|
+
when Array then authentication_keys.first
|
|
138
|
+
when Hash then authentication_keys.keys.first
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def request_keys
|
|
143
|
+
@request_keys ||= mapping.to.request_keys
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def request_values
|
|
147
|
+
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
|
|
148
|
+
values = keys.map { |k| self.request.send(k) }
|
|
149
|
+
Hash[keys.zip(values)]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def parse_authentication_key_values(hash, keys)
|
|
153
|
+
keys.each do |key, enforce|
|
|
154
|
+
value = hash[key].presence
|
|
155
|
+
if value
|
|
156
|
+
self.authentication_hash[key] = value
|
|
157
|
+
else
|
|
158
|
+
return false unless enforce == false
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Holds the authenticatable name for this class. Devise::Strategies::DatabaseAuthenticatable
|
|
165
|
+
# becomes simply :database.
|
|
166
|
+
def authenticatable_name
|
|
167
|
+
@authenticatable_name ||=
|
|
168
|
+
ActiveSupport::Inflector.underscore(self.class.name.split("::").last).
|
|
169
|
+
sub("_authenticatable", "").to_sym
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Devise
|
|
2
|
+
module Strategies
|
|
3
|
+
# Base strategy for Devise. Responsible for verifying correct scope and mapping.
|
|
4
|
+
class Base < ::Warden::Strategies::Base
|
|
5
|
+
# Whenever CSRF cannot be verified, we turn off any kind of storage
|
|
6
|
+
def store?
|
|
7
|
+
!env["devise.skip_storage"]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Checks if a valid scope was given for devise and find mapping based on this scope.
|
|
11
|
+
def mapping
|
|
12
|
+
@mapping ||= begin
|
|
13
|
+
mapping = Devise.mappings[scope]
|
|
14
|
+
raise "Could not find mapping for #{scope}" unless mapping
|
|
15
|
+
mapping
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'devise/strategies/authenticatable'
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
module Strategies
|
|
5
|
+
# Default strategy for signing in a user, based on their email and password in the database.
|
|
6
|
+
class DatabaseAuthenticatable < Authenticatable
|
|
7
|
+
def authenticate!
|
|
8
|
+
resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
|
|
9
|
+
encrypted = false
|
|
10
|
+
|
|
11
|
+
if validate(resource){ encrypted = true; resource.valid_password?(password) }
|
|
12
|
+
remember_me(resource)
|
|
13
|
+
resource.after_database_authentication
|
|
14
|
+
success!(resource)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
mapping.to.new.password = password if !encrypted && Devise.paranoid
|
|
18
|
+
fail(:not_found_in_database) unless resource
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Warden::Strategies.add(:database_authenticatable, Devise::Strategies::DatabaseAuthenticatable)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'devise/strategies/authenticatable'
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
module Strategies
|
|
5
|
+
# Remember the user through the remember token. This strategy is responsible
|
|
6
|
+
# to verify whether there is a cookie with the remember token, and to
|
|
7
|
+
# recreate the user from this cookie if it exists. Must be called *before*
|
|
8
|
+
# authenticatable.
|
|
9
|
+
class Rememberable < Authenticatable
|
|
10
|
+
# A valid strategy for rememberable needs a remember token in the cookies.
|
|
11
|
+
def valid?
|
|
12
|
+
@remember_cookie = nil
|
|
13
|
+
remember_cookie.present?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# To authenticate a user we deserialize the cookie and attempt finding
|
|
17
|
+
# the record in the database. If the attempt fails, we pass to another
|
|
18
|
+
# strategy handle the authentication.
|
|
19
|
+
def authenticate!
|
|
20
|
+
resource = mapping.to.serialize_from_cookie(*remember_cookie)
|
|
21
|
+
|
|
22
|
+
unless resource
|
|
23
|
+
cookies.delete(remember_key)
|
|
24
|
+
return pass
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if validate(resource)
|
|
28
|
+
remember_me(resource)
|
|
29
|
+
extend_remember_me_period(resource)
|
|
30
|
+
resource.after_remembered
|
|
31
|
+
success!(resource)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def extend_remember_me_period(resource)
|
|
38
|
+
if resource.respond_to?(:extend_remember_period=)
|
|
39
|
+
resource.extend_remember_period = mapping.to.extend_remember_period
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def remember_me?
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def remember_key
|
|
48
|
+
mapping.to.rememberable_options.fetch(:key, "remember_#{scope}_token")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def remember_cookie
|
|
52
|
+
@remember_cookie ||= cookies.signed[remember_key]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
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
|
+
module TestHelpers
|
|
10
|
+
def self.included(base)
|
|
11
|
+
base.class_eval do
|
|
12
|
+
setup :setup_controller_for_warden, :warden if respond_to?(:setup)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Override process to consider warden.
|
|
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
|
+
@warden ||= begin
|
|
30
|
+
manager = Warden::Manager.new(nil) do |config|
|
|
31
|
+
config.merge! Devise.warden_config
|
|
32
|
+
end
|
|
33
|
+
@request.env['warden'] = Warden::Proxy.new(@request.env, manager)
|
|
34
|
+
end
|
|
35
|
+
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
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "active_support/core_ext/module/delegation"
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
class TimeInflector
|
|
5
|
+
include ActionView::Helpers::DateHelper
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_reader :instance
|
|
9
|
+
delegate :time_ago_in_words, to: :instance
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
@instance = new
|
|
13
|
+
end
|
|
14
|
+
end
|