loyal_devise 2.1.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.
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