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,9 @@
1
+ # After each sign in, update sign in time, sign in count and sign in IP.
2
+ # This is only triggered when the user is explicitly set (with set_user)
3
+ # and on authentication. Retrieving the user from session (:fetch) does
4
+ # not trigger it.
5
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
6
+ if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
7
+ record.update_tracked_fields!(warden.request)
8
+ end
9
+ end
@@ -0,0 +1,90 @@
1
+ module Devise
2
+ module Mailers
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Devise::Controllers::ScopedViews
8
+ attr_reader :scope_name, :resource
9
+ end
10
+
11
+ protected
12
+
13
+ # Configure default email options
14
+ def devise_mail(record, action, opts={})
15
+ initialize_from_record(record)
16
+ mail headers_for(action, opts)
17
+ end
18
+
19
+ def initialize_from_record(record)
20
+ @scope_name = Devise::Mapping.find_scope!(record)
21
+ @resource = instance_variable_set("@#{devise_mapping.name}", record)
22
+ end
23
+
24
+ def devise_mapping
25
+ @devise_mapping ||= Devise.mappings[scope_name]
26
+ end
27
+
28
+ def headers_for(action, opts)
29
+ headers = {
30
+ subject: subject_for(action),
31
+ to: resource.email,
32
+ from: mailer_sender(devise_mapping),
33
+ reply_to: mailer_reply_to(devise_mapping),
34
+ template_path: template_paths,
35
+ template_name: action
36
+ }.merge(opts)
37
+
38
+ @email = headers[:to]
39
+ headers
40
+ end
41
+
42
+ def mailer_reply_to(mapping)
43
+ mailer_sender(mapping, :reply_to)
44
+ end
45
+
46
+ def mailer_from(mapping)
47
+ mailer_sender(mapping, :from)
48
+ end
49
+
50
+ def mailer_sender(mapping, sender = :from)
51
+ default_sender = default_params[sender]
52
+ if default_sender.present?
53
+ default_sender.respond_to?(:to_proc) ? instance_eval(&default_sender) : default_sender
54
+ elsif Devise.mailer_sender.is_a?(Proc)
55
+ Devise.mailer_sender.call(mapping.name)
56
+ else
57
+ Devise.mailer_sender
58
+ end
59
+ end
60
+
61
+ def template_paths
62
+ template_path = _prefixes.dup
63
+ template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
64
+ template_path
65
+ end
66
+
67
+ # Setup a subject doing an I18n lookup. At first, it attempts to set a subject
68
+ # based on the current mapping:
69
+ #
70
+ # en:
71
+ # devise:
72
+ # mailer:
73
+ # confirmation_instructions:
74
+ # user_subject: '...'
75
+ #
76
+ # If one does not exist, it fallbacks to ActionMailer default:
77
+ #
78
+ # en:
79
+ # devise:
80
+ # mailer:
81
+ # confirmation_instructions:
82
+ # subject: '...'
83
+ #
84
+ def subject_for(key)
85
+ I18n.t(:"#{devise_mapping.name}_subject", scope: [:devise, :mailer, key],
86
+ default: [:subject, key.to_s.humanize])
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,175 @@
1
+ module Devise
2
+ # Responsible for handling devise mappings and routes configuration. Each
3
+ # resource configured by devise_for in routes is actually creating a mapping
4
+ # object. You can refer to devise_for in routes for usage options.
5
+ #
6
+ # The required value in devise_for is actually not used internally, but it's
7
+ # inflected to find all other values.
8
+ #
9
+ # map.devise_for :users
10
+ # mapping = Devise.mappings[:user]
11
+ #
12
+ # mapping.name #=> :user
13
+ # # is the scope used in controllers and warden, given in the route as :singular.
14
+ #
15
+ # mapping.as #=> "users"
16
+ # # how the mapping should be search in the path, given in the route as :as.
17
+ #
18
+ # mapping.to #=> User
19
+ # # is the class to be loaded from routes, given in the route as :class_name.
20
+ #
21
+ # mapping.modules #=> [:authenticatable]
22
+ # # is the modules included in the class
23
+ #
24
+ class Mapping #:nodoc:
25
+ attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
26
+ :class_name, :sign_out_via, :format, :used_routes, :used_helpers,
27
+ :failure_app, :router_name
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!(obj)
34
+ case obj
35
+ when String, Symbol
36
+ return obj.to_sym
37
+ when Class
38
+ Devise.mappings.each_value { |m| return m.name if obj <= m.to }
39
+ else
40
+ Devise.mappings.each_value { |m| return m.name if obj.is_a?(m.to) }
41
+ end
42
+
43
+ raise "Could not find a valid mapping for #{obj.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
+ @router_name = options[:router_name]
65
+
66
+ default_failure_app(options)
67
+ default_controllers(options)
68
+ default_path_names(options)
69
+ default_used_route(options)
70
+ default_used_helpers(options)
71
+ end
72
+
73
+ # Return modules for the mapping.
74
+ def modules
75
+ @modules ||= to.respond_to?(:devise_modules) ? to.devise_modules : []
76
+ end
77
+
78
+ # Gives the class the mapping points to.
79
+ def to
80
+ @klass.get
81
+ end
82
+
83
+ def strategies
84
+ @strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
85
+ end
86
+
87
+ def no_input_strategies
88
+ self.strategies & Devise::NO_INPUT
89
+ end
90
+
91
+ def routes
92
+ @routes ||= ROUTES.values_at(*self.modules).compact.uniq
93
+ end
94
+
95
+ def authenticatable?
96
+ @authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
97
+ end
98
+
99
+ def fullpath
100
+ "/#{@path_prefix}/#{@path}".squeeze("/")
101
+ end
102
+
103
+ # Create magic predicates for verifying what module is activated by this map.
104
+ # Example:
105
+ #
106
+ # def confirmable?
107
+ # self.modules.include?(:confirmable)
108
+ # end
109
+ #
110
+ def self.add_module(m)
111
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
112
+ def #{m}?
113
+ self.modules.include?(:#{m})
114
+ end
115
+ METHOD
116
+ end
117
+
118
+ private
119
+
120
+ def default_failure_app(options)
121
+ @failure_app = options[:failure_app] || Devise::FailureApp
122
+ if @failure_app.is_a?(String)
123
+ ref = Devise.ref(@failure_app)
124
+ @failure_app = lambda { |env| ref.get.call(env) }
125
+ end
126
+ end
127
+
128
+ def default_controllers(options)
129
+ mod = options[:module] || "devise"
130
+ @controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
131
+ @controllers.merge!(options[:controllers]) if options[:controllers]
132
+ @controllers.each { |k,v| @controllers[k] = v.to_s }
133
+ end
134
+
135
+ def default_path_names(options)
136
+ @path_names = Hash.new { |h,k| h[k] = k.to_s }
137
+ @path_names[:registration] = ""
138
+ @path_names.merge!(options[:path_names]) if options[:path_names]
139
+ end
140
+
141
+ def default_constraints(options)
142
+ @constraints = Hash.new
143
+ @constraints.merge!(options[:constraints]) if options[:constraints]
144
+ end
145
+
146
+ def default_defaults(options)
147
+ @defaults = Hash.new
148
+ @defaults.merge!(options[:defaults]) if options[:defaults]
149
+ end
150
+
151
+ def default_used_route(options)
152
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
153
+
154
+ if options.has_key?(:only)
155
+ @used_routes = self.routes & Array(options[:only]).map(&singularizer)
156
+ elsif options[:skip] == :all
157
+ @used_routes = []
158
+ else
159
+ @used_routes = self.routes - Array(options[:skip]).map(&singularizer)
160
+ end
161
+ end
162
+
163
+ def default_used_helpers(options)
164
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
165
+
166
+ if options[:skip_helpers] == true
167
+ @used_helpers = @used_routes
168
+ elsif skip = options[:skip_helpers]
169
+ @used_helpers = self.routes - Array(skip).map(&singularizer)
170
+ else
171
+ @used_helpers = self.routes
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,119 @@
1
+ module Devise
2
+ module Models
3
+ class MissingAttribute < StandardError
4
+ def initialize(attributes)
5
+ @attributes = attributes
6
+ end
7
+
8
+ def message
9
+ "The following attribute(s) is (are) missing on your model: #{@attributes.join(", ")}"
10
+ end
11
+ end
12
+
13
+ # Creates configuration values for Devise and for the given module.
14
+ #
15
+ # Devise::Models.config(Devise::Authenticatable, :stretches, 10)
16
+ #
17
+ # The line above creates:
18
+ #
19
+ # 1) An accessor called Devise.stretches, which value is used by default;
20
+ #
21
+ # 2) Some class methods for your model Model.stretches and Model.stretches=
22
+ # which have higher priority than Devise.stretches;
23
+ #
24
+ # 3) And an instance method stretches.
25
+ #
26
+ # To add the class methods you need to have a module ClassMethods defined
27
+ # inside the given class.
28
+ #
29
+ def self.config(mod, *accessors) #:nodoc:
30
+ class << mod; attr_accessor :available_configs; end
31
+ mod.available_configs = accessors
32
+
33
+ accessors.each do |accessor|
34
+ mod.class_eval <<-METHOD, __FILE__, __LINE__ + 1
35
+ def #{accessor}
36
+ if defined?(@#{accessor})
37
+ @#{accessor}
38
+ elsif superclass.respond_to?(:#{accessor})
39
+ superclass.#{accessor}
40
+ else
41
+ Devise.#{accessor}
42
+ end
43
+ end
44
+
45
+ def #{accessor}=(value)
46
+ @#{accessor} = value
47
+ end
48
+ METHOD
49
+ end
50
+ end
51
+
52
+ def self.check_fields!(klass)
53
+ failed_attributes = []
54
+ instance = klass.new
55
+
56
+ klass.devise_modules.each do |mod|
57
+ constant = const_get(mod.to_s.classify)
58
+
59
+ constant.required_fields(klass).each do |field|
60
+ failed_attributes << field unless instance.respond_to?(field)
61
+ end
62
+ end
63
+
64
+ if failed_attributes.any?
65
+ fail Devise::Models::MissingAttribute.new(failed_attributes)
66
+ end
67
+ end
68
+
69
+ # Include the chosen devise modules in your model:
70
+ #
71
+ # devise :database_authenticatable, :confirmable, :recoverable
72
+ #
73
+ # You can also give any of the devise configuration values in form of a hash,
74
+ # with specific values for this model. Please check your Devise initializer
75
+ # for a complete description on those values.
76
+ #
77
+ def devise(*modules)
78
+ options = modules.extract_options!.dup
79
+
80
+ selected_modules = modules.map(&:to_sym).uniq.sort_by do |s|
81
+ Devise::ALL.index(s) || -1 # follow Devise::ALL order
82
+ end
83
+
84
+ devise_modules_hook! do
85
+ include Devise::Models::Authenticatable
86
+
87
+ selected_modules.each do |m|
88
+ mod = Devise::Models.const_get(m.to_s.classify)
89
+
90
+ if mod.const_defined?("ClassMethods")
91
+ class_mod = mod.const_get("ClassMethods")
92
+ extend class_mod
93
+
94
+ if class_mod.respond_to?(:available_configs)
95
+ available_configs = class_mod.available_configs
96
+ available_configs.each do |config|
97
+ next unless options.key?(config)
98
+ send(:"#{config}=", options.delete(config))
99
+ end
100
+ end
101
+ end
102
+
103
+ include mod
104
+ end
105
+
106
+ self.devise_modules |= selected_modules
107
+ options.each { |key, value| send(:"#{key}=", value) }
108
+ end
109
+ end
110
+
111
+ # The hook which is called inside devise.
112
+ # So your ORM can include devise compatibility stuff.
113
+ def devise_modules_hook!
114
+ yield
115
+ end
116
+ end
117
+ end
118
+
119
+ require 'devise/models/authenticatable'
@@ -0,0 +1,290 @@
1
+ require 'devise/hooks/activatable'
2
+ require 'devise/hooks/csrf_cleaner'
3
+
4
+ module Devise
5
+ module Models
6
+ # Authenticatable module. Holds common settings for authentication.
7
+ #
8
+ # == Options
9
+ #
10
+ # Authenticatable adds the following options to devise_for:
11
+ #
12
+ # * +authentication_keys+: parameters used for authentication. By default [:email].
13
+ #
14
+ # * +http_authentication_key+: map the username passed via HTTP Auth to this parameter. Defaults to
15
+ # the first element in +authentication_keys+.
16
+ #
17
+ # * +request_keys+: parameters from the request object used for authentication.
18
+ # By specifying a symbol (which should be a request method), it will automatically be
19
+ # passed to find_for_authentication method and considered in your model lookup.
20
+ #
21
+ # For instance, if you set :request_keys to [:subdomain], :subdomain will be considered
22
+ # as key on authentication. This can also be a hash where the value is a boolean specifying
23
+ # if the value is required or not.
24
+ #
25
+ # * +http_authenticatable+: if this model allows http authentication. By default false.
26
+ # It also accepts an array specifying the strategies that should allow http.
27
+ #
28
+ # * +params_authenticatable+: if this model allows authentication through request params. By default true.
29
+ # It also accepts an array specifying the strategies that should allow params authentication.
30
+ #
31
+ # * +skip_session_storage+: By default Devise will store the user in session.
32
+ # By default is set to skip_session_storage: [:http_auth].
33
+ #
34
+ # == active_for_authentication?
35
+ #
36
+ # After authenticating a user and in each request, Devise checks if your model is active by
37
+ # calling model.active_for_authentication?. This method is overwritten by other devise modules. For instance,
38
+ # :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
39
+ #
40
+ # You can overwrite this method yourself, but if you do, don't forget to call super:
41
+ #
42
+ # def active_for_authentication?
43
+ # super && special_condition_is_valid?
44
+ # end
45
+ #
46
+ # Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using
47
+ # the inactive_message method. You can overwrite it as well:
48
+ #
49
+ # def inactive_message
50
+ # special_condition_is_valid? ? super : :special_condition_is_not_valid
51
+ # end
52
+ #
53
+ module Authenticatable
54
+ extend ActiveSupport::Concern
55
+
56
+ BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
57
+ :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
58
+ :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
59
+ :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]
60
+
61
+ included do
62
+ class_attribute :devise_modules, instance_writer: false
63
+ self.devise_modules ||= []
64
+
65
+ before_validation :downcase_keys
66
+ before_validation :strip_whitespace
67
+ end
68
+
69
+ def self.required_fields(klass)
70
+ []
71
+ end
72
+
73
+ # Check if the current object is valid for authentication. This method and
74
+ # find_for_authentication are the methods used in a Warden::Strategy to check
75
+ # if a model should be signed in or not.
76
+ #
77
+ # However, you should not overwrite this method, you should overwrite active_for_authentication?
78
+ # and inactive_message instead.
79
+ def valid_for_authentication?
80
+ block_given? ? yield : true
81
+ end
82
+
83
+ def unauthenticated_message
84
+ :invalid
85
+ end
86
+
87
+ def active_for_authentication?
88
+ true
89
+ end
90
+
91
+ def inactive_message
92
+ :inactive
93
+ end
94
+
95
+ def authenticatable_salt
96
+ end
97
+
98
+ array = %w(serializable_hash)
99
+ # to_xml does not call serializable_hash on 3.1
100
+ array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
101
+
102
+ array.each do |method|
103
+ class_eval <<-RUBY, __FILE__, __LINE__
104
+ # Redefine to_xml and serializable_hash in models for more secure defaults.
105
+ # By default, it removes from the serializable model all attributes that
106
+ # are *not* accessible. You can remove this default by using :force_except
107
+ # and passing a new list of attributes you want to exempt. All attributes
108
+ # given to :except will simply add names to exempt to Devise internal list.
109
+ def #{method}(options=nil)
110
+ options ||= {}
111
+ options[:except] = Array(options[:except])
112
+
113
+ if options[:force_except]
114
+ options[:except].concat Array(options[:force_except])
115
+ else
116
+ options[:except].concat BLACKLIST_FOR_SERIALIZATION
117
+ end
118
+ super(options)
119
+ end
120
+ RUBY
121
+ end
122
+
123
+ protected
124
+
125
+ def devise_mailer
126
+ Devise.mailer
127
+ end
128
+
129
+ # This is an internal method called every time Devise needs
130
+ # to send a notification/mail. This can be overridden if you
131
+ # need to customize the e-mail delivery logic. For instance,
132
+ # if you are using a queue to deliver e-mails (delayed job,
133
+ # sidekiq, resque, etc), you must add the delivery to the queue
134
+ # just after the transaction was committed. To achieve this,
135
+ # you can override send_devise_notification to store the
136
+ # deliveries until the after_commit callback is triggered:
137
+ #
138
+ # class User
139
+ # devise :database_authenticatable, :confirmable
140
+ #
141
+ # after_commit :send_pending_notifications
142
+ #
143
+ # protected
144
+ #
145
+ # def send_devise_notification(notification, *args)
146
+ # # If the record is new or changed then delay the
147
+ # # delivery until the after_commit callback otherwise
148
+ # # send now because after_commit will not be called.
149
+ # if new_record? || changed?
150
+ # pending_notifications << [notification, args]
151
+ # else
152
+ # devise_mailer.send(notification, self, *args).deliver
153
+ # end
154
+ # end
155
+ #
156
+ # def send_pending_notifications
157
+ # pending_notifications.each do |notification, args|
158
+ # devise_mailer.send(notification, self, *args).deliver
159
+ # end
160
+ #
161
+ # # Empty the pending notifications array because the
162
+ # # after_commit hook can be called multiple times which
163
+ # # could cause multiple emails to be sent.
164
+ # pending_notifications.clear
165
+ # end
166
+ #
167
+ # def pending_notifications
168
+ # @pending_notifications ||= []
169
+ # end
170
+ # end
171
+ #
172
+ def send_devise_notification(notification, *args)
173
+ message = devise_mailer.send(notification, self, *args)
174
+ # Remove once we move to Rails 4.2+ only.
175
+ if message.respond_to?(:deliver_now)
176
+ message.deliver_now
177
+ else
178
+ message.deliver
179
+ end
180
+ end
181
+
182
+ def downcase_keys
183
+ self.class.case_insensitive_keys.each { |k| apply_to_attribute_or_variable(k, :downcase) }
184
+ end
185
+
186
+ def strip_whitespace
187
+ self.class.strip_whitespace_keys.each { |k| apply_to_attribute_or_variable(k, :strip) }
188
+ end
189
+
190
+ def apply_to_attribute_or_variable(attr, method)
191
+ if self[attr]
192
+ self[attr] = self[attr].try(method)
193
+
194
+ # Use respond_to? here to avoid a regression where globally
195
+ # configured strip_whitespace_keys or case_insensitive_keys were
196
+ # attempting to strip or downcase when a model didn't have the
197
+ # globally configured key.
198
+ elsif respond_to?(attr) && respond_to?("#{attr}=")
199
+ new_value = send(attr).try(method)
200
+ send("#{attr}=", new_value)
201
+ end
202
+ end
203
+
204
+ module ClassMethods
205
+ Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys,
206
+ :case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage,
207
+ :http_authentication_key)
208
+
209
+ def serialize_into_session(record)
210
+ [record.to_key, record.authenticatable_salt]
211
+ end
212
+
213
+ def serialize_from_session(key, salt)
214
+ record = to_adapter.get(key)
215
+ record if record && record.authenticatable_salt == salt
216
+ end
217
+
218
+ def params_authenticatable?(strategy)
219
+ params_authenticatable.is_a?(Array) ?
220
+ params_authenticatable.include?(strategy) : params_authenticatable
221
+ end
222
+
223
+ def http_authenticatable?(strategy)
224
+ http_authenticatable.is_a?(Array) ?
225
+ http_authenticatable.include?(strategy) : http_authenticatable
226
+ end
227
+
228
+ # Find first record based on conditions given (ie by the sign in form).
229
+ # This method is always called during an authentication process but
230
+ # it may be wrapped as well. For instance, database authenticatable
231
+ # provides a `find_for_database_authentication` that wraps a call to
232
+ # this method. This allows you to customize both database authenticatable
233
+ # or the whole authenticate stack by customize `find_for_authentication.`
234
+ #
235
+ # Overwrite to add customized conditions, create a join, or maybe use a
236
+ # namedscope to filter records while authenticating.
237
+ # Example:
238
+ #
239
+ # def self.find_for_authentication(tainted_conditions)
240
+ # find_first_by_auth_conditions(tainted_conditions, active: true)
241
+ # end
242
+ #
243
+ # Finally, notice that Devise also queries for users in other scenarios
244
+ # besides authentication, for example when retrieving an user to send
245
+ # an e-mail for password reset. In such cases, find_for_authentication
246
+ # is not called.
247
+ def find_for_authentication(tainted_conditions)
248
+ find_first_by_auth_conditions(tainted_conditions)
249
+ end
250
+
251
+ def find_first_by_auth_conditions(tainted_conditions, opts={})
252
+ to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
253
+ end
254
+
255
+ # Find or initialize a record setting an error if it can't be found.
256
+ def find_or_initialize_with_error_by(attribute, value, error=:invalid) #:nodoc:
257
+ find_or_initialize_with_errors([attribute], { attribute => value }, error)
258
+ end
259
+
260
+ # Find or initialize a record with group of attributes based on a list of required attributes.
261
+ def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
262
+ attributes = attributes.slice(*required_attributes).with_indifferent_access
263
+ attributes.delete_if { |key, value| value.blank? }
264
+
265
+ if attributes.size == required_attributes.size
266
+ record = find_first_by_auth_conditions(attributes)
267
+ end
268
+
269
+ unless record
270
+ record = new
271
+
272
+ required_attributes.each do |key|
273
+ value = attributes[key]
274
+ record.send("#{key}=", value)
275
+ record.errors.add(key, value.present? ? error : :blank)
276
+ end
277
+ end
278
+
279
+ record
280
+ end
281
+
282
+ protected
283
+
284
+ def devise_parameter_filter
285
+ @devise_parameter_filter ||= Devise::ParameterFilter.new(case_insensitive_keys, strip_whitespace_keys)
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end