devise-edge 1.2.rc

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 (161) hide show
  1. data/CHANGELOG.rdoc +500 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +335 -0
  4. data/app/controllers/devise/confirmations_controller.rb +33 -0
  5. data/app/controllers/devise/oauth_callbacks_controller.rb +4 -0
  6. data/app/controllers/devise/passwords_controller.rb +41 -0
  7. data/app/controllers/devise/registrations_controller.rb +75 -0
  8. data/app/controllers/devise/sessions_controller.rb +23 -0
  9. data/app/controllers/devise/unlocks_controller.rb +34 -0
  10. data/app/helpers/devise_helper.rb +17 -0
  11. data/app/mailers/devise/mailer.rb +88 -0
  12. data/app/views/devise/confirmations/new.html.erb +12 -0
  13. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  14. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  15. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  16. data/app/views/devise/passwords/edit.html.erb +16 -0
  17. data/app/views/devise/passwords/new.html.erb +12 -0
  18. data/app/views/devise/registrations/edit.html.erb +25 -0
  19. data/app/views/devise/registrations/new.html.erb +18 -0
  20. data/app/views/devise/sessions/new.html.erb +17 -0
  21. data/app/views/devise/shared/_links.erb +25 -0
  22. data/app/views/devise/unlocks/new.html.erb +12 -0
  23. data/config/locales/en.yml +42 -0
  24. data/lib/devise.rb +371 -0
  25. data/lib/devise/controllers/helpers.rb +261 -0
  26. data/lib/devise/controllers/internal_helpers.rb +113 -0
  27. data/lib/devise/controllers/scoped_views.rb +33 -0
  28. data/lib/devise/controllers/url_helpers.rb +39 -0
  29. data/lib/devise/encryptors/authlogic_sha512.rb +19 -0
  30. data/lib/devise/encryptors/base.rb +20 -0
  31. data/lib/devise/encryptors/clearance_sha1.rb +17 -0
  32. data/lib/devise/encryptors/restful_authentication_sha1.rb +22 -0
  33. data/lib/devise/encryptors/sha1.rb +25 -0
  34. data/lib/devise/encryptors/sha512.rb +25 -0
  35. data/lib/devise/failure_app.rb +126 -0
  36. data/lib/devise/hooks/activatable.rb +11 -0
  37. data/lib/devise/hooks/forgetable.rb +12 -0
  38. data/lib/devise/hooks/rememberable.rb +45 -0
  39. data/lib/devise/hooks/timeoutable.rb +22 -0
  40. data/lib/devise/hooks/trackable.rb +9 -0
  41. data/lib/devise/mapping.rb +105 -0
  42. data/lib/devise/models.rb +66 -0
  43. data/lib/devise/models/authenticatable.rb +143 -0
  44. data/lib/devise/models/confirmable.rb +160 -0
  45. data/lib/devise/models/database_authenticatable.rb +94 -0
  46. data/lib/devise/models/encryptable.rb +65 -0
  47. data/lib/devise/models/lockable.rb +168 -0
  48. data/lib/devise/models/oauthable.rb +49 -0
  49. data/lib/devise/models/recoverable.rb +83 -0
  50. data/lib/devise/models/registerable.rb +21 -0
  51. data/lib/devise/models/rememberable.rb +122 -0
  52. data/lib/devise/models/timeoutable.rb +33 -0
  53. data/lib/devise/models/token_authenticatable.rb +72 -0
  54. data/lib/devise/models/trackable.rb +30 -0
  55. data/lib/devise/models/validatable.rb +60 -0
  56. data/lib/devise/modules.rb +30 -0
  57. data/lib/devise/oauth.rb +41 -0
  58. data/lib/devise/oauth/config.rb +33 -0
  59. data/lib/devise/oauth/helpers.rb +18 -0
  60. data/lib/devise/oauth/internal_helpers.rb +182 -0
  61. data/lib/devise/oauth/test_helpers.rb +29 -0
  62. data/lib/devise/oauth/url_helpers.rb +35 -0
  63. data/lib/devise/orm/active_record.rb +36 -0
  64. data/lib/devise/orm/mongo_mapper.rb +46 -0
  65. data/lib/devise/orm/mongoid.rb +29 -0
  66. data/lib/devise/path_checker.rb +18 -0
  67. data/lib/devise/rails.rb +67 -0
  68. data/lib/devise/rails/routes.rb +260 -0
  69. data/lib/devise/rails/warden_compat.rb +42 -0
  70. data/lib/devise/schema.rb +96 -0
  71. data/lib/devise/strategies/authenticatable.rb +150 -0
  72. data/lib/devise/strategies/base.rb +15 -0
  73. data/lib/devise/strategies/database_authenticatable.rb +21 -0
  74. data/lib/devise/strategies/rememberable.rb +51 -0
  75. data/lib/devise/strategies/token_authenticatable.rb +53 -0
  76. data/lib/devise/test_helpers.rb +100 -0
  77. data/lib/devise/version.rb +3 -0
  78. data/lib/generators/active_record/devise_generator.rb +28 -0
  79. data/lib/generators/active_record/templates/migration.rb +30 -0
  80. data/lib/generators/devise/devise_generator.rb +17 -0
  81. data/lib/generators/devise/install_generator.rb +24 -0
  82. data/lib/generators/devise/orm_helpers.rb +24 -0
  83. data/lib/generators/devise/views_generator.rb +63 -0
  84. data/lib/generators/mongoid/devise_generator.rb +17 -0
  85. data/lib/generators/templates/README +25 -0
  86. data/lib/generators/templates/devise.rb +168 -0
  87. data/test/controllers/helpers_test.rb +220 -0
  88. data/test/controllers/internal_helpers_test.rb +56 -0
  89. data/test/controllers/url_helpers_test.rb +59 -0
  90. data/test/devise_test.rb +65 -0
  91. data/test/encryptors_test.rb +30 -0
  92. data/test/failure_app_test.rb +148 -0
  93. data/test/integration/authenticatable_test.rb +424 -0
  94. data/test/integration/confirmable_test.rb +104 -0
  95. data/test/integration/database_authenticatable_test.rb +38 -0
  96. data/test/integration/http_authenticatable_test.rb +64 -0
  97. data/test/integration/lockable_test.rb +109 -0
  98. data/test/integration/oauthable_test.rb +258 -0
  99. data/test/integration/recoverable_test.rb +141 -0
  100. data/test/integration/registerable_test.rb +179 -0
  101. data/test/integration/rememberable_test.rb +179 -0
  102. data/test/integration/timeoutable_test.rb +80 -0
  103. data/test/integration/token_authenticatable_test.rb +99 -0
  104. data/test/integration/trackable_test.rb +64 -0
  105. data/test/mailers/confirmation_instructions_test.rb +84 -0
  106. data/test/mailers/reset_password_instructions_test.rb +72 -0
  107. data/test/mailers/unlock_instructions_test.rb +66 -0
  108. data/test/mapping_test.rb +95 -0
  109. data/test/models/confirmable_test.rb +221 -0
  110. data/test/models/database_authenticatable_test.rb +82 -0
  111. data/test/models/encryptable_test.rb +65 -0
  112. data/test/models/lockable_test.rb +204 -0
  113. data/test/models/oauthable_test.rb +21 -0
  114. data/test/models/recoverable_test.rb +155 -0
  115. data/test/models/rememberable_test.rb +271 -0
  116. data/test/models/timeoutable_test.rb +28 -0
  117. data/test/models/token_authenticatable_test.rb +37 -0
  118. data/test/models/trackable_test.rb +5 -0
  119. data/test/models/validatable_test.rb +99 -0
  120. data/test/models_test.rb +77 -0
  121. data/test/oauth/config_test.rb +44 -0
  122. data/test/oauth/url_helpers_test.rb +47 -0
  123. data/test/orm/active_record.rb +9 -0
  124. data/test/orm/mongoid.rb +10 -0
  125. data/test/rails_app/app/active_record/admin.rb +6 -0
  126. data/test/rails_app/app/active_record/shim.rb +2 -0
  127. data/test/rails_app/app/active_record/user.rb +8 -0
  128. data/test/rails_app/app/controllers/admins/sessions_controller.rb +6 -0
  129. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  130. data/test/rails_app/app/controllers/application_controller.rb +9 -0
  131. data/test/rails_app/app/controllers/home_controller.rb +12 -0
  132. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
  133. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
  134. data/test/rails_app/app/controllers/users_controller.rb +18 -0
  135. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  136. data/test/rails_app/app/mongoid/admin.rb +9 -0
  137. data/test/rails_app/app/mongoid/shim.rb +24 -0
  138. data/test/rails_app/app/mongoid/user.rb +10 -0
  139. data/test/rails_app/config/application.rb +35 -0
  140. data/test/rails_app/config/boot.rb +13 -0
  141. data/test/rails_app/config/environment.rb +5 -0
  142. data/test/rails_app/config/environments/development.rb +19 -0
  143. data/test/rails_app/config/environments/production.rb +33 -0
  144. data/test/rails_app/config/environments/test.rb +33 -0
  145. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  146. data/test/rails_app/config/initializers/devise.rb +172 -0
  147. data/test/rails_app/config/initializers/inflections.rb +2 -0
  148. data/test/rails_app/config/initializers/secret_token.rb +2 -0
  149. data/test/rails_app/config/routes.rb +54 -0
  150. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +31 -0
  151. data/test/rails_app/db/schema.rb +52 -0
  152. data/test/rails_app/lib/shared_admin.rb +9 -0
  153. data/test/rails_app/lib/shared_user.rb +48 -0
  154. data/test/routes_test.rb +189 -0
  155. data/test/support/assertions.rb +24 -0
  156. data/test/support/helpers.rb +60 -0
  157. data/test/support/integration.rb +88 -0
  158. data/test/support/webrat/integrations/rails.rb +24 -0
  159. data/test/test_helper.rb +23 -0
  160. data/test/test_helpers_test.rb +101 -0
  161. metadata +335 -0
@@ -0,0 +1,42 @@
1
+ module Warden::Mixins::Common
2
+ def request
3
+ @request ||= ActionDispatch::Request.new(env)
4
+ end
5
+
6
+ def reset_session!
7
+ raw_session.inspect # why do I have to inspect it to get it to clear?
8
+ raw_session.clear
9
+ end
10
+
11
+ def cookies
12
+ request.cookie_jar
13
+ end
14
+ end
15
+
16
+ class Warden::SessionSerializer
17
+ def serialize(record)
18
+ [record.class.name, record.id, record.authenticatable_salt]
19
+ end
20
+
21
+ def deserialize(keys)
22
+ if keys.size == 2
23
+ raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
24
+ "you can fix it by changing one character in your cookie secret, forcing all previous " <<
25
+ "cookies to expire, or cleaning up your database sessions if you are using a db store."
26
+ end
27
+
28
+ klass, id, salt = keys
29
+
30
+ begin
31
+ record = klass.constantize.find(:first, :conditions => { :id => id })
32
+ record if record && record.authenticatable_salt == salt
33
+ rescue NameError => e
34
+ if e.message =~ /uninitialized constant/
35
+ Rails.logger.debug "Trying to deserialize invalid class #{klass}"
36
+ nil
37
+ else
38
+ raise
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,96 @@
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 email, encrypted_password and password_salt.
7
+ #
8
+ # == Options
9
+ # * :null - When true, allow columns to be null.
10
+ # * :default - Should be set to "" when :null is false.
11
+ #
12
+ # == Notes
13
+ # For Datamapper compatibility, we explicitly hardcode the limit for the
14
+ # encrypter password field in 128 characters.
15
+ def database_authenticatable(options={})
16
+ null = options[:null] || false
17
+ default = options.key?(:default) ? options[:default] : ("" if null == false)
18
+
19
+ apply_devise_schema :email, String, :null => null, :default => default
20
+ apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
21
+ end
22
+
23
+ # Creates password salt for encryption support.
24
+ def encryptable
25
+ apply_devise_schema :password_salt, String
26
+ end
27
+
28
+ # Creates authentication_token.
29
+ def token_authenticatable
30
+ apply_devise_schema :authentication_token, String
31
+ end
32
+
33
+ # Creates confirmation_token, confirmed_at and confirmation_sent_at.
34
+ def confirmable
35
+ apply_devise_schema :confirmation_token, String
36
+ apply_devise_schema :confirmed_at, DateTime
37
+ apply_devise_schema :confirmation_sent_at, DateTime
38
+ end
39
+
40
+ # Creates reset_password_token.
41
+ def recoverable
42
+ apply_devise_schema :reset_password_token, String
43
+ end
44
+
45
+ # Creates remember_token and remember_created_at.
46
+ #
47
+ # == Options
48
+ # * :use_salt - When true, does not create a remember_token and use password_salt instead.
49
+ def rememberable(options={})
50
+ use_salt = options.fetch(:use_salt, Devise.use_salt_as_remember_token)
51
+ apply_devise_schema :remember_token, String unless use_salt
52
+ apply_devise_schema :remember_created_at, DateTime
53
+ end
54
+
55
+ # Creates sign_in_count, current_sign_in_at, last_sign_in_at,
56
+ # current_sign_in_ip, last_sign_in_ip.
57
+ def trackable
58
+ apply_devise_schema :sign_in_count, Integer, :default => 0
59
+ apply_devise_schema :current_sign_in_at, DateTime
60
+ apply_devise_schema :last_sign_in_at, DateTime
61
+ apply_devise_schema :current_sign_in_ip, String
62
+ apply_devise_schema :last_sign_in_ip, String
63
+ end
64
+
65
+ # Creates failed_attempts, unlock_token and locked_at depending on the options given.
66
+ #
67
+ # == Options
68
+ # * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
69
+ # If :email or :both, creates a unlock_token field.
70
+ # * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
71
+ def lockable(options={})
72
+ unlock_strategy = options[:unlock_strategy]
73
+ unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
74
+ unlock_strategy ||= :both
75
+
76
+ lock_strategy = options[:lock_strategy]
77
+ lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
78
+ lock_strategy ||= :failed_attempts
79
+
80
+ if lock_strategy == :failed_attempts
81
+ apply_devise_schema :failed_attempts, Integer, :default => 0
82
+ end
83
+
84
+ if [:both, :email].include?(unlock_strategy)
85
+ apply_devise_schema :unlock_token, String
86
+ end
87
+
88
+ apply_devise_schema :locked_at, DateTime
89
+ end
90
+
91
+ # Overwrite with specific modification to create your own schema.
92
+ def apply_devise_schema(name, type, options={})
93
+ raise NotImplementedError
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,150 @@
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 Symbol, String
23
+ fail!(result)
24
+ else
25
+ result
26
+ end
27
+ end
28
+
29
+ # Check if this is strategy is valid for http authentication by:
30
+ #
31
+ # * Validating if the model allows params authentication;
32
+ # * If any of the authorization headers were sent;
33
+ # * If all authentication keys are present;
34
+ #
35
+ def valid_for_http_auth?
36
+ http_authenticatable? && request.authorization && with_authentication_hash(http_auth_hash)
37
+ end
38
+
39
+ # Check if this is strategy is valid for params authentication by:
40
+ #
41
+ # * Validating if the model allows params authentication;
42
+ # * If the request hits the sessions controller through POST;
43
+ # * If the params[scope] returns a hash with credentials;
44
+ # * If all authentication keys are present;
45
+ #
46
+ def valid_for_params_auth?
47
+ params_authenticatable? && valid_request? &&
48
+ valid_params? && with_authentication_hash(params_auth_hash)
49
+ end
50
+
51
+ # Check if the model accepts this strategy as http authenticatable.
52
+ def http_authenticatable?
53
+ mapping.to.http_authenticatable?(authenticatable_name)
54
+ end
55
+
56
+ # Check if the model accepts this strategy as params authenticatable.
57
+ def params_authenticatable?
58
+ mapping.to.params_authenticatable?(authenticatable_name)
59
+ end
60
+
61
+ # Extract the appropriate subhash for authentication from params.
62
+ def params_auth_hash
63
+ params[scope]
64
+ end
65
+
66
+ # Extract a hash with attributes:values from the http params.
67
+ def http_auth_hash
68
+ keys = [authentication_keys.first, :password]
69
+ Hash[*keys.zip(decode_credentials).flatten]
70
+ end
71
+
72
+ # By default, a request is valid if the controller is allowed and the VERB is POST.
73
+ def valid_request?
74
+ valid_controller? && valid_verb?
75
+ end
76
+
77
+ # Check if the controller is the one registered for authentication.
78
+ def valid_controller?
79
+ mapping.controllers[:sessions] == params[:controller]
80
+ end
81
+
82
+ # Check if it was a POST request.
83
+ def valid_verb?
84
+ request.post?
85
+ end
86
+
87
+ # If the request is valid, finally check if params_auth_hash returns a hash.
88
+ def valid_params?
89
+ params_auth_hash.is_a?(Hash)
90
+ end
91
+
92
+ # Check if password is present and is not equal to "X" (default value for token).
93
+ def valid_password?
94
+ password.present? && password != "X"
95
+ end
96
+
97
+ # Helper to decode credentials from HTTP.
98
+ def decode_credentials
99
+ return [] unless request.authorization && request.authorization =~ /^Basic (.*)/
100
+ ActiveSupport::Base64.decode64($1).split(/:/, 2)
101
+ end
102
+
103
+ # Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
104
+ def with_authentication_hash(auth_values)
105
+ self.authentication_hash = {}
106
+ self.password = auth_values[:password]
107
+
108
+ parse_authentication_key_values(auth_values, authentication_keys) &&
109
+ parse_authentication_key_values(request_values, request_keys)
110
+ end
111
+
112
+ # Holds the authentication keys.
113
+ def authentication_keys
114
+ @authentication_keys ||= mapping.to.authentication_keys
115
+ end
116
+
117
+ # Holds request keys.
118
+ def request_keys
119
+ @request_keys ||= mapping.to.request_keys
120
+ end
121
+
122
+ # Returns values from the request object.
123
+ def request_values
124
+ keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
125
+ values = keys.map { |k| self.request.send(k) }
126
+ Hash[keys.zip(values)]
127
+ end
128
+
129
+ # Parse authentication keys considering if they should be enforced or not.
130
+ def parse_authentication_key_values(hash, keys)
131
+ keys.each do |key, enforce|
132
+ value = hash[key].presence
133
+ if value
134
+ self.authentication_hash[key] = value
135
+ else
136
+ return false unless enforce == false
137
+ end
138
+ end
139
+ true
140
+ end
141
+
142
+ # Holds the authenticatable name for this class. Devise::Strategies::DatabaseAuthenticatable
143
+ # becomes simply :database.
144
+ def authenticatable_name
145
+ @authenticatable_name ||=
146
+ self.class.name.split("::").last.underscore.sub("_authenticatable", "").to_sym
147
+ end
148
+ end
149
+ end
150
+ 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
+ else
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,51 @@
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.present?
13
+ end
14
+
15
+ # To authenticate a user we deserialize the cookie and attempt finding
16
+ # the record in the database. If the attempt fails, we pass to another
17
+ # strategy handle the authentication.
18
+ def authenticate!
19
+ resource = mapping.to.serialize_from_cookie(*remember_cookie)
20
+
21
+ if validate(resource)
22
+ success!(resource)
23
+ else
24
+ cookies.delete(remember_key)
25
+ pass
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def remember_me?
32
+ true
33
+ end
34
+
35
+ def remember_key
36
+ "remember_#{scope}_token"
37
+ end
38
+
39
+ def extend_remember_period?
40
+ mapping.to.extend_remember_period
41
+ end
42
+
43
+ # Accessor for remember cookie
44
+ def remember_cookie
45
+ @remember_cookie ||= cookies.signed[remember_key]
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
@@ -0,0 +1,53 @@
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
+ else
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
+ params[scope] || params
43
+ end
44
+
45
+ # Overwrite authentication keys to use token_authentication_key.
46
+ def authentication_keys
47
+ @authentication_keys ||= [mapping.to.token_authentication_key]
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Warden::Strategies.add(:token_authenticatable, Devise::Strategies::TokenAuthenticatable)
@@ -0,0 +1,100 @@
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 an 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
+ # This is a Warden::Proxy customized for functional tests. It's meant to
17
+ # some of Warden::Manager responsibilities, as retrieving configuration
18
+ # options and calling the FailureApp.
19
+ class TestWarden < Warden::Proxy #:nodoc:
20
+ attr_reader :controller
21
+
22
+ def initialize(controller)
23
+ @controller = controller
24
+ manager = Warden::Manager.new(nil) do |config|
25
+ config.merge! Devise.warden_config
26
+ end
27
+ super(controller.request.env, manager)
28
+ end
29
+
30
+ def authenticate!(*args)
31
+ catch_with_redirect { super }
32
+ end
33
+
34
+ def user(*args)
35
+ catch_with_redirect { super }
36
+ end
37
+
38
+ def catch_with_redirect(&block)
39
+ result = catch(:warden, &block)
40
+
41
+ if result.is_a?(Hash) && !custom_failure? && !@controller.send(:performed?)
42
+ result[:action] ||= :unauthenticated
43
+
44
+ env = @controller.request.env
45
+ env["PATH_INFO"] = "/#{result[:action]}"
46
+ env["warden.options"] = result
47
+ Warden::Manager._before_failure.each{ |hook| hook.call(env, result) }
48
+
49
+ status, headers, body = Devise::FailureApp.call(env).to_a
50
+ @controller.send :render, :status => status, :text => body,
51
+ :content_type => headers["Content-Type"], :location => headers["Location"]
52
+
53
+ nil
54
+ else
55
+ result
56
+ end
57
+ end
58
+ end
59
+
60
+ # We need to setup the environment variables and the response in the controller.
61
+ def setup_controller_for_warden #:nodoc:
62
+ @request.env['action_controller.instance'] = @controller
63
+ end
64
+
65
+ # Quick access to Warden::Proxy.
66
+ def warden #:nodoc:
67
+ @warden ||= (@request.env['warden'] = TestWarden.new(@controller))
68
+ end
69
+
70
+ # sign_in a given resource by storing its keys in the session.
71
+ # This method bypass any warden authentication callback.
72
+ #
73
+ # Examples:
74
+ #
75
+ # sign_in :user, @user # sign_in(scope, resource)
76
+ # sign_in @user # sign_in(resource)
77
+ #
78
+ def sign_in(resource_or_scope, resource=nil)
79
+ scope ||= Devise::Mapping.find_scope!(resource_or_scope)
80
+ resource ||= resource_or_scope
81
+ warden.session_serializer.store(resource, scope)
82
+ end
83
+
84
+ # Sign out a given resource or scope by calling logout on Warden.
85
+ # This method bypass any warden logout callback.
86
+ #
87
+ # Examples:
88
+ #
89
+ # sign_out :user # sign_out(scope)
90
+ # sign_out @user # sign_out(resource)
91
+ #
92
+ def sign_out(resource_or_scope)
93
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
94
+ @controller.instance_variable_set(:"@current_#{scope}", nil)
95
+ user = warden.instance_variable_get(:@users).delete(scope)
96
+ warden.session_serializer.delete(scope, user)
97
+ end
98
+
99
+ end
100
+ end