loyal_devise 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +15 -0
  3. data/CHANGELOG.rdoc +881 -0
  4. data/CONTRIBUTING.md +12 -0
  5. data/Gemfile +31 -0
  6. data/Gemfile.lock +154 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +388 -0
  9. data/Rakefile +34 -0
  10. data/app/controllers/devise/confirmations_controller.rb +44 -0
  11. data/app/controllers/devise/omniauth_callbacks_controller.rb +31 -0
  12. data/app/controllers/devise/passwords_controller.rb +57 -0
  13. data/app/controllers/devise/registrations_controller.rb +120 -0
  14. data/app/controllers/devise/sessions_controller.rb +51 -0
  15. data/app/controllers/devise/unlocks_controller.rb +45 -0
  16. data/app/controllers/devise_controller.rb +193 -0
  17. data/app/helpers/devise_helper.rb +26 -0
  18. data/app/mailers/devise/mailer.rb +16 -0
  19. data/app/views/devise/_links.erb +3 -0
  20. data/app/views/devise/confirmations/new.html.erb +12 -0
  21. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  22. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  23. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  24. data/app/views/devise/passwords/edit.html.erb +16 -0
  25. data/app/views/devise/passwords/new.html.erb +12 -0
  26. data/app/views/devise/registrations/edit.html.erb +25 -0
  27. data/app/views/devise/registrations/new.html.erb +18 -0
  28. data/app/views/devise/sessions/new.html.erb +17 -0
  29. data/app/views/devise/shared/_links.erb +25 -0
  30. data/app/views/devise/unlocks/new.html.erb +12 -0
  31. data/config/locales/en.yml +59 -0
  32. data/devise.gemspec +26 -0
  33. data/gemfiles/Gemfile.rails-3.1.x +35 -0
  34. data/gemfiles/Gemfile.rails-3.1.x.lock +167 -0
  35. data/lib/devise/controllers/helpers.rb +273 -0
  36. data/lib/devise/controllers/rememberable.rb +53 -0
  37. data/lib/devise/controllers/scoped_views.rb +18 -0
  38. data/lib/devise/controllers/url_helpers.rb +68 -0
  39. data/lib/devise/delegator.rb +17 -0
  40. data/lib/devise/failure_app.rb +188 -0
  41. data/lib/devise/hooks/activatable.rb +12 -0
  42. data/lib/devise/hooks/forgetable.rb +10 -0
  43. data/lib/devise/hooks/lockable.rb +8 -0
  44. data/lib/devise/hooks/rememberable.rb +7 -0
  45. data/lib/devise/hooks/timeoutable.rb +26 -0
  46. data/lib/devise/hooks/trackable.rb +10 -0
  47. data/lib/devise/mailers/helpers.rb +92 -0
  48. data/lib/devise/mapping.rb +173 -0
  49. data/lib/devise/models/authenticatable.rb +269 -0
  50. data/lib/devise/models/confirmable.rb +271 -0
  51. data/lib/devise/models/database_authenticatable.rb +127 -0
  52. data/lib/devise/models/lockable.rb +194 -0
  53. data/lib/devise/models/omniauthable.rb +28 -0
  54. data/lib/devise/models/recoverable.rb +141 -0
  55. data/lib/devise/models/registerable.rb +26 -0
  56. data/lib/devise/models/rememberable.rb +126 -0
  57. data/lib/devise/models/timeoutable.rb +50 -0
  58. data/lib/devise/models/token_authenticatable.rb +90 -0
  59. data/lib/devise/models/trackable.rb +36 -0
  60. data/lib/devise/models/validatable.rb +67 -0
  61. data/lib/devise/models.rb +129 -0
  62. data/lib/devise/modules.rb +30 -0
  63. data/lib/devise/omniauth/config.rb +46 -0
  64. data/lib/devise/omniauth/url_helpers.rb +19 -0
  65. data/lib/devise/omniauth.rb +29 -0
  66. data/lib/devise/orm/active_record.rb +4 -0
  67. data/lib/devise/orm/mongoid.rb +4 -0
  68. data/lib/devise/param_filter.rb +42 -0
  69. data/lib/devise/rails/routes.rb +447 -0
  70. data/lib/devise/rails/warden_compat.rb +44 -0
  71. data/lib/devise/rails.rb +55 -0
  72. data/lib/devise/strategies/authenticatable.rb +177 -0
  73. data/lib/devise/strategies/base.rb +21 -0
  74. data/lib/devise/strategies/database_authenticatable.rb +21 -0
  75. data/lib/devise/strategies/rememberable.rb +56 -0
  76. data/lib/devise/strategies/token_authenticatable.rb +57 -0
  77. data/lib/devise/test_helpers.rb +132 -0
  78. data/lib/devise/time_inflector.rb +15 -0
  79. data/lib/devise/version.rb +4 -0
  80. data/lib/devise.rb +445 -0
  81. data/lib/generators/active_record/devise_generator.rb +80 -0
  82. data/lib/generators/active_record/templates/migration.rb +20 -0
  83. data/lib/generators/active_record/templates/migration_existing.rb +27 -0
  84. data/lib/generators/devise/devise_generator.rb +25 -0
  85. data/lib/generators/devise/install_generator.rb +25 -0
  86. data/lib/generators/devise/orm_helpers.rb +33 -0
  87. data/lib/generators/devise/views_generator.rb +117 -0
  88. data/lib/generators/mongoid/devise_generator.rb +58 -0
  89. data/lib/generators/templates/README +35 -0
  90. data/lib/generators/templates/devise.rb +241 -0
  91. data/lib/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  92. data/lib/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  93. data/lib/generators/templates/markerb/unlock_instructions.markerb +7 -0
  94. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +15 -0
  95. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +19 -0
  96. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +15 -0
  97. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +22 -0
  98. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +17 -0
  99. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +15 -0
  100. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +15 -0
  101. data/test/controllers/custom_strategy_test.rb +63 -0
  102. data/test/controllers/helpers_test.rb +254 -0
  103. data/test/controllers/internal_helpers_test.rb +111 -0
  104. data/test/controllers/sessions_controller_test.rb +58 -0
  105. data/test/controllers/url_helpers_test.rb +60 -0
  106. data/test/delegator_test.rb +20 -0
  107. data/test/devise_test.rb +73 -0
  108. data/test/failure_app_test.rb +222 -0
  109. data/test/generators/active_record_generator_test.rb +76 -0
  110. data/test/generators/devise_generator_test.rb +40 -0
  111. data/test/generators/install_generator_test.rb +14 -0
  112. data/test/generators/mongoid_generator_test.rb +24 -0
  113. data/test/generators/views_generator_test.rb +53 -0
  114. data/test/helpers/devise_helper_test.rb +52 -0
  115. data/test/indifferent_hash.rb +34 -0
  116. data/test/integration/authenticatable_test.rb +634 -0
  117. data/test/integration/confirmable_test.rb +299 -0
  118. data/test/integration/database_authenticatable_test.rb +83 -0
  119. data/test/integration/http_authenticatable_test.rb +98 -0
  120. data/test/integration/lockable_test.rb +243 -0
  121. data/test/integration/omniauthable_test.rb +134 -0
  122. data/test/integration/recoverable_test.rb +307 -0
  123. data/test/integration/registerable_test.rb +346 -0
  124. data/test/integration/rememberable_test.rb +159 -0
  125. data/test/integration/timeoutable_test.rb +141 -0
  126. data/test/integration/token_authenticatable_test.rb +162 -0
  127. data/test/integration/trackable_test.rb +93 -0
  128. data/test/mailers/confirmation_instructions_test.rb +103 -0
  129. data/test/mailers/reset_password_instructions_test.rb +84 -0
  130. data/test/mailers/unlock_instructions_test.rb +78 -0
  131. data/test/mapping_test.rb +128 -0
  132. data/test/models/authenticatable_test.rb +8 -0
  133. data/test/models/confirmable_test.rb +392 -0
  134. data/test/models/database_authenticatable_test.rb +190 -0
  135. data/test/models/lockable_test.rb +274 -0
  136. data/test/models/omniauthable_test.rb +8 -0
  137. data/test/models/recoverable_test.rb +206 -0
  138. data/test/models/registerable_test.rb +8 -0
  139. data/test/models/rememberable_test.rb +175 -0
  140. data/test/models/serializable_test.rb +49 -0
  141. data/test/models/timeoutable_test.rb +47 -0
  142. data/test/models/token_authenticatable_test.rb +56 -0
  143. data/test/models/trackable_test.rb +14 -0
  144. data/test/models/validatable_test.rb +117 -0
  145. data/test/models_test.rb +180 -0
  146. data/test/omniauth/config_test.rb +58 -0
  147. data/test/omniauth/url_helpers_test.rb +52 -0
  148. data/test/orm/active_record.rb +10 -0
  149. data/test/orm/mongoid.rb +15 -0
  150. data/test/rails_app/Rakefile +10 -0
  151. data/test/rails_app/app/active_record/admin.rb +7 -0
  152. data/test/rails_app/app/active_record/shim.rb +3 -0
  153. data/test/rails_app/app/active_record/user.rb +7 -0
  154. data/test/rails_app/app/controllers/admins/sessions_controller.rb +7 -0
  155. data/test/rails_app/app/controllers/admins_controller.rb +12 -0
  156. data/test/rails_app/app/controllers/application_controller.rb +9 -0
  157. data/test/rails_app/app/controllers/home_controller.rb +26 -0
  158. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +3 -0
  159. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +3 -0
  160. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +15 -0
  161. data/test/rails_app/app/controllers/users_controller.rb +24 -0
  162. data/test/rails_app/app/helpers/application_helper.rb +4 -0
  163. data/test/rails_app/app/mailers/users/mailer.rb +9 -0
  164. data/test/rails_app/app/mongoid/admin.rb +28 -0
  165. data/test/rails_app/app/mongoid/shim.rb +25 -0
  166. data/test/rails_app/app/mongoid/user.rb +43 -0
  167. data/test/rails_app/app/views/admins/index.html.erb +1 -0
  168. data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
  169. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -0
  170. data/test/rails_app/app/views/home/index.html.erb +1 -0
  171. data/test/rails_app/app/views/home/join.html.erb +1 -0
  172. data/test/rails_app/app/views/home/private.html.erb +1 -0
  173. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -0
  174. data/test/rails_app/app/views/layouts/application.html.erb +24 -0
  175. data/test/rails_app/app/views/users/index.html.erb +1 -0
  176. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
  177. data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
  178. data/test/rails_app/config/application.rb +42 -0
  179. data/test/rails_app/config/boot.rb +9 -0
  180. data/test/rails_app/config/database.yml +18 -0
  181. data/test/rails_app/config/environment.rb +6 -0
  182. data/test/rails_app/config/environments/development.rb +19 -0
  183. data/test/rails_app/config/environments/production.rb +34 -0
  184. data/test/rails_app/config/environments/test.rb +34 -0
  185. data/test/rails_app/config/initializers/backtrace_silencers.rb +8 -0
  186. data/test/rails_app/config/initializers/devise.rb +179 -0
  187. data/test/rails_app/config/initializers/inflections.rb +3 -0
  188. data/test/rails_app/config/initializers/secret_token.rb +3 -0
  189. data/test/rails_app/config/routes.rb +101 -0
  190. data/test/rails_app/config.ru +4 -0
  191. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +75 -0
  192. data/test/rails_app/db/schema.rb +53 -0
  193. data/test/rails_app/lib/shared_admin.rb +15 -0
  194. data/test/rails_app/lib/shared_user.rb +27 -0
  195. data/test/rails_app/public/404.html +26 -0
  196. data/test/rails_app/public/422.html +26 -0
  197. data/test/rails_app/public/500.html +26 -0
  198. data/test/rails_app/public/favicon.ico +0 -0
  199. data/test/rails_app/script/rails +10 -0
  200. data/test/routes_test.rb +249 -0
  201. data/test/support/assertions.rb +41 -0
  202. data/test/support/helpers.rb +92 -0
  203. data/test/support/integration.rb +93 -0
  204. data/test/support/locale/en.yml +4 -0
  205. data/test/support/webrat/integrations/rails.rb +25 -0
  206. data/test/test_helper.rb +28 -0
  207. data/test/test_helpers_test.rb +152 -0
  208. metadata +407 -0
@@ -0,0 +1,68 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Devise
3
+ module Controllers
4
+ # Create url helpers to be used with resource/scope configuration. Acts as
5
+ # proxies to the generated routes created by devise.
6
+ # Resource param can be a string or symbol, a class, or an instance object.
7
+ # Example using a :user resource:
8
+ #
9
+ # new_session_path(:user) => new_user_session_path
10
+ # session_path(:user) => user_session_path
11
+ # destroy_session_path(:user) => destroy_user_session_path
12
+ #
13
+ # new_password_path(:user) => new_user_password_path
14
+ # password_path(:user) => user_password_path
15
+ # edit_password_path(:user) => edit_user_password_path
16
+ #
17
+ # new_confirmation_path(:user) => new_user_confirmation_path
18
+ # confirmation_path(:user) => user_confirmation_path
19
+ #
20
+ # Those helpers are included by default to ActionController::Base.
21
+ #
22
+ # In case you want to add such helpers to another class, you can do
23
+ # that as long as this new class includes both url_helpers and
24
+ # mounted_helpers. Example:
25
+ #
26
+ # include Rails.application.routes.url_helpers
27
+ # include Rails.application.routes.mounted_helpers
28
+ #
29
+ module UrlHelpers
30
+ def self.remove_helpers!
31
+ self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
32
+ remove_method method
33
+ end
34
+ end
35
+
36
+ def self.generate_helpers!(routes=nil)
37
+ routes ||= begin
38
+ mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
39
+ Devise::URL_HELPERS.slice(*mappings)
40
+ end
41
+
42
+ routes.each do |module_name, actions|
43
+ [:path, :url].each do |path_or_url|
44
+ actions.each do |action|
45
+ action = action ? "#{action}_" : ""
46
+ method = "#{action}#{module_name}_#{path_or_url}"
47
+
48
+ class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
49
+ def #{method}(resource_or_scope, *args)
50
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
51
+ _devise_route_context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
52
+ end
53
+ URL_HELPERS
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ generate_helpers!(Devise::URL_HELPERS)
60
+
61
+ private
62
+
63
+ def _devise_route_context
64
+ @_devise_route_context ||= send(Devise.available_router_name)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Devise
3
+ # Checks the scope in the given environment and returns the associated failure app.
4
+ class Delegator
5
+ def call(env)
6
+ failure_app(env).call(env)
7
+ end
8
+
9
+ def failure_app(env)
10
+ app = env["warden.options"] &&
11
+ (scope = env["warden.options"][:scope]) &&
12
+ Devise.mappings[scope.to_sym].failure_app
13
+
14
+ app || Devise::FailureApp
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,188 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require "action_controller/metal"
3
+
4
+ module Devise
5
+ # Failure application that will be called every time :warden is thrown from
6
+ # any strategy or hook. Responsible for redirect the user to the sign in
7
+ # page based on current scope and mapping. If no scope is given, redirect
8
+ # to the default_url.
9
+ class FailureApp < ActionController::Metal
10
+ include ActionController::RackDelegation
11
+ include ActionController::UrlFor
12
+ include ActionController::Redirecting
13
+
14
+ include Rails.application.routes.url_helpers
15
+ include Rails.application.routes.mounted_helpers
16
+
17
+ delegate :flash, :to => :request
18
+
19
+ def self.call(env)
20
+ @respond ||= action(:respond)
21
+ @respond.call(env)
22
+ end
23
+
24
+ def self.default_url_options(*args)
25
+ if defined?(ApplicationController)
26
+ ApplicationController.default_url_options(*args)
27
+ else
28
+ {}
29
+ end
30
+ end
31
+
32
+ def respond
33
+ if http_auth?
34
+ http_auth
35
+ elsif warden_options[:recall]
36
+ recall
37
+ else
38
+ redirect
39
+ end
40
+ end
41
+
42
+ def http_auth
43
+ self.status = 401
44
+ self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header?
45
+ self.content_type = request.format.to_s
46
+ self.response_body = http_auth_body
47
+ end
48
+
49
+ def recall
50
+ env["PATH_INFO"] = attempted_path
51
+ flash.now[:alert] = i18n_message(:invalid)
52
+ self.response = recall_app(warden_options[:recall]).call(env)
53
+ end
54
+
55
+ def redirect
56
+ store_location!
57
+ if flash[:timedout] && flash[:alert]
58
+ flash.keep(:timedout)
59
+ flash.keep(:alert)
60
+ else
61
+ flash[:alert] = i18n_message
62
+ end
63
+ redirect_to redirect_url
64
+ end
65
+
66
+ protected
67
+
68
+ def i18n_message(default = nil)
69
+ message = warden_message || default || :unauthenticated
70
+
71
+ if message.is_a?(Symbol)
72
+ I18n.t(:"#{scope}.#{message}", :resource_name => scope,
73
+ :scope => "devise.failure", :default => [message])
74
+ else
75
+ message.to_s
76
+ end
77
+ end
78
+
79
+ def redirect_url
80
+ if warden_message == :timeout
81
+ flash[:timedout] = true
82
+ attempted_path || scope_path
83
+ else
84
+ scope_path
85
+ end
86
+ end
87
+
88
+ def scope_path
89
+ opts = {}
90
+ route = :"new_#{scope}_session_path"
91
+ opts[:format] = request_format unless skip_format?
92
+
93
+ config = Rails.application.config
94
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
95
+
96
+ context = send(Devise.available_router_name)
97
+
98
+ if context.respond_to?(route)
99
+ context.send(route, opts)
100
+ elsif respond_to?(:root_path)
101
+ root_path(opts)
102
+ else
103
+ "/"
104
+ end
105
+ end
106
+
107
+ def skip_format?
108
+ %w(html */*).include? request_format.to_s
109
+ end
110
+
111
+ # Choose whether we should respond in a http authentication fashion,
112
+ # including 401 and optional headers.
113
+ #
114
+ # This method allows the user to explicitly disable http authentication
115
+ # on ajax requests in case they want to redirect on failures instead of
116
+ # handling the errors on their own. This is useful in case your ajax API
117
+ # is the same as your public API and uses a format like JSON (so you
118
+ # cannot mark JSON as a navigational format).
119
+ def http_auth?
120
+ if request.xhr?
121
+ Devise.http_authenticatable_on_xhr
122
+ else
123
+ !(request_format && is_navigational_format?)
124
+ end
125
+ end
126
+
127
+ # It does not make sense to send authenticate headers in ajax requests
128
+ # or if the user disabled them.
129
+ def http_auth_header?
130
+ Devise.mappings[scope].to.http_authenticatable && !request.xhr?
131
+ end
132
+
133
+ def http_auth_body
134
+ return i18n_message unless request_format
135
+ method = "to_#{request_format}"
136
+ if method == "to_xml"
137
+ { :error => i18n_message }.to_xml(:root => "errors")
138
+ elsif {}.respond_to?(method)
139
+ { :error => i18n_message }.send(method)
140
+ else
141
+ i18n_message
142
+ end
143
+ end
144
+
145
+ def recall_app(app)
146
+ controller, action = app.split("#")
147
+ controller_name = ActiveSupport::Inflector.camelize(controller)
148
+ controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
149
+ controller_klass.action(action)
150
+ end
151
+
152
+ def warden
153
+ env['warden']
154
+ end
155
+
156
+ def warden_options
157
+ env['warden.options']
158
+ end
159
+
160
+ def warden_message
161
+ @message ||= warden.message || warden_options[:message]
162
+ end
163
+
164
+ def scope
165
+ @scope ||= warden_options[:scope] || Devise.default_scope
166
+ end
167
+
168
+ def attempted_path
169
+ warden_options[:attempted_path]
170
+ end
171
+
172
+ # Stores requested uri to redirect the user after signing in. We cannot use
173
+ # scoped session provided by warden here, since the user is not authenticated
174
+ # yet, but we still need to store the uri based on scope, so different scopes
175
+ # would never use the same uri to redirect.
176
+ def store_location!
177
+ session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
178
+ end
179
+
180
+ def is_navigational_format?
181
+ Devise.navigational_formats.include?(request_format)
182
+ end
183
+
184
+ def request_format
185
+ @request_format ||= request.format.try(:ref)
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Deny user access whenever his account is not active yet. All strategies that inherits from
3
+ # Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
4
+ # before actively signing him in. However, we need this as hook to validate the user activity
5
+ # in each request and in case the user is using other strategies beside Devise ones.
6
+ Warden::Manager.after_set_user do |record, warden, options|
7
+ if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
8
+ scope = options[:scope]
9
+ warden.logout(scope)
10
+ throw :warden, :scope => scope, :message => record.inactive_message
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Before logout hook to forget the user in the given scope, if it responds
3
+ # to forget_me! Also clear remember token to ensure the user won't be
4
+ # remembered again. Notice that we forget the user unless the record is not persisted.
5
+ # This avoids forgetting deleted users.
6
+ Warden::Manager.before_logout do |record, warden, options|
7
+ if record.respond_to?(:forget_me!)
8
+ Devise::Controllers::Rememberable::Proxy.new(warden).forget_me(record)
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # After each sign in, if resource responds to failed_attempts, sets it to 0
3
+ # This is only triggered when the user is explicitly set (with set_user)
4
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
5
+ if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
6
+ record.update_attribute(:failed_attempts, 0)
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # -*- encoding : utf-8 -*-
2
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
3
+ scope = options[:scope]
4
+ if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
5
+ Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Each time a record is set we check whether its session has already timed out
3
+ # or not, based on last request time. If so, the record is logged out and
4
+ # redirected to the sign in page. Also, each time the request comes and the
5
+ # record is set, we set the last request time inside its scoped session to
6
+ # verify timeout in the following request.
7
+ Warden::Manager.after_set_user do |record, warden, options|
8
+ scope = options[:scope]
9
+ env = warden.request.env
10
+
11
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
12
+ last_request_at = warden.session(scope)['last_request_at']
13
+
14
+ if record.timedout?(last_request_at) && !env['devise.skip_timeout']
15
+ warden.logout(scope)
16
+ if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
17
+ record.reset_authentication_token!
18
+ end
19
+ throw :warden, :scope => scope, :message => :timeout
20
+ end
21
+
22
+ unless env['devise.skip_trackable']
23
+ warden.session(scope)['last_request_at'] = Time.now.utc
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # After each sign in, update sign in time, sign in count and sign in IP.
3
+ # This is only triggered when the user is explicitly set (with set_user)
4
+ # and on authentication. Retrieving the user from session (:fetch) does
5
+ # not trigger it.
6
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
7
+ if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
8
+ record.update_tracked_fields!(warden.request)
9
+ end
10
+ end
@@ -0,0 +1,92 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Devise
3
+ module Mailers
4
+ module Helpers
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Devise::Controllers::ScopedViews
9
+ attr_reader :scope_name, :resource
10
+ end
11
+
12
+ protected
13
+
14
+ # Configure default email options
15
+ def devise_mail(record, action)
16
+ initialize_from_record(record)
17
+ mail headers_for(action)
18
+ end
19
+
20
+ def initialize_from_record(record)
21
+ @scope_name = Devise::Mapping.find_scope!(record)
22
+ @resource = instance_variable_set("@#{devise_mapping.name}", record)
23
+ end
24
+
25
+ def devise_mapping
26
+ @devise_mapping ||= Devise.mappings[scope_name]
27
+ end
28
+
29
+ def headers_for(action)
30
+ headers = {
31
+ :subject => translate(devise_mapping, action),
32
+ :to => resource.email,
33
+ :from => mailer_sender(devise_mapping),
34
+ :reply_to => mailer_reply_to(devise_mapping),
35
+ :template_path => template_paths
36
+ }
37
+
38
+ if resource.respond_to?(:headers_for)
39
+ headers.merge!(resource.headers_for(action))
40
+ end
41
+
42
+ headers
43
+ end
44
+
45
+ def mailer_reply_to(mapping)
46
+ mailer_sender(mapping, :reply_to)
47
+ end
48
+
49
+ def mailer_from(mapping)
50
+ mailer_sender(mapping, :from)
51
+ end
52
+
53
+ def mailer_sender(mapping, sender = :from)
54
+ if default_params[sender].present?
55
+ default_params[sender]
56
+ elsif Devise.mailer_sender.is_a?(Proc)
57
+ Devise.mailer_sender.call(mapping.name)
58
+ else
59
+ Devise.mailer_sender
60
+ end
61
+ end
62
+
63
+ def template_paths
64
+ template_path = [self.class.mailer_name]
65
+ template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
66
+ template_path
67
+ end
68
+
69
+ # Setup a subject doing an I18n lookup. At first, it attemps to set a subject
70
+ # based on the current mapping:
71
+ #
72
+ # en:
73
+ # devise:
74
+ # mailer:
75
+ # confirmation_instructions:
76
+ # user_subject: '...'
77
+ #
78
+ # If one does not exist, it fallbacks to ActionMailer default:
79
+ #
80
+ # en:
81
+ # devise:
82
+ # mailer:
83
+ # confirmation_instructions:
84
+ # subject: '...'
85
+ #
86
+ def translate(mapping, key)
87
+ I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
88
+ :default => [:subject, key.to_s.humanize])
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,173 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Devise
3
+ # Responsible for handling devise mappings and routes configuration. Each
4
+ # resource configured by devise_for in routes is actually creating a mapping
5
+ # object. You can refer to devise_for in routes for usage options.
6
+ #
7
+ # The required value in devise_for is actually not used internally, but it's
8
+ # inflected to find all other values.
9
+ #
10
+ # map.devise_for :users
11
+ # mapping = Devise.mappings[:user]
12
+ #
13
+ # mapping.name #=> :user
14
+ # # is the scope used in controllers and warden, given in the route as :singular.
15
+ #
16
+ # mapping.as #=> "users"
17
+ # # how the mapping should be search in the path, given in the route as :as.
18
+ #
19
+ # mapping.to #=> User
20
+ # # is the class to be loaded from routes, given in the route as :class_name.
21
+ #
22
+ # mapping.modules #=> [:authenticatable]
23
+ # # is the modules included in the class
24
+ #
25
+ class Mapping #:nodoc:
26
+ attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
27
+ :class_name, :sign_out_via, :format, :used_routes, :used_helpers, :failure_app
28
+
29
+ alias :name :singular
30
+
31
+ # Receives an object and find a scope for it. If a scope cannot be found,
32
+ # raises an error. If a symbol is given, it's considered to be the scope.
33
+ def self.find_scope!(duck)
34
+ case duck
35
+ when String, Symbol
36
+ return duck
37
+ when Class
38
+ Devise.mappings.each_value { |m| return m.name if duck <= m.to }
39
+ else
40
+ Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) }
41
+ end
42
+
43
+ raise "Could not find a valid mapping for #{duck.inspect}"
44
+ end
45
+
46
+ def self.find_by_path!(path, path_type=:fullpath)
47
+ Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
48
+ raise "Could not find a valid mapping for path #{path.inspect}"
49
+ end
50
+
51
+ def initialize(name, options) #:nodoc:
52
+ @scoped_path = options[:as] ? "#{options[:as]}/#{name}" : name.to_s
53
+ @singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
54
+
55
+ @class_name = (options[:class_name] || name.to_s.classify).to_s
56
+ @klass = Devise.ref(@class_name)
57
+
58
+ @path = (options[:path] || name).to_s
59
+ @path_prefix = options[:path_prefix]
60
+
61
+ @sign_out_via = options[:sign_out_via] || Devise.sign_out_via
62
+ @format = options[:format]
63
+
64
+ default_failure_app(options)
65
+ default_controllers(options)
66
+ default_path_names(options)
67
+ default_used_route(options)
68
+ default_used_helpers(options)
69
+ end
70
+
71
+ # Return modules for the mapping.
72
+ def modules
73
+ @modules ||= to.respond_to?(:devise_modules) ? to.devise_modules : []
74
+ end
75
+
76
+ # Gives the class the mapping points to.
77
+ def to
78
+ @klass.get
79
+ end
80
+
81
+ def strategies
82
+ @strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
83
+ end
84
+
85
+ def no_input_strategies
86
+ self.strategies & Devise::NO_INPUT
87
+ end
88
+
89
+ def routes
90
+ @routes ||= ROUTES.values_at(*self.modules).compact.uniq
91
+ end
92
+
93
+ def authenticatable?
94
+ @authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
95
+ end
96
+
97
+ def fullpath
98
+ "/#{@path_prefix}/#{@path}".squeeze("/")
99
+ end
100
+
101
+ # Create magic predicates for verifying what module is activated by this map.
102
+ # Example:
103
+ #
104
+ # def confirmable?
105
+ # self.modules.include?(:confirmable)
106
+ # end
107
+ #
108
+ def self.add_module(m)
109
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
110
+ def #{m}?
111
+ self.modules.include?(:#{m})
112
+ end
113
+ METHOD
114
+ end
115
+
116
+ private
117
+
118
+ def default_failure_app(options)
119
+ @failure_app = options[:failure_app] || Devise::FailureApp
120
+ if @failure_app.is_a?(String)
121
+ ref = Devise.ref(@failure_app)
122
+ @failure_app = lambda { |env| ref.get.call(env) }
123
+ end
124
+ end
125
+
126
+ def default_controllers(options)
127
+ mod = options[:module] || "devise"
128
+ @controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
129
+ @controllers.merge!(options[:controllers]) if options[:controllers]
130
+ @controllers.each { |k,v| @controllers[k] = v.to_s }
131
+ end
132
+
133
+ def default_path_names(options)
134
+ @path_names = Hash.new { |h,k| h[k] = k.to_s }
135
+ @path_names[:registration] = ""
136
+ @path_names.merge!(options[:path_names]) if options[:path_names]
137
+ end
138
+
139
+ def default_constraints(options)
140
+ @constraints = Hash.new
141
+ @constraints.merge!(options[:constraints]) if options[:constraints]
142
+ end
143
+
144
+ def default_defaults(options)
145
+ @defaults = Hash.new
146
+ @defaults.merge!(options[:defaults]) if options[:defaults]
147
+ end
148
+
149
+ def default_used_route(options)
150
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
151
+
152
+ if options.has_key?(:only)
153
+ @used_routes = self.routes & Array(options[:only]).map(&singularizer)
154
+ elsif options[:skip] == :all
155
+ @used_routes = []
156
+ else
157
+ @used_routes = self.routes - Array(options[:skip]).map(&singularizer)
158
+ end
159
+ end
160
+
161
+ def default_used_helpers(options)
162
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
163
+
164
+ if options[:skip_helpers] == true
165
+ @used_helpers = @used_routes
166
+ elsif skip = options[:skip_helpers]
167
+ @used_helpers = self.routes - Array(skip).map(&singularizer)
168
+ else
169
+ @used_helpers = self.routes
170
+ end
171
+ end
172
+ end
173
+ end