cloudfoundry-devise 1.5.2
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.
- data/.gitignore +12 -0
- data/.travis.yml +13 -0
- data/CHANGELOG.rdoc +755 -0
- data/Gemfile +35 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +366 -0
- data/Rakefile +34 -0
- data/app/controllers/devise/confirmations_controller.rb +46 -0
- data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
- data/app/controllers/devise/passwords_controller.rb +50 -0
- data/app/controllers/devise/registrations_controller.rb +114 -0
- data/app/controllers/devise/sessions_controller.rb +49 -0
- data/app/controllers/devise/unlocks_controller.rb +34 -0
- data/app/helpers/devise_helper.rb +25 -0
- data/app/mailers/devise/mailer.rb +15 -0
- data/app/views/devise/confirmations/new.html.erb +12 -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 +16 -0
- data/app/views/devise/passwords/new.html.erb +12 -0
- data/app/views/devise/registrations/edit.html.erb +25 -0
- data/app/views/devise/registrations/new.html.erb +18 -0
- data/app/views/devise/sessions/new.html.erb +17 -0
- data/app/views/devise/shared/_links.erb +25 -0
- data/app/views/devise/unlocks/new.html.erb +12 -0
- data/cloudfoundry-devise.gemspec +25 -0
- data/config/locales/en.yml +59 -0
- data/lib/devise.rb +453 -0
- data/lib/devise/controllers/helpers.rb +260 -0
- data/lib/devise/controllers/internal_helpers.rb +161 -0
- data/lib/devise/controllers/rememberable.rb +52 -0
- data/lib/devise/controllers/scoped_views.rb +33 -0
- data/lib/devise/controllers/shared_helpers.rb +26 -0
- data/lib/devise/controllers/url_helpers.rb +53 -0
- data/lib/devise/delegator.rb +16 -0
- data/lib/devise/encryptors/authlogic_sha512.rb +19 -0
- data/lib/devise/encryptors/base.rb +20 -0
- data/lib/devise/encryptors/clearance_sha1.rb +17 -0
- data/lib/devise/encryptors/restful_authentication_sha1.rb +22 -0
- data/lib/devise/encryptors/sha1.rb +25 -0
- data/lib/devise/encryptors/sha512.rb +25 -0
- data/lib/devise/failure_app.rb +149 -0
- data/lib/devise/hooks/activatable.rb +11 -0
- data/lib/devise/hooks/forgetable.rb +9 -0
- data/lib/devise/hooks/rememberable.rb +6 -0
- data/lib/devise/hooks/timeoutable.rb +24 -0
- data/lib/devise/hooks/trackable.rb +9 -0
- data/lib/devise/mailers/helpers.rb +86 -0
- data/lib/devise/mapping.rb +175 -0
- data/lib/devise/models.rb +91 -0
- data/lib/devise/models/authenticatable.rb +181 -0
- data/lib/devise/models/confirmable.rb +220 -0
- data/lib/devise/models/database_authenticatable.rb +122 -0
- data/lib/devise/models/encryptable.rb +72 -0
- data/lib/devise/models/lockable.rb +169 -0
- data/lib/devise/models/omniauthable.rb +23 -0
- data/lib/devise/models/recoverable.rb +136 -0
- data/lib/devise/models/registerable.rb +21 -0
- data/lib/devise/models/rememberable.rb +114 -0
- data/lib/devise/models/serializable.rb +43 -0
- data/lib/devise/models/timeoutable.rb +45 -0
- data/lib/devise/models/token_authenticatable.rb +72 -0
- data/lib/devise/models/trackable.rb +30 -0
- data/lib/devise/models/validatable.rb +62 -0
- data/lib/devise/modules.rb +30 -0
- data/lib/devise/omniauth.rb +28 -0
- data/lib/devise/omniauth/config.rb +45 -0
- data/lib/devise/omniauth/url_helpers.rb +33 -0
- data/lib/devise/orm/active_record.rb +44 -0
- data/lib/devise/orm/mongoid.rb +31 -0
- data/lib/devise/param_filter.rb +41 -0
- data/lib/devise/path_checker.rb +18 -0
- data/lib/devise/rails.rb +73 -0
- data/lib/devise/rails/routes.rb +385 -0
- data/lib/devise/rails/warden_compat.rb +120 -0
- data/lib/devise/schema.rb +109 -0
- data/lib/devise/strategies/authenticatable.rb +155 -0
- data/lib/devise/strategies/base.rb +15 -0
- data/lib/devise/strategies/database_authenticatable.rb +21 -0
- data/lib/devise/strategies/rememberable.rb +53 -0
- data/lib/devise/strategies/token_authenticatable.rb +57 -0
- data/lib/devise/test_helpers.rb +90 -0
- data/lib/devise/version.rb +3 -0
- data/lib/generators/active_record/devise_generator.rb +71 -0
- data/lib/generators/active_record/templates/migration.rb +29 -0
- data/lib/generators/active_record/templates/migration_existing.rb +26 -0
- data/lib/generators/devise/devise_generator.rb +22 -0
- data/lib/generators/devise/install_generator.rb +24 -0
- data/lib/generators/devise/orm_helpers.rb +31 -0
- data/lib/generators/devise/views_generator.rb +98 -0
- data/lib/generators/mongoid/devise_generator.rb +60 -0
- data/lib/generators/templates/README +32 -0
- data/lib/generators/templates/devise.rb +215 -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 +15 -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 +22 -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 +15 -0
- data/test/controllers/helpers_test.rb +254 -0
- data/test/controllers/internal_helpers_test.rb +96 -0
- data/test/controllers/sessions_controller_test.rb +16 -0
- data/test/controllers/url_helpers_test.rb +59 -0
- data/test/delegator_test.rb +19 -0
- data/test/devise_test.rb +72 -0
- data/test/encryptors_test.rb +30 -0
- data/test/failure_app_test.rb +207 -0
- data/test/generators/active_record_generator_test.rb +47 -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 +52 -0
- data/test/helpers/devise_helper_test.rb +51 -0
- data/test/indifferent_hash.rb +33 -0
- data/test/integration/authenticatable_test.rb +590 -0
- data/test/integration/confirmable_test.rb +262 -0
- data/test/integration/database_authenticatable_test.rb +82 -0
- data/test/integration/http_authenticatable_test.rb +82 -0
- data/test/integration/lockable_test.rb +212 -0
- data/test/integration/omniauthable_test.rb +133 -0
- data/test/integration/recoverable_test.rb +287 -0
- data/test/integration/registerable_test.rb +335 -0
- data/test/integration/rememberable_test.rb +158 -0
- data/test/integration/timeoutable_test.rb +98 -0
- data/test/integration/token_authenticatable_test.rb +148 -0
- data/test/integration/trackable_test.rb +92 -0
- data/test/mailers/confirmation_instructions_test.rb +95 -0
- data/test/mailers/reset_password_instructions_test.rb +83 -0
- data/test/mailers/unlock_instructions_test.rb +77 -0
- data/test/mapping_test.rb +128 -0
- data/test/models/confirmable_test.rb +334 -0
- data/test/models/database_authenticatable_test.rb +167 -0
- data/test/models/encryptable_test.rb +67 -0
- data/test/models/lockable_test.rb +225 -0
- data/test/models/recoverable_test.rb +198 -0
- data/test/models/rememberable_test.rb +168 -0
- data/test/models/serializable_test.rb +38 -0
- data/test/models/timeoutable_test.rb +42 -0
- data/test/models/token_authenticatable_test.rb +49 -0
- data/test/models/trackable_test.rb +5 -0
- data/test/models/validatable_test.rb +113 -0
- data/test/models_test.rb +109 -0
- data/test/omniauth/config_test.rb +57 -0
- data/test/omniauth/url_helpers_test.rb +58 -0
- data/test/orm/active_record.rb +9 -0
- data/test/orm/mongoid.rb +14 -0
- data/test/rails_app/Rakefile +10 -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/controllers/admins/sessions_controller.rb +6 -0
- data/test/rails_app/app/controllers/admins_controller.rb +6 -0
- data/test/rails_app/app/controllers/application_controller.rb +8 -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 +23 -0
- data/test/rails_app/app/helpers/application_helper.rb +3 -0
- data/test/rails_app/app/mailers/users/mailer.rb +3 -0
- data/test/rails_app/app/mongoid/admin.rb +24 -0
- data/test/rails_app/app/mongoid/shim.rb +24 -0
- data/test/rails_app/app/mongoid/user.rb +45 -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/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/config.ru +4 -0
- data/test/rails_app/config/application.rb +41 -0
- data/test/rails_app/config/boot.rb +8 -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 +18 -0
- data/test/rails_app/config/environments/production.rb +33 -0
- data/test/rails_app/config/environments/test.rb +33 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/devise.rb +197 -0
- data/test/rails_app/config/initializers/inflections.rb +2 -0
- data/test/rails_app/config/initializers/secret_token.rb +2 -0
- data/test/rails_app/config/routes.rb +87 -0
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +71 -0
- data/test/rails_app/db/schema.rb +52 -0
- data/test/rails_app/lib/shared_admin.rb +10 -0
- data/test/rails_app/lib/shared_user.rb +26 -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/rails_app/script/rails +10 -0
- data/test/routes_test.rb +240 -0
- data/test/support/assertions.rb +27 -0
- data/test/support/helpers.rb +109 -0
- data/test/support/integration.rb +88 -0
- data/test/support/locale/en.yml +4 -0
- data/test/support/webrat/integrations/rails.rb +24 -0
- data/test/test_helper.rb +27 -0
- data/test/test_helpers_test.rb +134 -0
- metadata +295 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module Devise
|
|
2
|
+
# Holds devise schema information. To use it, just include its methods
|
|
3
|
+
# and overwrite the apply_schema method.
|
|
4
|
+
module Schema
|
|
5
|
+
|
|
6
|
+
# Creates encrypted_password, and email when it is used as an authentication
|
|
7
|
+
# key (default).
|
|
8
|
+
#
|
|
9
|
+
# == Options
|
|
10
|
+
# * :null - When true, allow columns to be null.
|
|
11
|
+
# * :default - Set to "" when :null is false, unless overridden.
|
|
12
|
+
#
|
|
13
|
+
# == Notes
|
|
14
|
+
# For Datamapper compatibility, we explicitly hardcode the limit for the
|
|
15
|
+
# encrypter password field in 128 characters.
|
|
16
|
+
def database_authenticatable(options={})
|
|
17
|
+
null = options[:null] || false
|
|
18
|
+
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
|
19
|
+
include_email = !respond_to?(:authentication_keys) || self.authentication_keys.include?(:email)
|
|
20
|
+
|
|
21
|
+
apply_devise_schema :email, String, :null => null, :default => default if include_email
|
|
22
|
+
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates password salt for encryption support when using encryptors other
|
|
26
|
+
# than the database_authenticable default of bcrypt.
|
|
27
|
+
def encryptable
|
|
28
|
+
apply_devise_schema :password_salt, String
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Creates authentication_token.
|
|
32
|
+
def token_authenticatable
|
|
33
|
+
apply_devise_schema :authentication_token, String
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Creates confirmation_token, confirmed_at and confirmation_sent_at.
|
|
37
|
+
def confirmable
|
|
38
|
+
apply_devise_schema :confirmation_token, String
|
|
39
|
+
apply_devise_schema :confirmed_at, DateTime
|
|
40
|
+
apply_devise_schema :confirmation_sent_at, DateTime
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Creates unconfirmed_email
|
|
44
|
+
def reconfirmable
|
|
45
|
+
apply_devise_schema :unconfirmed_email, String
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Creates reset_password_token and reset_password_sent_at.
|
|
49
|
+
#
|
|
50
|
+
# == Options
|
|
51
|
+
# * :reset_within - When true, adds a column that reset passwords within some date
|
|
52
|
+
def recoverable(options={})
|
|
53
|
+
use_within = options.fetch(:reset_within, Devise.reset_password_within.present?)
|
|
54
|
+
apply_devise_schema :reset_password_token, String
|
|
55
|
+
apply_devise_schema :reset_password_sent_at, DateTime if use_within
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Creates remember_token and remember_created_at.
|
|
59
|
+
#
|
|
60
|
+
# == Options
|
|
61
|
+
# * :use_salt - When true, does not create a remember_token and use password_salt instead.
|
|
62
|
+
def rememberable(options={})
|
|
63
|
+
use_salt = options.fetch(:use_salt, Devise.use_salt_as_remember_token)
|
|
64
|
+
apply_devise_schema :remember_token, String unless use_salt
|
|
65
|
+
apply_devise_schema :remember_created_at, DateTime
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Creates sign_in_count, current_sign_in_at, last_sign_in_at,
|
|
69
|
+
# current_sign_in_ip, last_sign_in_ip.
|
|
70
|
+
def trackable
|
|
71
|
+
apply_devise_schema :sign_in_count, Integer, :default => 0
|
|
72
|
+
apply_devise_schema :current_sign_in_at, DateTime
|
|
73
|
+
apply_devise_schema :last_sign_in_at, DateTime
|
|
74
|
+
apply_devise_schema :current_sign_in_ip, String
|
|
75
|
+
apply_devise_schema :last_sign_in_ip, String
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Creates failed_attempts, unlock_token and locked_at depending on the options given.
|
|
79
|
+
#
|
|
80
|
+
# == Options
|
|
81
|
+
# * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
|
|
82
|
+
# If :email or :both, creates a unlock_token field.
|
|
83
|
+
# * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
|
|
84
|
+
def lockable(options={})
|
|
85
|
+
unlock_strategy = options[:unlock_strategy]
|
|
86
|
+
unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
|
|
87
|
+
unlock_strategy ||= :both
|
|
88
|
+
|
|
89
|
+
lock_strategy = options[:lock_strategy]
|
|
90
|
+
lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
|
|
91
|
+
lock_strategy ||= :failed_attempts
|
|
92
|
+
|
|
93
|
+
if lock_strategy == :failed_attempts
|
|
94
|
+
apply_devise_schema :failed_attempts, Integer, :default => 0
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if [:both, :email].include?(unlock_strategy)
|
|
98
|
+
apply_devise_schema :unlock_token, String
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
apply_devise_schema :locked_at, DateTime
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Overwrite with specific modification to create your own schema.
|
|
105
|
+
def apply_devise_schema(name, type, options={})
|
|
106
|
+
raise NotImplementedError
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
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, :password
|
|
10
|
+
|
|
11
|
+
def valid?
|
|
12
|
+
valid_for_params_auth? || valid_for_http_auth?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Simply invokes valid_for_authentication? with the given block and deal with the result.
|
|
18
|
+
def validate(resource, &block)
|
|
19
|
+
result = resource && resource.valid_for_authentication?(&block)
|
|
20
|
+
|
|
21
|
+
case result
|
|
22
|
+
when String, Symbol
|
|
23
|
+
fail!(result)
|
|
24
|
+
false
|
|
25
|
+
when TrueClass
|
|
26
|
+
decorate(resource)
|
|
27
|
+
true
|
|
28
|
+
else
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get values from params and set in the resource.
|
|
34
|
+
def decorate(resource)
|
|
35
|
+
resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Should this resource be marked to be remembered?
|
|
39
|
+
def remember_me?
|
|
40
|
+
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Check if this is strategy is valid for http authentication by:
|
|
44
|
+
#
|
|
45
|
+
# * Validating if the model allows params authentication;
|
|
46
|
+
# * If any of the authorization headers were sent;
|
|
47
|
+
# * If all authentication keys are present;
|
|
48
|
+
#
|
|
49
|
+
def valid_for_http_auth?
|
|
50
|
+
http_authenticatable? && request.authorization && with_authentication_hash(http_auth_hash)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Check if this is strategy is valid for params authentication by:
|
|
54
|
+
#
|
|
55
|
+
# * Validating if the model allows params authentication;
|
|
56
|
+
# * If the request hits the sessions controller through POST;
|
|
57
|
+
# * If the params[scope] returns a hash with credentials;
|
|
58
|
+
# * If all authentication keys are present;
|
|
59
|
+
#
|
|
60
|
+
def valid_for_params_auth?
|
|
61
|
+
params_authenticatable? && valid_request? &&
|
|
62
|
+
valid_params? && with_authentication_hash(params_auth_hash)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Check if the model accepts this strategy as http authenticatable.
|
|
66
|
+
def http_authenticatable?
|
|
67
|
+
mapping.to.http_authenticatable?(authenticatable_name)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Check if the model accepts this strategy as params authenticatable.
|
|
71
|
+
def params_authenticatable?
|
|
72
|
+
mapping.to.params_authenticatable?(authenticatable_name)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Extract the appropriate subhash for authentication from params.
|
|
76
|
+
def params_auth_hash
|
|
77
|
+
params[scope]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Extract a hash with attributes:values from the http params.
|
|
81
|
+
def http_auth_hash
|
|
82
|
+
keys = [authentication_keys.first, :password]
|
|
83
|
+
Hash[*keys.zip(decode_credentials).flatten]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# By default, a request is valid if the controller is allowed and the VERB is POST.
|
|
87
|
+
def valid_request?
|
|
88
|
+
!!env["devise.allow_params_authentication"]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# If the request is valid, finally check if params_auth_hash returns a hash.
|
|
92
|
+
def valid_params?
|
|
93
|
+
params_auth_hash.is_a?(Hash)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Check if password is present and is not equal to "X" (default value for token).
|
|
97
|
+
def valid_password?
|
|
98
|
+
password.present? && password != "X"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Helper to decode credentials from HTTP.
|
|
102
|
+
def decode_credentials
|
|
103
|
+
return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m
|
|
104
|
+
ActiveSupport::Base64.decode64($1).split(/:/, 2)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
|
|
108
|
+
def with_authentication_hash(auth_values)
|
|
109
|
+
self.authentication_hash = {}
|
|
110
|
+
self.password = auth_values[:password]
|
|
111
|
+
|
|
112
|
+
parse_authentication_key_values(auth_values, authentication_keys) &&
|
|
113
|
+
parse_authentication_key_values(request_values, request_keys)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Holds the authentication keys.
|
|
117
|
+
def authentication_keys
|
|
118
|
+
@authentication_keys ||= mapping.to.authentication_keys
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Holds request keys.
|
|
122
|
+
def request_keys
|
|
123
|
+
@request_keys ||= mapping.to.request_keys
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Returns values from the request object.
|
|
127
|
+
def request_values
|
|
128
|
+
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
|
|
129
|
+
values = keys.map { |k| self.request.send(k) }
|
|
130
|
+
Hash[keys.zip(values)]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Parse authentication keys considering if they should be enforced or not.
|
|
134
|
+
def parse_authentication_key_values(hash, keys)
|
|
135
|
+
keys.each do |key, enforce|
|
|
136
|
+
value = hash[key].presence
|
|
137
|
+
if value
|
|
138
|
+
self.authentication_hash[key] = value
|
|
139
|
+
else
|
|
140
|
+
return false unless enforce == false
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Holds the authenticatable name for this class. Devise::Strategies::DatabaseAuthenticatable
|
|
147
|
+
# becomes simply :database.
|
|
148
|
+
def authenticatable_name
|
|
149
|
+
@authenticatable_name ||=
|
|
150
|
+
ActiveSupport::Inflector.underscore(self.class.name.split("::").last).
|
|
151
|
+
sub("_authenticatable", "").to_sym
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
# Checks if a valid scope was given for devise and find mapping based on this scope.
|
|
6
|
+
def mapping
|
|
7
|
+
@mapping ||= begin
|
|
8
|
+
mapping = Devise.mappings[scope]
|
|
9
|
+
raise "Could not find mapping for #{scope}" unless mapping
|
|
10
|
+
mapping
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'devise/strategies/authenticatable'
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
module Strategies
|
|
5
|
+
# Default strategy for signing in a user, based on his 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
|
+
|
|
10
|
+
if validate(resource){ resource.valid_password?(password) }
|
|
11
|
+
resource.after_database_authentication
|
|
12
|
+
success!(resource)
|
|
13
|
+
elsif !halted?
|
|
14
|
+
fail(:invalid)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Warden::Strategies.add(:database_authenticatable, Devise::Strategies::DatabaseAuthenticatable)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'devise/strategies/base'
|
|
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
|
+
if validate(resource)
|
|
23
|
+
success!(resource)
|
|
24
|
+
elsif !halted?
|
|
25
|
+
cookies.delete(remember_key)
|
|
26
|
+
pass
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def decorate(resource)
|
|
33
|
+
super
|
|
34
|
+
resource.extend_remember_period = mapping.to.extend_remember_period if resource.respond_to?(:extend_remember_period=)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def remember_me?
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def remember_key
|
|
42
|
+
"remember_#{scope}_token"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def remember_cookie
|
|
46
|
+
@remember_cookie ||= cookies.signed[remember_key]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'devise/strategies/base'
|
|
2
|
+
|
|
3
|
+
module Devise
|
|
4
|
+
module Strategies
|
|
5
|
+
# Strategy for signing in a user, based on a authenticatable token. This works for both params
|
|
6
|
+
# and http. For the former, all you need to do is to pass the params in the URL:
|
|
7
|
+
#
|
|
8
|
+
# http://myapp.example.com/?user_token=SECRET
|
|
9
|
+
#
|
|
10
|
+
# For HTTP, you can pass the token as username and blank password. Since some clients may require
|
|
11
|
+
# a password, you can pass "X" as password and it will simply be ignored.
|
|
12
|
+
class TokenAuthenticatable < Authenticatable
|
|
13
|
+
def store?
|
|
14
|
+
!mapping.to.stateless_token
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def authenticate!
|
|
18
|
+
resource = mapping.to.find_for_token_authentication(authentication_hash)
|
|
19
|
+
|
|
20
|
+
if validate(resource)
|
|
21
|
+
resource.after_token_authentication
|
|
22
|
+
success!(resource)
|
|
23
|
+
elsif !halted?
|
|
24
|
+
fail(:invalid_token)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# TokenAuthenticatable request is valid for any controller and any verb.
|
|
31
|
+
def valid_request?
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Do not use remember_me behavior with token.
|
|
36
|
+
def remember_me?
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Try both scoped and non scoped keys.
|
|
41
|
+
def params_auth_hash
|
|
42
|
+
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
|
|
43
|
+
params[scope]
|
|
44
|
+
else
|
|
45
|
+
params
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Overwrite authentication keys to use token_authentication_key.
|
|
50
|
+
def authentication_keys
|
|
51
|
+
@authentication_keys ||= [mapping.to.token_authentication_key]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Warden::Strategies.add(:token_authenticatable, Devise::Strategies::TokenAuthenticatable)
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
result = nil
|
|
19
|
+
_catch_warden { result = super }
|
|
20
|
+
result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# We need to setup the environment variables and the response in the controller.
|
|
24
|
+
def setup_controller_for_warden #:nodoc:
|
|
25
|
+
@request.env['action_controller.instance'] = @controller
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Quick access to Warden::Proxy.
|
|
29
|
+
def warden #:nodoc:
|
|
30
|
+
@warden ||= begin
|
|
31
|
+
manager = Warden::Manager.new(nil) do |config|
|
|
32
|
+
config.merge! Devise.warden_config
|
|
33
|
+
end
|
|
34
|
+
@request.env['warden'] = Warden::Proxy.new(@request.env, manager)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# sign_in a given resource by storing its keys in the session.
|
|
39
|
+
# This method bypass any warden authentication callback.
|
|
40
|
+
#
|
|
41
|
+
# Examples:
|
|
42
|
+
#
|
|
43
|
+
# sign_in :user, @user # sign_in(scope, resource)
|
|
44
|
+
# sign_in @user # sign_in(resource)
|
|
45
|
+
#
|
|
46
|
+
def sign_in(resource_or_scope, resource=nil)
|
|
47
|
+
scope ||= Devise::Mapping.find_scope!(resource_or_scope)
|
|
48
|
+
resource ||= resource_or_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
|
+
def _catch_warden(&block)
|
|
70
|
+
result = catch(:warden, &block)
|
|
71
|
+
|
|
72
|
+
if result.is_a?(Hash) && !warden.custom_failure? && !@controller.send(:performed?)
|
|
73
|
+
result[:action] ||= :unauthenticated
|
|
74
|
+
|
|
75
|
+
env = @controller.request.env
|
|
76
|
+
env["PATH_INFO"] = "/#{result[:action]}"
|
|
77
|
+
env["warden.options"] = result
|
|
78
|
+
Warden::Manager._run_callbacks(:before_failure, env, result)
|
|
79
|
+
|
|
80
|
+
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
|
81
|
+
@controller.send :render, :status => status, :text => body,
|
|
82
|
+
:content_type => headers["Content-Type"], :location => headers["Location"]
|
|
83
|
+
|
|
84
|
+
nil
|
|
85
|
+
else
|
|
86
|
+
result
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|