deviseOne 1.0.0

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 (246) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +38 -0
  4. data/.yardopts +9 -0
  5. data/CHANGELOG.md +1117 -0
  6. data/CONTRIBUTING.md +14 -0
  7. data/Gemfile +29 -0
  8. data/Gemfile.lock +199 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +529 -0
  11. data/Rakefile +35 -0
  12. data/app/controllers/devise/confirmations_controller.rb +47 -0
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +30 -0
  14. data/app/controllers/devise/passwords_controller.rb +71 -0
  15. data/app/controllers/devise/registrations_controller.rb +143 -0
  16. data/app/controllers/devise/sessions_controller.rb +166 -0
  17. data/app/controllers/devise/unlocks_controller.rb +46 -0
  18. data/app/controllers/devise_controller.rb +193 -0
  19. data/app/helpers/devise_helper.rb +25 -0
  20. data/app/mailers/devise/mailer.rb +20 -0
  21. data/app/views/devise/confirmations/new.html.erb +16 -0
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  23. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  24. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  25. data/app/views/devise/passwords/edit.html.erb +25 -0
  26. data/app/views/devise/passwords/new.html.erb +16 -0
  27. data/app/views/devise/registrations/edit.html.erb +39 -0
  28. data/app/views/devise/registrations/new.html.erb +29 -0
  29. data/app/views/devise/sessions/new.html.erb +27 -0
  30. data/app/views/devise/shared/_links.html.erb +21 -0
  31. data/app/views/devise/unlocks/new.html.erb +16 -0
  32. data/config/locales/en.yml +70 -0
  33. data/devise.gemspec +33 -0
  34. data/devise.png +0 -0
  35. data/gemfiles/Gemfile.rails-3.2-stable +29 -0
  36. data/gemfiles/Gemfile.rails-3.2-stable.lock +169 -0
  37. data/gemfiles/Gemfile.rails-4.0-stable +29 -0
  38. data/gemfiles/Gemfile.rails-4.0-stable.lock +165 -0
  39. data/gemfiles/Gemfile.rails-4.1-stable +29 -0
  40. data/gemfiles/Gemfile.rails-4.1-stable.lock +170 -0
  41. data/lib/devise.rb +499 -0
  42. data/lib/devise/controllers/helpers.rb +284 -0
  43. data/lib/devise/controllers/rememberable.rb +47 -0
  44. data/lib/devise/controllers/scoped_views.rb +17 -0
  45. data/lib/devise/controllers/sign_in_out.rb +102 -0
  46. data/lib/devise/controllers/store_location.rb +58 -0
  47. data/lib/devise/controllers/url_helpers.rb +69 -0
  48. data/lib/devise/delegator.rb +16 -0
  49. data/lib/devise/failure_app.rb +212 -0
  50. data/lib/devise/hooks/activatable.rb +10 -0
  51. data/lib/devise/hooks/csrf_cleaner.rb +7 -0
  52. data/lib/devise/hooks/forgetable.rb +9 -0
  53. data/lib/devise/hooks/lockable.rb +7 -0
  54. data/lib/devise/hooks/proxy.rb +21 -0
  55. data/lib/devise/hooks/rememberable.rb +7 -0
  56. data/lib/devise/hooks/timeoutable.rb +35 -0
  57. data/lib/devise/hooks/trackable.rb +9 -0
  58. data/lib/devise/mailers/helpers.rb +90 -0
  59. data/lib/devise/mapping.rb +175 -0
  60. data/lib/devise/models.rb +119 -0
  61. data/lib/devise/models/authenticatable.rb +290 -0
  62. data/lib/devise/models/confirmable.rb +305 -0
  63. data/lib/devise/models/database_authenticatable.rb +164 -0
  64. data/lib/devise/models/lockable.rb +196 -0
  65. data/lib/devise/models/omniauthable.rb +27 -0
  66. data/lib/devise/models/recoverable.rb +157 -0
  67. data/lib/devise/models/registerable.rb +25 -0
  68. data/lib/devise/models/rememberable.rb +142 -0
  69. data/lib/devise/models/timeoutable.rb +49 -0
  70. data/lib/devise/models/trackable.rb +38 -0
  71. data/lib/devise/models/validatable.rb +66 -0
  72. data/lib/devise/modules.rb +28 -0
  73. data/lib/devise/omniauth.rb +28 -0
  74. data/lib/devise/omniauth/config.rb +45 -0
  75. data/lib/devise/omniauth/url_helpers.rb +18 -0
  76. data/lib/devise/orm/active_record.rb +3 -0
  77. data/lib/devise/orm/mongoid.rb +3 -0
  78. data/lib/devise/parameter_filter.rb +40 -0
  79. data/lib/devise/parameter_sanitizer.rb +99 -0
  80. data/lib/devise/rails.rb +56 -0
  81. data/lib/devise/rails/routes.rb +495 -0
  82. data/lib/devise/rails/warden_compat.rb +22 -0
  83. data/lib/devise/strategies/authenticatable.rb +173 -0
  84. data/lib/devise/strategies/base.rb +20 -0
  85. data/lib/devise/strategies/database_authenticatable.rb +24 -0
  86. data/lib/devise/strategies/rememberable.rb +59 -0
  87. data/lib/devise/test_helpers.rb +132 -0
  88. data/lib/devise/time_inflector.rb +14 -0
  89. data/lib/devise/token_generator.rb +70 -0
  90. data/lib/devise/version.rb +3 -0
  91. data/lib/generators/active_record/devise_generator.rb +91 -0
  92. data/lib/generators/active_record/templates/migration.rb +18 -0
  93. data/lib/generators/active_record/templates/migration_existing.rb +25 -0
  94. data/lib/generators/devise/controllers_generator.rb +44 -0
  95. data/lib/generators/devise/devise_generator.rb +26 -0
  96. data/lib/generators/devise/install_generator.rb +29 -0
  97. data/lib/generators/devise/orm_helpers.rb +51 -0
  98. data/lib/generators/devise/views_generator.rb +135 -0
  99. data/lib/generators/mongoid/devise_generator.rb +55 -0
  100. data/lib/generators/templates/README +35 -0
  101. data/lib/generators/templates/controllers/README +14 -0
  102. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  103. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  104. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  105. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  106. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  107. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  108. data/lib/generators/templates/devise.rb +263 -0
  109. data/lib/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  110. data/lib/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  111. data/lib/generators/templates/markerb/unlock_instructions.markerb +7 -0
  112. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +16 -0
  113. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +19 -0
  114. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +15 -0
  115. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +27 -0
  116. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +17 -0
  117. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +15 -0
  118. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +16 -0
  119. data/script/cached-bundle +49 -0
  120. data/script/s3-put +71 -0
  121. data/test/controllers/custom_registrations_controller_test.rb +35 -0
  122. data/test/controllers/custom_strategy_test.rb +62 -0
  123. data/test/controllers/helpers_test.rb +316 -0
  124. data/test/controllers/internal_helpers_test.rb +129 -0
  125. data/test/controllers/load_hooks_controller_test.rb +19 -0
  126. data/test/controllers/passwords_controller_test.rb +31 -0
  127. data/test/controllers/sessions_controller_test.rb +102 -0
  128. data/test/controllers/url_helpers_test.rb +65 -0
  129. data/test/delegator_test.rb +19 -0
  130. data/test/devise_test.rb +107 -0
  131. data/test/failure_app_test.rb +275 -0
  132. data/test/generators/active_record_generator_test.rb +109 -0
  133. data/test/generators/controllers_generator_test.rb +48 -0
  134. data/test/generators/devise_generator_test.rb +39 -0
  135. data/test/generators/install_generator_test.rb +13 -0
  136. data/test/generators/mongoid_generator_test.rb +23 -0
  137. data/test/generators/views_generator_test.rb +96 -0
  138. data/test/helpers/devise_helper_test.rb +49 -0
  139. data/test/integration/authenticatable_test.rb +731 -0
  140. data/test/integration/confirmable_test.rb +324 -0
  141. data/test/integration/database_authenticatable_test.rb +94 -0
  142. data/test/integration/http_authenticatable_test.rb +105 -0
  143. data/test/integration/lockable_test.rb +239 -0
  144. data/test/integration/omniauthable_test.rb +133 -0
  145. data/test/integration/recoverable_test.rb +334 -0
  146. data/test/integration/registerable_test.rb +361 -0
  147. data/test/integration/rememberable_test.rb +176 -0
  148. data/test/integration/timeoutable_test.rb +189 -0
  149. data/test/integration/trackable_test.rb +92 -0
  150. data/test/mailers/confirmation_instructions_test.rb +115 -0
  151. data/test/mailers/reset_password_instructions_test.rb +96 -0
  152. data/test/mailers/unlock_instructions_test.rb +91 -0
  153. data/test/mapping_test.rb +128 -0
  154. data/test/models/authenticatable_test.rb +23 -0
  155. data/test/models/confirmable_test.rb +461 -0
  156. data/test/models/database_authenticatable_test.rb +249 -0
  157. data/test/models/lockable_test.rb +328 -0
  158. data/test/models/omniauthable_test.rb +7 -0
  159. data/test/models/recoverable_test.rb +205 -0
  160. data/test/models/registerable_test.rb +7 -0
  161. data/test/models/rememberable_test.rb +198 -0
  162. data/test/models/serializable_test.rb +49 -0
  163. data/test/models/timeoutable_test.rb +51 -0
  164. data/test/models/trackable_test.rb +41 -0
  165. data/test/models/validatable_test.rb +127 -0
  166. data/test/models_test.rb +144 -0
  167. data/test/omniauth/config_test.rb +57 -0
  168. data/test/omniauth/url_helpers_test.rb +54 -0
  169. data/test/orm/active_record.rb +10 -0
  170. data/test/orm/mongoid.rb +13 -0
  171. data/test/parameter_sanitizer_test.rb +81 -0
  172. data/test/rails_app/Rakefile +6 -0
  173. data/test/rails_app/app/active_record/admin.rb +6 -0
  174. data/test/rails_app/app/active_record/shim.rb +2 -0
  175. data/test/rails_app/app/active_record/user.rb +6 -0
  176. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  177. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  178. data/test/rails_app/app/controllers/admins/sessions_controller.rb +6 -0
  179. data/test/rails_app/app/controllers/admins_controller.rb +11 -0
  180. data/test/rails_app/app/controllers/application_controller.rb +12 -0
  181. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  182. data/test/rails_app/app/controllers/custom/registrations_controller.rb +21 -0
  183. data/test/rails_app/app/controllers/home_controller.rb +25 -0
  184. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
  185. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
  186. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +14 -0
  187. data/test/rails_app/app/controllers/users_controller.rb +31 -0
  188. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  189. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  190. data/test/rails_app/app/mailers/users/mailer.rb +3 -0
  191. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  192. data/test/rails_app/app/mongoid/admin.rb +29 -0
  193. data/test/rails_app/app/mongoid/shim.rb +23 -0
  194. data/test/rails_app/app/mongoid/user.rb +39 -0
  195. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  196. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  197. data/test/rails_app/app/views/admins/index.html.erb +1 -0
  198. data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
  199. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -0
  200. data/test/rails_app/app/views/home/index.html.erb +1 -0
  201. data/test/rails_app/app/views/home/join.html.erb +1 -0
  202. data/test/rails_app/app/views/home/private.html.erb +1 -0
  203. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -0
  204. data/test/rails_app/app/views/layouts/application.html.erb +24 -0
  205. data/test/rails_app/app/views/users/edit_form.html.erb +1 -0
  206. data/test/rails_app/app/views/users/index.html.erb +1 -0
  207. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
  208. data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
  209. data/test/rails_app/bin/bundle +3 -0
  210. data/test/rails_app/bin/rails +4 -0
  211. data/test/rails_app/bin/rake +4 -0
  212. data/test/rails_app/config.ru +4 -0
  213. data/test/rails_app/config/application.rb +40 -0
  214. data/test/rails_app/config/boot.rb +14 -0
  215. data/test/rails_app/config/database.yml +18 -0
  216. data/test/rails_app/config/environment.rb +5 -0
  217. data/test/rails_app/config/environments/development.rb +30 -0
  218. data/test/rails_app/config/environments/production.rb +80 -0
  219. data/test/rails_app/config/environments/test.rb +36 -0
  220. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  221. data/test/rails_app/config/initializers/devise.rb +180 -0
  222. data/test/rails_app/config/initializers/inflections.rb +2 -0
  223. data/test/rails_app/config/initializers/secret_token.rb +8 -0
  224. data/test/rails_app/config/initializers/session_store.rb +1 -0
  225. data/test/rails_app/config/routes.rb +122 -0
  226. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +71 -0
  227. data/test/rails_app/db/schema.rb +55 -0
  228. data/test/rails_app/lib/shared_admin.rb +17 -0
  229. data/test/rails_app/lib/shared_user.rb +29 -0
  230. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  231. data/test/rails_app/public/404.html +26 -0
  232. data/test/rails_app/public/422.html +26 -0
  233. data/test/rails_app/public/500.html +26 -0
  234. data/test/rails_app/public/favicon.ico +0 -0
  235. data/test/routes_test.rb +264 -0
  236. data/test/support/action_controller/record_identifier.rb +10 -0
  237. data/test/support/assertions.rb +39 -0
  238. data/test/support/helpers.rb +73 -0
  239. data/test/support/integration.rb +92 -0
  240. data/test/support/locale/en.yml +8 -0
  241. data/test/support/mongoid.yml +6 -0
  242. data/test/support/webrat/integrations/rails.rb +24 -0
  243. data/test/test_helper.rb +34 -0
  244. data/test/test_helpers_test.rb +163 -0
  245. data/test/test_models.rb +33 -0
  246. metadata +531 -0
@@ -0,0 +1,58 @@
1
+ require "uri"
2
+
3
+ module Devise
4
+ module Controllers
5
+ # Provide the ability to store a location.
6
+ # Used to redirect back to a desired path after sign in.
7
+ # Included by default in all controllers.
8
+ module StoreLocation
9
+ # Returns and delete (if it's navigational format) the url stored in the session for
10
+ # the given scope. Useful for giving redirect backs after sign up:
11
+ #
12
+ # Example:
13
+ #
14
+ # redirect_to stored_location_for(:user) || root_path
15
+ #
16
+ def stored_location_for(resource_or_scope)
17
+ session_key = stored_location_key_for(resource_or_scope)
18
+
19
+ if is_navigational_format?
20
+ session.delete(session_key)
21
+ else
22
+ session[session_key]
23
+ end
24
+ end
25
+
26
+ # Stores the provided location to redirect the user after signing in.
27
+ # Useful in combination with the `stored_location_for` helper.
28
+ #
29
+ # Example:
30
+ #
31
+ # store_location_for(:user, dashboard_path)
32
+ # redirect_to user_omniauth_authorize_path(:facebook)
33
+ #
34
+ def store_location_for(resource_or_scope, location)
35
+ session_key = stored_location_key_for(resource_or_scope)
36
+ uri = parse_uri(location)
37
+ if uri
38
+ path = [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
39
+ path = [path, uri.fragment].compact.join('#')
40
+ session[session_key] = path
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def parse_uri(location)
47
+ location && URI.parse(location)
48
+ rescue URI::InvalidURIError
49
+ nil
50
+ end
51
+
52
+ def stored_location_key_for(resource_or_scope)
53
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
54
+ "#{scope}_return_to"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,69 @@
1
+ module Devise
2
+ module Controllers
3
+ # Create url helpers to be used with resource/scope configuration. Acts as
4
+ # proxies to the generated routes created by devise.
5
+ # Resource param can be a string or symbol, a class, or an instance object.
6
+ # Example using a :user resource:
7
+ #
8
+ # new_session_path(:user) => new_user_session_path
9
+ # session_path(:user) => user_session_path
10
+ # destroy_session_path(:user) => destroy_user_session_path
11
+ #
12
+ # new_password_path(:user) => new_user_password_path
13
+ # password_path(:user) => user_password_path
14
+ # edit_password_path(:user) => edit_user_password_path
15
+ #
16
+ # new_confirmation_path(:user) => new_user_confirmation_path
17
+ # confirmation_path(:user) => user_confirmation_path
18
+ #
19
+ # Those helpers are included by default to ActionController::Base.
20
+ #
21
+ # In case you want to add such helpers to another class, you can do
22
+ # that as long as this new class includes both url_helpers and
23
+ # mounted_helpers. Example:
24
+ #
25
+ # include Rails.application.routes.url_helpers
26
+ # include Rails.application.routes.mounted_helpers
27
+ #
28
+ module UrlHelpers
29
+ def self.remove_helpers!
30
+ self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
31
+ remove_method method
32
+ end
33
+ end
34
+
35
+ def self.generate_helpers!(routes=nil)
36
+ routes ||= begin
37
+ mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
38
+ Devise::URL_HELPERS.slice(*mappings)
39
+ end
40
+
41
+ routes.each do |module_name, actions|
42
+ [:path, :url].each do |path_or_url|
43
+ actions.each do |action|
44
+ action = action ? "#{action}_" : ""
45
+ method = "#{action}#{module_name}_#{path_or_url}"
46
+
47
+ class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
48
+ def #{method}(resource_or_scope, *args)
49
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
50
+ router_name = Devise.mappings[scope].router_name
51
+ context = router_name ? send(router_name) : _devise_route_context
52
+ context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
53
+ end
54
+ URL_HELPERS
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ generate_helpers!(Devise::URL_HELPERS)
61
+
62
+ private
63
+
64
+ def _devise_route_context
65
+ @_devise_route_context ||= send(Devise.available_router_name)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,16 @@
1
+ module Devise
2
+ # Checks the scope in the given environment and returns the associated failure app.
3
+ class Delegator
4
+ def call(env)
5
+ failure_app(env).call(env)
6
+ end
7
+
8
+ def failure_app(env)
9
+ app = env["warden.options"] &&
10
+ (scope = env["warden.options"][:scope]) &&
11
+ Devise.mappings[scope.to_sym].failure_app
12
+
13
+ app || Devise::FailureApp
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,212 @@
1
+ require "action_controller/metal"
2
+
3
+ module Devise
4
+ # Failure application that will be called every time :warden is thrown from
5
+ # any strategy or hook. Responsible for redirect the user to the sign in
6
+ # page based on current scope and mapping. If no scope is given, redirect
7
+ # to the default_url.
8
+ class FailureApp < ActionController::Metal
9
+ include ActionController::RackDelegation
10
+ include ActionController::UrlFor
11
+ include ActionController::Redirecting
12
+
13
+ include Rails.application.routes.url_helpers
14
+ include Rails.application.routes.mounted_helpers
15
+
16
+ include Devise::Controllers::StoreLocation
17
+
18
+ delegate :flash, to: :request
19
+
20
+ def self.call(env)
21
+ @respond ||= action(:respond)
22
+ @respond.call(env)
23
+ end
24
+
25
+ def self.default_url_options(*args)
26
+ if defined?(ApplicationController)
27
+ ApplicationController.default_url_options(*args)
28
+ else
29
+ {}
30
+ end
31
+ end
32
+
33
+ def respond
34
+ if http_auth?
35
+ http_auth
36
+ elsif warden_options[:recall]
37
+ recall
38
+ else
39
+ redirect
40
+ end
41
+ end
42
+
43
+ def http_auth
44
+ self.status = 401
45
+ self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header?
46
+ self.content_type = request.format.to_s
47
+ self.response_body = http_auth_body
48
+ end
49
+
50
+ def recall
51
+ env["PATH_INFO"] = attempted_path
52
+ flash.now[:alert] = i18n_message(:invalid)
53
+ self.response = recall_app(warden_options[:recall]).call(env)
54
+ end
55
+
56
+ def redirect
57
+ store_location!
58
+ if flash[:timedout] && flash[:alert]
59
+ flash.keep(:timedout)
60
+ flash.keep(:alert)
61
+ else
62
+ flash[:alert] = i18n_message
63
+ end
64
+ redirect_to redirect_url
65
+ end
66
+
67
+ protected
68
+
69
+ def i18n_options(options)
70
+ options
71
+ end
72
+
73
+ def i18n_message(default = nil)
74
+ message = warden_message || default || :unauthenticated
75
+
76
+ if message.is_a?(Symbol)
77
+ options = {}
78
+ options[:resource_name] = scope
79
+ options[:scope] = "devise.failure"
80
+ options[:default] = [message]
81
+ auth_keys = scope_class.authentication_keys
82
+ keys = auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
83
+ options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
84
+ options = i18n_options(options)
85
+
86
+ I18n.t(:"#{scope}.#{message}", options)
87
+ else
88
+ message.to_s
89
+ end
90
+ end
91
+
92
+ def redirect_url
93
+ if warden_message == :timeout
94
+ flash[:timedout] = true
95
+
96
+ path = if request.get?
97
+ attempted_path
98
+ else
99
+ request.referrer
100
+ end
101
+
102
+ path || scope_url
103
+ else
104
+ scope_url
105
+ end
106
+ end
107
+
108
+ def scope_url
109
+ opts = {}
110
+ route = :"new_#{scope}_session_url"
111
+ opts[:format] = request_format unless skip_format?
112
+
113
+ config = Rails.application.config
114
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
115
+
116
+ context = send(Devise.available_router_name)
117
+
118
+ if context.respond_to?(route)
119
+ context.send(route, opts)
120
+ elsif respond_to?(:root_url)
121
+ root_url(opts)
122
+ else
123
+ "/"
124
+ end
125
+ end
126
+
127
+ def skip_format?
128
+ %w(html */*).include? request_format.to_s
129
+ end
130
+
131
+ # Choose whether we should respond in a http authentication fashion,
132
+ # including 401 and optional headers.
133
+ #
134
+ # This method allows the user to explicitly disable http authentication
135
+ # on ajax requests in case they want to redirect on failures instead of
136
+ # handling the errors on their own. This is useful in case your ajax API
137
+ # is the same as your public API and uses a format like JSON (so you
138
+ # cannot mark JSON as a navigational format).
139
+ def http_auth?
140
+ if request.xhr?
141
+ Devise.http_authenticatable_on_xhr
142
+ else
143
+ !(request_format && is_navigational_format?)
144
+ end
145
+ end
146
+
147
+ # It does not make sense to send authenticate headers in ajax requests
148
+ # or if the user disabled them.
149
+ def http_auth_header?
150
+ scope_class.http_authenticatable && !request.xhr?
151
+ end
152
+
153
+ def http_auth_body
154
+ return i18n_message unless request_format
155
+ method = "to_#{request_format}"
156
+ if method == "to_xml"
157
+ { error: i18n_message }.to_xml(root: "errors")
158
+ elsif {}.respond_to?(method)
159
+ { error: i18n_message }.send(method)
160
+ else
161
+ i18n_message
162
+ end
163
+ end
164
+
165
+ def recall_app(app)
166
+ controller, action = app.split("#")
167
+ controller_name = ActiveSupport::Inflector.camelize(controller)
168
+ controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
169
+ controller_klass.action(action)
170
+ end
171
+
172
+ def warden
173
+ env['warden']
174
+ end
175
+
176
+ def warden_options
177
+ env['warden.options']
178
+ end
179
+
180
+ def warden_message
181
+ @message ||= warden.message || warden_options[:message]
182
+ end
183
+
184
+ def scope
185
+ @scope ||= warden_options[:scope] || Devise.default_scope
186
+ end
187
+
188
+ def scope_class
189
+ @scope_class ||= Devise.mappings[scope].to
190
+ end
191
+
192
+ def attempted_path
193
+ warden_options[:attempted_path]
194
+ end
195
+
196
+ # Stores requested uri to redirect the user after signing in. We cannot use
197
+ # scoped session provided by warden here, since the user is not authenticated
198
+ # yet, but we still need to store the uri based on scope, so different scopes
199
+ # would never use the same uri to redirect.
200
+ def store_location!
201
+ store_location_for(scope, attempted_path) if request.get? && !http_auth?
202
+ end
203
+
204
+ def is_navigational_format?
205
+ Devise.navigational_formats.include?(request_format)
206
+ end
207
+
208
+ def request_format
209
+ @request_format ||= request.format.try(:ref)
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,10 @@
1
+ # Deny user access whenever their account is not active yet.
2
+ # We need this as hook to validate the user activity on each request
3
+ # and in case the user is using other strategies beside Devise ones.
4
+ Warden::Manager.after_set_user do |record, warden, options|
5
+ if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
6
+ scope = options[:scope]
7
+ warden.logout(scope)
8
+ throw :warden, scope: scope, message: record.inactive_message
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ Warden::Manager.after_authentication do |record, warden, options|
2
+ clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
3
+ warden.winning_strategy.clean_up_csrf?
4
+ if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
5
+ warden.request.session.try(:delete, :_csrf_token)
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # Before logout hook to forget the user in the given scope, if it responds
2
+ # to forget_me! Also clear remember token to ensure the user won't be
3
+ # remembered again. Notice that we forget the user unless the record is not persisted.
4
+ # This avoids forgetting deleted users.
5
+ Warden::Manager.before_logout do |record, warden, options|
6
+ if record.respond_to?(:forget_me!)
7
+ Devise::Hooks::Proxy.new(warden).forget_me(record)
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # After each sign in, if resource responds to failed_attempts, sets it to 0
2
+ # This is only triggered when the user is explicitly set (with set_user)
3
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
4
+ if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
5
+ record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module Devise
2
+ module Hooks
3
+ # A small warden proxy so we can remember, forget and
4
+ # sign out users from hooks.
5
+ class Proxy #:nodoc:
6
+ include Devise::Controllers::Rememberable
7
+ include Devise::Controllers::SignInOut
8
+
9
+ attr_reader :warden
10
+ delegate :cookies, :env, to: :warden
11
+
12
+ def initialize(warden)
13
+ @warden = warden
14
+ end
15
+
16
+ def session
17
+ warden.request.session
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
2
+ scope = options[:scope]
3
+ if record.respond_to?(:remember_me) && options[:store] != false &&
4
+ record.remember_me && warden.authenticated?(scope)
5
+ Devise::Hooks::Proxy.new(warden).remember_me(record)
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ # Each time a record is set we check whether its session has already timed out
2
+ # or not, based on last request time. If so, the record is logged out and
3
+ # redirected to the sign in page. Also, each time the request comes and the
4
+ # record is set, we set the last request time inside its scoped session to
5
+ # verify timeout in the following request.
6
+ Warden::Manager.after_set_user do |record, warden, options|
7
+ scope = options[:scope]
8
+ env = warden.request.env
9
+
10
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
11
+ last_request_at = warden.session(scope)['last_request_at']
12
+
13
+ if last_request_at.is_a? Integer
14
+ last_request_at = Time.at(last_request_at).utc
15
+ elsif last_request_at.is_a? String
16
+ last_request_at = Time.parse(last_request_at)
17
+ end
18
+
19
+ proxy = Devise::Hooks::Proxy.new(warden)
20
+
21
+ if record.timedout?(last_request_at) && !env['devise.skip_timeout']
22
+ Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
23
+
24
+ if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
25
+ record.reset_authentication_token!
26
+ end
27
+
28
+ throw :warden, scope: scope, message: :timeout
29
+ end
30
+
31
+ unless env['devise.skip_trackable']
32
+ warden.session(scope)['last_request_at'] = Time.now.utc.to_i
33
+ end
34
+ end
35
+ end