devise 1.1.pre4 → 1.1.rc0

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.
Files changed (122) hide show
  1. data/CHANGELOG.rdoc +31 -2
  2. data/Gemfile +15 -6
  3. data/README.rdoc +12 -16
  4. data/Rakefile +2 -2
  5. data/TODO +2 -1
  6. data/app/controllers/devise/confirmations_controller.rb +1 -1
  7. data/app/controllers/devise/passwords_controller.rb +2 -3
  8. data/app/controllers/devise/registrations_controller.rb +5 -5
  9. data/app/controllers/devise/sessions_controller.rb +5 -27
  10. data/app/controllers/devise/unlocks_controller.rb +9 -1
  11. data/app/models/devise/mailer.rb +17 -11
  12. data/app/views/devise/confirmations/new.html.erb +1 -1
  13. data/app/views/devise/passwords/edit.html.erb +1 -1
  14. data/app/views/devise/passwords/new.html.erb +1 -1
  15. data/app/views/devise/registrations/edit.html.erb +2 -2
  16. data/app/views/devise/registrations/new.html.erb +2 -2
  17. data/app/views/devise/sessions/new.html.erb +2 -2
  18. data/app/views/devise/shared/_links.erb +5 -5
  19. data/app/views/devise/unlocks/new.html.erb +1 -1
  20. data/config/locales/en.yml +4 -9
  21. data/lib/devise.rb +83 -42
  22. data/lib/devise/controllers/helpers.rb +6 -18
  23. data/lib/devise/controllers/internal_helpers.rb +11 -12
  24. data/lib/devise/controllers/scoped_views.rb +2 -2
  25. data/lib/devise/controllers/url_helpers.rb +1 -1
  26. data/lib/devise/failure_app.rb +56 -16
  27. data/lib/devise/hooks/activatable.rb +18 -6
  28. data/lib/devise/hooks/rememberable.rb +36 -27
  29. data/lib/devise/hooks/timeoutable.rb +1 -1
  30. data/lib/devise/hooks/trackable.rb +4 -2
  31. data/lib/devise/mapping.rb +19 -14
  32. data/lib/devise/models.rb +12 -3
  33. data/lib/devise/models/authenticatable.rb +19 -95
  34. data/lib/devise/models/confirmable.rb +14 -20
  35. data/lib/devise/models/database_authenticatable.rb +99 -0
  36. data/lib/devise/models/lockable.rb +53 -39
  37. data/lib/devise/models/recoverable.rb +3 -3
  38. data/lib/devise/models/rememberable.rb +5 -10
  39. data/lib/devise/models/token_authenticatable.rb +18 -25
  40. data/lib/devise/models/validatable.rb +14 -9
  41. data/lib/devise/modules.rb +7 -8
  42. data/lib/devise/orm/active_record.rb +1 -1
  43. data/lib/devise/orm/data_mapper.rb +20 -7
  44. data/lib/devise/orm/mongoid.rb +40 -0
  45. data/lib/devise/rails.rb +26 -3
  46. data/lib/devise/rails/routes.rb +18 -16
  47. data/lib/devise/rails/warden_compat.rb +2 -2
  48. data/lib/devise/schema.rb +45 -18
  49. data/lib/devise/strategies/authenticatable.rb +92 -21
  50. data/lib/devise/strategies/base.rb +6 -3
  51. data/lib/devise/strategies/database_authenticatable.rb +20 -0
  52. data/lib/devise/strategies/rememberable.rb +10 -6
  53. data/lib/devise/strategies/token_authenticatable.rb +28 -19
  54. data/lib/devise/test_helpers.rb +5 -1
  55. data/lib/devise/version.rb +1 -1
  56. data/lib/generators/devise/devise_generator.rb +15 -5
  57. data/lib/generators/devise/templates/migration.rb +2 -2
  58. data/lib/generators/devise_install/templates/devise.rb +37 -16
  59. data/lib/generators/devise_views/devise_views_generator.rb +51 -4
  60. data/test/controllers/helpers_test.rb +16 -8
  61. data/test/controllers/internal_helpers_test.rb +6 -1
  62. data/test/controllers/url_helpers_test.rb +10 -10
  63. data/test/devise_test.rb +13 -17
  64. data/test/encryptors_test.rb +2 -0
  65. data/test/failure_app_test.rb +72 -23
  66. data/test/integration/confirmable_test.rb +4 -4
  67. data/test/integration/{authenticatable_test.rb → database_authenticatable_test.rb} +35 -17
  68. data/test/integration/http_authenticatable_test.rb +3 -3
  69. data/test/integration/lockable_test.rb +28 -8
  70. data/test/integration/recoverable_test.rb +3 -3
  71. data/test/integration/registerable_test.rb +6 -4
  72. data/test/integration/rememberable_test.rb +11 -4
  73. data/test/integration/timeoutable_test.rb +4 -4
  74. data/test/integration/token_authenticatable_test.rb +46 -10
  75. data/test/integration/trackable_test.rb +2 -2
  76. data/test/mailers/confirmation_instructions_test.rb +5 -5
  77. data/test/mailers/reset_password_instructions_test.rb +5 -5
  78. data/test/mailers/unlock_instructions_test.rb +5 -5
  79. data/test/mapping_test.rb +15 -14
  80. data/test/models/confirmable_test.rb +9 -32
  81. data/test/models/{authenticatable_test.rb → database_authenticatable_test.rb} +2 -34
  82. data/test/models/lockable_test.rb +48 -66
  83. data/test/models/recoverable_test.rb +8 -8
  84. data/test/models/rememberable_test.rb +6 -28
  85. data/test/models/timeoutable_test.rb +1 -1
  86. data/test/models/token_authenticatable_test.rb +1 -8
  87. data/test/models/trackable_test.rb +1 -1
  88. data/test/models/validatable_test.rb +2 -2
  89. data/test/models_test.rb +16 -2
  90. data/test/orm/active_record.rb +1 -22
  91. data/test/orm/data_mapper.rb +1 -0
  92. data/test/orm/mongoid.rb +10 -0
  93. data/test/rails_app/app/active_record/admin.rb +1 -5
  94. data/test/rails_app/app/controllers/application_controller.rb +2 -0
  95. data/test/rails_app/app/controllers/sessions_controller.rb +1 -1
  96. data/test/rails_app/app/data_mapper/admin.rb +13 -0
  97. data/test/rails_app/app/data_mapper/user.rb +24 -0
  98. data/test/rails_app/app/mongoid/admin.rb +15 -0
  99. data/test/rails_app/app/mongoid/user.rb +21 -0
  100. data/test/rails_app/config/application.rb +10 -5
  101. data/test/rails_app/config/boot.rb +5 -1
  102. data/test/rails_app/config/initializers/devise.rb +1 -1
  103. data/test/rails_app/config/routes.rb +4 -1
  104. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +27 -0
  105. data/test/rails_app/db/schema.rb +86 -0
  106. data/test/routes_test.rb +3 -3
  107. data/test/support/assertions.rb +2 -0
  108. data/test/support/helpers.rb +2 -0
  109. data/test/support/integration.rb +4 -7
  110. data/test/support/webrat/integrations/rails.rb +2 -1
  111. data/test/test_helper.rb +5 -2
  112. data/test/test_helpers_test.rb +4 -4
  113. metadata +36 -21
  114. data/lib/devise/models/http_authenticatable.rb +0 -19
  115. data/lib/devise/orm/mongo_mapper.rb +0 -49
  116. data/lib/devise/strategies/http_authenticatable.rb +0 -47
  117. data/test/models/http_authenticatable_test.rb +0 -19
  118. data/test/orm/mongo_mapper.rb +0 -12
  119. data/test/rails_app/app/mongo_mapper/admin.rb +0 -10
  120. data/test/rails_app/app/mongo_mapper/user.rb +0 -11
  121. data/test/rails_app/config/initializers/cookie_verification_secret.rb +0 -7
  122. data/test/rails_app/config/initializers/session_store.rb +0 -15
@@ -0,0 +1,40 @@
1
+ module Devise
2
+ module Orm
3
+ module Mongoid
4
+ module Hook
5
+ def devise_modules_hook!
6
+ extend Schema
7
+ include ::Mongoid::Timestamps
8
+ include Compatibility
9
+ yield
10
+ return unless Devise.apply_schema
11
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
12
+ end
13
+ end
14
+
15
+ module Schema
16
+ include Devise::Schema
17
+
18
+ # Tell how to apply schema methods
19
+ def apply_schema(name, type, options={})
20
+ type = Time if type == DateTime
21
+ field name, { :type => type }.merge(options)
22
+ end
23
+ end
24
+
25
+ module Compatibility
26
+ def save(validate = true)
27
+ if validate.is_a?(Hash) && validate.has_key?(:validate)
28
+ validate = validate[:validate]
29
+ end
30
+ super(validate)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ Mongoid::Document::ClassMethods.class_eval do
38
+ include Devise::Models
39
+ include Devise::Orm::Mongoid::Hook
40
+ end
@@ -3,10 +3,33 @@ require 'devise/rails/warden_compat'
3
3
 
4
4
  module Devise
5
5
  class Engine < ::Rails::Engine
6
- engine_name :devise
6
+ config.devise = Devise
7
7
 
8
- config.middleware.use Warden::Manager do |config|
9
- Devise.configure_warden(config)
8
+ initializer "devise.add_middleware" do |app|
9
+ app.config.middleware.use Warden::Manager do |config|
10
+ Devise.warden_config = config
11
+ config.failure_app = Devise::FailureApp
12
+ config.default_scope = Devise.default_scope
13
+ end
14
+ end
15
+
16
+ initializer "devise.add_url_helpers" do |app|
17
+ Devise::FailureApp.send :include, app.routes.url_helpers
18
+ end
19
+
20
+ config.after_initialize do
21
+ I18n.available_locales
22
+ flash = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked]
23
+
24
+ I18n.backend.send(:translations).each do |locale, translations|
25
+ keys = flash & (translations[:devise][:sessions].keys) rescue []
26
+
27
+ if keys.any?
28
+ ActiveSupport::Deprecation.warn "The following I18n messages in 'devise.sessions' " <<
29
+ "for locale '#{locale}' are deprecated: #{keys.to_sentence}. Please move them to " <<
30
+ "'devise.failure' instead."
31
+ end
32
+ end
10
33
  end
11
34
  end
12
35
  end
@@ -4,11 +4,9 @@ module ActionDispatch::Routing
4
4
  # need devise_for mappings already declared to create filters and helpers.
5
5
  def finalize_with_devise!
6
6
  finalize_without_devise!
7
- return if Devise.mappings.empty?
8
-
7
+ Devise.configure_warden!
9
8
  ActionController::Base.send :include, Devise::Controllers::Helpers
10
9
  ActionController::Base.send :include, Devise::Controllers::UrlHelpers
11
-
12
10
  ActionView::Base.send :include, Devise::Controllers::UrlHelpers
13
11
  end
14
12
  alias_method_chain :finalize!, :devise
@@ -83,31 +81,35 @@ module ActionDispatch::Routing
83
81
  #
84
82
  # devise_for :users, :controllers => { :sessions => "users/sessions" }
85
83
  #
84
+ # * :skip => tell which controller you want to skip routes from being created:
85
+ #
86
+ # devise_for :users, :skip => :sessions
87
+ #
86
88
  def devise_for(*resources)
87
89
  options = resources.extract_options!
88
90
  resources.map!(&:to_sym)
89
91
 
90
92
  resources.each do |resource|
91
- mapping = Devise::Mapping.new(resource, options)
93
+ mapping = Devise.register(resource, options)
92
94
 
93
95
  unless mapping.to.respond_to?(:devise)
94
96
  raise "#{mapping.to.name} does not respond to 'devise' method. This usually means you haven't " <<
95
- "loaded your ORM file or it's being loaded to late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
97
+ "loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
96
98
  "inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
97
99
  end
98
100
 
99
- Devise.default_scope ||= mapping.name
100
- Devise.mappings[mapping.name] = mapping
101
+ routes = mapping.routes
102
+ routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
101
103
 
102
- mapping.modules.each do |mod|
103
- send(mod, mapping, mapping.controllers) if self.respond_to?(mod, true)
104
+ routes.each do |mod|
105
+ send(:"devise_#{mod}", mapping, mapping.controllers)
104
106
  end
105
107
  end
106
108
  end
107
109
 
108
110
  protected
109
111
 
110
- def authenticatable(mapping, controllers)
112
+ def devise_session(mapping, controllers)
111
113
  scope mapping.path do
112
114
  get mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#new", :as => :"new_#{mapping.name}_session"
113
115
  post mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#create", :as => :"#{mapping.name}_session"
@@ -115,27 +117,27 @@ module ActionDispatch::Routing
115
117
  end
116
118
  end
117
119
 
118
- def recoverable(mapping, controllers)
120
+ def devise_password(mapping, controllers)
119
121
  scope mapping.path, :name_prefix => mapping.name do
120
122
  resource :password, :only => [:new, :create, :edit, :update], :as => mapping.path_names[:password], :controller => controllers[:passwords]
121
123
  end
122
124
  end
123
125
 
124
- def confirmable(mapping, controllers)
126
+ def devise_confirmation(mapping, controllers)
125
127
  scope mapping.path, :name_prefix => mapping.name do
126
128
  resource :confirmation, :only => [:new, :create, :show], :as => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
127
129
  end
128
130
  end
129
131
 
130
- def lockable(mapping, controllers)
132
+ def devise_unlock(mapping, controllers)
131
133
  scope mapping.path, :name_prefix => mapping.name do
132
134
  resource :unlock, :only => [:new, :create, :show], :as => mapping.path_names[:unlock], :controller => controllers[:unlocks]
133
135
  end
134
136
  end
135
137
 
136
- def registerable(mapping, controllers)
137
- scope :name_prefix => mapping.name do
138
- resource :registration, :only => [:new, :create, :edit, :update, :destroy], :as => mapping.path[1..-1],
138
+ def devise_registration(mapping, controllers)
139
+ scope mapping.path[1..-1], :name_prefix => "#{mapping.name}_registration" do
140
+ resource :registration, :only => [:new, :create, :edit, :update, :destroy], :as => "",
139
141
  :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
140
142
  end
141
143
  end
@@ -8,8 +8,8 @@ module Warden::Mixins::Common
8
8
  raw_session.clear
9
9
  end
10
10
 
11
- def response
12
- @response ||= env['action_controller.instance'].response
11
+ def cookies
12
+ request.cookie_jar
13
13
  end
14
14
  end
15
15
 
@@ -3,59 +3,86 @@ module Devise
3
3
  # and overwrite the apply_schema method.
4
4
  module Schema
5
5
 
6
+ def authenticatable(*args)
7
+ ActiveSupport::Deprecation.warn "t.authenticatable in migrations is deprecated. Please use t.database_authenticatable instead.", caller
8
+ database_authenticatable(*args)
9
+ end
10
+
6
11
  # Creates email, encrypted_password and password_salt.
7
12
  #
8
13
  # == Options
9
14
  # * :null - When true, allow columns to be null.
10
- # * :encryptor - The encryptor going to be used, necessary for setting the proper encrypter password length.
11
- def authenticatable(options={})
12
- null = options[:null] || false
13
- default = options[:default]
14
- encryptor = options[:encryptor] || (respond_to?(:encryptor) ? self.encryptor : :sha1)
15
+ # * :default - Should be set to "" when :null is false.
16
+ def database_authenticatable(options={})
17
+ null = options[:null] || false
18
+ default = options[:default] || ""
19
+
20
+ if options.delete(:encryptor)
21
+ ActiveSupport::Deprecation.warn ":encryptor as option is deprecated, simply remove it."
22
+ end
15
23
 
16
24
  apply_schema :email, String, :null => null, :default => default
17
- apply_schema :encrypted_password, String, :null => null, :default => default, :limit => Devise::ENCRYPTORS_LENGTH[encryptor]
25
+ apply_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
18
26
  apply_schema :password_salt, String, :null => null, :default => default
19
- end
27
+ end
20
28
 
21
29
  # Creates authentication_token.
22
- def token_authenticatable
23
- apply_schema :authentication_token, String, :limit => 20
30
+ def token_authenticatable(options={})
31
+ apply_schema :authentication_token, String
24
32
  end
25
33
 
26
34
  # Creates confirmation_token, confirmed_at and confirmation_sent_at.
27
35
  def confirmable
28
- apply_schema :confirmation_token, String, :limit => 20
36
+ apply_schema :confirmation_token, String
29
37
  apply_schema :confirmed_at, DateTime
30
38
  apply_schema :confirmation_sent_at, DateTime
31
39
  end
32
40
 
33
41
  # Creates reset_password_token.
34
42
  def recoverable
35
- apply_schema :reset_password_token, String, :limit => 20
43
+ apply_schema :reset_password_token, String
36
44
  end
37
45
 
38
46
  # Creates remember_token and remember_created_at.
39
47
  def rememberable
40
- apply_schema :remember_token, String, :limit => 20
48
+ apply_schema :remember_token, String
41
49
  apply_schema :remember_created_at, DateTime
42
50
  end
43
51
 
44
52
  # Creates sign_in_count, current_sign_in_at, last_sign_in_at,
45
53
  # current_sign_in_ip, last_sign_in_ip.
46
54
  def trackable
47
- apply_schema :sign_in_count, Integer
55
+ apply_schema :sign_in_count, Integer, :default => 0
48
56
  apply_schema :current_sign_in_at, DateTime
49
57
  apply_schema :last_sign_in_at, DateTime
50
58
  apply_schema :current_sign_in_ip, String
51
59
  apply_schema :last_sign_in_ip, String
52
60
  end
53
61
 
54
- # Creates failed_attempts, unlock_token and locked_at
55
- def lockable
56
- apply_schema :failed_attempts, Integer, :default => 0
57
- apply_schema :unlock_token, String, :limit => 20
58
- apply_schema :locked_at, DateTime
62
+ # Creates failed_attempts, unlock_token and locked_at depending on the options given.
63
+ #
64
+ # == Options
65
+ # * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
66
+ # If :email or :both, creates a unlock_token field.
67
+ # * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
68
+ def lockable(options={})
69
+ unlock_strategy = options[:unlock_strategy]
70
+ unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
71
+ unlock_strategy ||= :both
72
+
73
+ lock_strategy = options[:lock_strategy]
74
+ lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
75
+ lock_strategy ||= :failed_attempts
76
+
77
+ if lock_strategy == :failed_attempts
78
+ apply_schema :failed_attempts, Integer, :default => 0
79
+ end
80
+
81
+ if [:both, :email].include?(unlock_strategy)
82
+ apply_schema :unlock_token, String
83
+ end
84
+
85
+ apply_schema :locked_at, DateTime
59
86
  end
60
87
 
61
88
  # Overwrite with specific modification to create your own schema.
@@ -2,35 +2,106 @@ require 'devise/strategies/base'
2
2
 
3
3
  module Devise
4
4
  module Strategies
5
- # Default strategy for signing in a user, based on his email and password.
6
- # Redirects to sign_in page if it's not authenticated
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.
7
8
  class Authenticatable < Base
9
+ attr_accessor :authentication_hash, :password
10
+
8
11
  def valid?
9
- valid_controller? && valid_params? && mapping.to.respond_to?(:authenticate)
12
+ valid_for_http_auth? || valid_for_params_auth?
10
13
  end
11
14
 
12
- # Authenticate a user based on email and password params, returning to warden
13
- # success and the authenticated user if everything is okay. Otherwise redirect
14
- # to sign in page.
15
- def authenticate!
16
- if resource = mapping.to.authenticate(params[scope])
17
- success!(resource)
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 Symbol, String
23
+ fail!(result)
18
24
  else
19
- fail!(:invalid)
20
- end
25
+ result
26
+ end
27
+ end
28
+
29
+ # Check if this is strategy is valid for http authentication.
30
+ def valid_for_http_auth?
31
+ http_authenticatable? && request.authorization && with_authentication_hash(http_auth_hash)
32
+ end
33
+
34
+ # Check if this is strategy is valid for params authentication.
35
+ def valid_for_params_auth?
36
+ params_authenticatable? && valid_request? &&
37
+ valid_params? && with_authentication_hash(params_auth_hash)
38
+ end
39
+
40
+ # Check if the model accepts this strategy as http authenticatable.
41
+ def http_authenticatable?
42
+ mapping.to.http_authenticatable?(authenticatable_name)
43
+ end
44
+
45
+ # Check if the model accepts this strategy as params authenticatable.
46
+ def params_authenticatable?
47
+ mapping.to.params_authenticatable?(authenticatable_name)
48
+ end
49
+
50
+ # Extract the appropriate subhash for authentication from params.
51
+ def params_auth_hash
52
+ params[scope]
53
+ end
54
+
55
+ # Extract a hash with attributes:values from the http params.
56
+ def http_auth_hash
57
+ keys = [authentication_keys.first, :password]
58
+ Hash[*keys.zip(decode_credentials).flatten]
21
59
  end
22
60
 
23
- protected
61
+ # By default, a request is valid if the controller is allowed and the VERB is POST.
62
+ def valid_request?
63
+ valid_controller? && valid_verb?
64
+ end
65
+
66
+ # Check if the controller is valid for params authentication.
67
+ def valid_controller?
68
+ mapping.controllers[:sessions] == params[:controller]
69
+ end
70
+
71
+ # Check if the params_auth_hash is valid for params authentication.
72
+ def valid_verb?
73
+ request.post?
74
+ end
75
+
76
+ # If the request is valid, finally check if params_auth_hash returns a hash.
77
+ def valid_params?
78
+ params_auth_hash.is_a?(Hash)
79
+ end
24
80
 
25
- def valid_controller?
26
- mapping.controllers[:sessions] == params[:controller]
27
- end
81
+ # Helper to decode credentials from HTTP.
82
+ def decode_credentials
83
+ username_and_password = request.authorization.split(' ', 2).last || ''
84
+ ActiveSupport::Base64.decode64(username_and_password).split(/:/, 2)
85
+ end
86
+
87
+ # Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
88
+ def with_authentication_hash(hash)
89
+ self.authentication_hash = hash.slice(*authentication_keys)
90
+ self.password = hash[:password]
91
+ authentication_keys.all?{ |k| authentication_hash[k].present? }
92
+ end
28
93
 
29
- def valid_params?
30
- params[scope] && params[scope][:password].present?
31
- end
94
+ # Holds the authentication keys.
95
+ def authentication_keys
96
+ @authentication_keys ||= mapping.to.authentication_keys
97
+ end
98
+
99
+ # Holds the authenticatable name for this class. Devise::Strategies::DatabaseAuthenticatable
100
+ # becomes simply :database.
101
+ def authenticatable_name
102
+ @authenticatable_name ||=
103
+ self.class.name.split("::").last.underscore.sub("_authenticatable", "").to_sym
104
+ end
32
105
  end
33
106
  end
34
- end
35
-
36
- Warden::Strategies.add(:authenticatable, Devise::Strategies::Authenticatable)
107
+ end
@@ -2,8 +2,7 @@ module Devise
2
2
  module Strategies
3
3
  # Base strategy for Devise. Responsible for verifying correct scope and mapping.
4
4
  class Base < ::Warden::Strategies::Base
5
- # Checks if a valid scope was given for devise and find mapping based on
6
- # this scope.
5
+ # Checks if a valid scope was given for devise and find mapping based on this scope.
7
6
  def mapping
8
7
  @mapping ||= begin
9
8
  mapping = Devise.mappings[scope]
@@ -11,6 +10,10 @@ module Devise
11
10
  mapping
12
11
  end
13
12
  end
13
+
14
+ def succeeded?
15
+ @result == :success
16
+ end
14
17
  end
15
18
  end
16
- end
19
+ end
@@ -0,0 +1,20 @@
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 = mapping.to.find_for_database_authentication(authentication_hash)
9
+
10
+ if validate(resource){ resource.valid_password?(password) }
11
+ success!(resource)
12
+ else
13
+ fail(:invalid)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ Warden::Strategies.add(:database_authenticatable, Devise::Strategies::DatabaseAuthenticatable)