devise-bootstrap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +31 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/app/controllers/devise/confirmations_controller.rb +47 -0
  8. data/app/controllers/devise/omniauth_callbacks_controller.rb +30 -0
  9. data/app/controllers/devise/passwords_controller.rb +70 -0
  10. data/app/controllers/devise/registrations_controller.rb +137 -0
  11. data/app/controllers/devise/sessions_controller.rb +53 -0
  12. data/app/controllers/devise/unlocks_controller.rb +46 -0
  13. data/app/controllers/devise_controller.rb +176 -0
  14. data/app/helpers/devise_helper.rb +25 -0
  15. data/app/mailers/devise/mailer.rb +20 -0
  16. data/app/views/devise/confirmations/new.html.erb +12 -0
  17. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  18. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  19. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  20. data/app/views/devise/passwords/edit.html.erb +16 -0
  21. data/app/views/devise/passwords/new.html.erb +12 -0
  22. data/app/views/devise/registrations/edit.html.erb +29 -0
  23. data/app/views/devise/registrations/new.html.erb +18 -0
  24. data/app/views/devise/sessions/new.html.erb +17 -0
  25. data/app/views/devise/shared/_links.erb +25 -0
  26. data/app/views/devise/unlocks/new.html.erb +12 -0
  27. data/config/locales/en.yml +59 -0
  28. data/devise-bootstrap.gemspec +30 -0
  29. data/gemfiles/Gemfile.rails-3.2-stable +29 -0
  30. data/gemfiles/Gemfile.rails-4.0-stable +29 -0
  31. data/gemfiles/Gemfile.rails-head +29 -0
  32. data/lib/devise/bootstrap.rb +7 -0
  33. data/lib/devise/bootstrap/version.rb +5 -0
  34. data/lib/devise/devise.rb +491 -0
  35. data/lib/devise/devise/controllers/helpers.rb +213 -0
  36. data/lib/devise/devise/controllers/rememberable.rb +47 -0
  37. data/lib/devise/devise/controllers/scoped_views.rb +17 -0
  38. data/lib/devise/devise/controllers/sign_in_out.rb +103 -0
  39. data/lib/devise/devise/controllers/store_location.rb +50 -0
  40. data/lib/devise/devise/controllers/url_helpers.rb +67 -0
  41. data/lib/devise/devise/delegator.rb +16 -0
  42. data/lib/devise/devise/failure_app.rb +205 -0
  43. data/lib/devise/devise/hooks/activatable.rb +11 -0
  44. data/lib/devise/devise/hooks/csrf_cleaner.rb +5 -0
  45. data/lib/devise/devise/hooks/forgetable.rb +9 -0
  46. data/lib/devise/devise/hooks/lockable.rb +7 -0
  47. data/lib/devise/devise/hooks/proxy.rb +21 -0
  48. data/lib/devise/devise/hooks/rememberable.rb +7 -0
  49. data/lib/devise/devise/hooks/timeoutable.rb +28 -0
  50. data/lib/devise/devise/hooks/trackable.rb +9 -0
  51. data/lib/devise/devise/mailers/helpers.rb +90 -0
  52. data/lib/devise/devise/mapping.rb +172 -0
  53. data/lib/devise/devise/models.rb +119 -0
  54. data/lib/devise/devise/models/authenticatable.rb +284 -0
  55. data/lib/devise/devise/models/confirmable.rb +295 -0
  56. data/lib/devise/devise/models/database_authenticatable.rb +164 -0
  57. data/lib/devise/devise/models/lockable.rb +196 -0
  58. data/lib/devise/devise/models/omniauthable.rb +27 -0
  59. data/lib/devise/devise/models/recoverable.rb +131 -0
  60. data/lib/devise/devise/models/registerable.rb +25 -0
  61. data/lib/devise/devise/models/rememberable.rb +129 -0
  62. data/lib/devise/devise/models/timeoutable.rb +49 -0
  63. data/lib/devise/devise/models/trackable.rb +35 -0
  64. data/lib/devise/devise/models/validatable.rb +66 -0
  65. data/lib/devise/devise/modules.rb +28 -0
  66. data/lib/devise/devise/omniauth.rb +28 -0
  67. data/lib/devise/devise/omniauth/config.rb +45 -0
  68. data/lib/devise/devise/omniauth/url_helpers.rb +18 -0
  69. data/lib/devise/devise/orm/active_record.rb +3 -0
  70. data/lib/devise/devise/orm/mongoid.rb +3 -0
  71. data/lib/devise/devise/parameter_filter.rb +40 -0
  72. data/lib/devise/devise/parameter_sanitizer.rb +99 -0
  73. data/lib/devise/devise/rails.rb +56 -0
  74. data/lib/devise/devise/rails/routes.rb +496 -0
  75. data/lib/devise/devise/rails/warden_compat.rb +22 -0
  76. data/lib/devise/devise/strategies/authenticatable.rb +167 -0
  77. data/lib/devise/devise/strategies/base.rb +20 -0
  78. data/lib/devise/devise/strategies/database_authenticatable.rb +23 -0
  79. data/lib/devise/devise/strategies/rememberable.rb +55 -0
  80. data/lib/devise/devise/test_helpers.rb +132 -0
  81. data/lib/devise/devise/time_inflector.rb +14 -0
  82. data/lib/devise/devise/token_generator.rb +70 -0
  83. data/lib/devise/devise/version.rb +3 -0
  84. data/lib/devise/generators/active_record/devise_generator.rb +73 -0
  85. data/lib/devise/generators/active_record/templates/migration.rb +18 -0
  86. data/lib/devise/generators/active_record/templates/migration_existing.rb +25 -0
  87. data/lib/devise/generators/devise/devise_generator.rb +26 -0
  88. data/lib/devise/generators/devise/install_generator.rb +29 -0
  89. data/lib/devise/generators/devise/orm_helpers.rb +51 -0
  90. data/lib/devise/generators/devise/views_generator.rb +135 -0
  91. data/lib/devise/generators/mongoid/devise_generator.rb +55 -0
  92. data/lib/devise/generators/templates/README +35 -0
  93. data/lib/devise/generators/templates/devise.rb +260 -0
  94. data/lib/devise/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  95. data/lib/devise/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  96. data/lib/devise/generators/templates/markerb/unlock_instructions.markerb +7 -0
  97. data/lib/devise/generators/templates/simple_form_for/confirmations/new.html.erb +16 -0
  98. data/lib/devise/generators/templates/simple_form_for/passwords/edit.html.erb +19 -0
  99. data/lib/devise/generators/templates/simple_form_for/passwords/new.html.erb +15 -0
  100. data/lib/devise/generators/templates/simple_form_for/registrations/edit.html.erb +27 -0
  101. data/lib/devise/generators/templates/simple_form_for/registrations/new.html.erb +17 -0
  102. data/lib/devise/generators/templates/simple_form_for/sessions/new.html.erb +15 -0
  103. data/lib/devise/generators/templates/simple_form_for/unlocks/new.html.erb +16 -0
  104. metadata +250 -0
@@ -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,205 @@
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
+ options = i18n_options(options)
82
+
83
+ I18n.t(:"#{scope}.#{message}", options)
84
+ else
85
+ message.to_s
86
+ end
87
+ end
88
+
89
+ def redirect_url
90
+ if warden_message == :timeout
91
+ flash[:timedout] = true
92
+
93
+ path = if request.get?
94
+ attempted_path
95
+ else
96
+ request.referrer
97
+ end
98
+
99
+ path || scope_path
100
+ else
101
+ scope_path
102
+ end
103
+ end
104
+
105
+ def scope_path
106
+ opts = {}
107
+ route = :"new_#{scope}_session_path"
108
+ opts[:format] = request_format unless skip_format?
109
+
110
+ config = Rails.application.config
111
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
112
+
113
+ context = send(Devise.available_router_name)
114
+
115
+ if context.respond_to?(route)
116
+ context.send(route, opts)
117
+ elsif respond_to?(:root_path)
118
+ root_path(opts)
119
+ else
120
+ "/"
121
+ end
122
+ end
123
+
124
+ def skip_format?
125
+ %w(html */*).include? request_format.to_s
126
+ end
127
+
128
+ # Choose whether we should respond in a http authentication fashion,
129
+ # including 401 and optional headers.
130
+ #
131
+ # This method allows the user to explicitly disable http authentication
132
+ # on ajax requests in case they want to redirect on failures instead of
133
+ # handling the errors on their own. This is useful in case your ajax API
134
+ # is the same as your public API and uses a format like JSON (so you
135
+ # cannot mark JSON as a navigational format).
136
+ def http_auth?
137
+ if request.xhr?
138
+ Devise.http_authenticatable_on_xhr
139
+ else
140
+ !(request_format && is_navigational_format?)
141
+ end
142
+ end
143
+
144
+ # It does not make sense to send authenticate headers in ajax requests
145
+ # or if the user disabled them.
146
+ def http_auth_header?
147
+ Devise.mappings[scope].to.http_authenticatable && !request.xhr?
148
+ end
149
+
150
+ def http_auth_body
151
+ return i18n_message unless request_format
152
+ method = "to_#{request_format}"
153
+ if method == "to_xml"
154
+ { error: i18n_message }.to_xml(root: "errors")
155
+ elsif {}.respond_to?(method)
156
+ { error: i18n_message }.send(method)
157
+ else
158
+ i18n_message
159
+ end
160
+ end
161
+
162
+ def recall_app(app)
163
+ controller, action = app.split("#")
164
+ controller_name = ActiveSupport::Inflector.camelize(controller)
165
+ controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
166
+ controller_klass.action(action)
167
+ end
168
+
169
+ def warden
170
+ env['warden']
171
+ end
172
+
173
+ def warden_options
174
+ env['warden.options']
175
+ end
176
+
177
+ def warden_message
178
+ @message ||= warden.message || warden_options[:message]
179
+ end
180
+
181
+ def scope
182
+ @scope ||= warden_options[:scope] || Devise.default_scope
183
+ end
184
+
185
+ def attempted_path
186
+ warden_options[:attempted_path]
187
+ end
188
+
189
+ # Stores requested uri to redirect the user after signing in. We cannot use
190
+ # scoped session provided by warden here, since the user is not authenticated
191
+ # yet, but we still need to store the uri based on scope, so different scopes
192
+ # would never use the same uri to redirect.
193
+ def store_location!
194
+ store_location_for(scope, attempted_path) if request.get? && !http_auth?
195
+ end
196
+
197
+ def is_navigational_format?
198
+ Devise.navigational_formats.include?(request_format)
199
+ end
200
+
201
+ def request_format
202
+ @request_format ||= request.format.try(:ref)
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,11 @@
1
+ # Deny user access whenever their account is not active yet. All strategies that inherits from
2
+ # Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
3
+ # before actively signing them in. However, we need this as hook to validate the user activity
4
+ # in each request and in case the user is using other strategies beside Devise ones.
5
+ Warden::Manager.after_set_user do |record, warden, options|
6
+ if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
7
+ scope = options[:scope]
8
+ warden.logout(scope)
9
+ throw :warden, scope: scope, message: record.inactive_message
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ Warden::Manager.after_authentication do |record, warden, options|
2
+ if Devise.clean_up_csrf_token_on_authentication
3
+ warden.request.session.try(:delete, :_csrf_token)
4
+ end
5
+ 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,28 @@
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
+ proxy = Devise::Hooks::Proxy.new(warden)
13
+
14
+ if record.timedout?(last_request_at) && !env['devise.skip_timeout']
15
+ Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
16
+
17
+ if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
18
+ record.reset_authentication_token!
19
+ end
20
+
21
+ throw :warden, scope: scope, message: :timeout
22
+ end
23
+
24
+ unless env['devise.skip_trackable']
25
+ warden.session(scope)['last_request_at'] = Time.now.utc
26
+ end
27
+ end
28
+ end
@@ -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,172 @@
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, :failure_app
27
+
28
+ alias :name :singular
29
+
30
+ # Receives an object and find a scope for it. If a scope cannot be found,
31
+ # raises an error. If a symbol is given, it's considered to be the scope.
32
+ def self.find_scope!(obj)
33
+ case obj
34
+ when String, Symbol
35
+ return obj
36
+ when Class
37
+ Devise.mappings.each_value { |m| return m.name if obj <= m.to }
38
+ else
39
+ Devise.mappings.each_value { |m| return m.name if obj.is_a?(m.to) }
40
+ end
41
+
42
+ raise "Could not find a valid mapping for #{obj.inspect}"
43
+ end
44
+
45
+ def self.find_by_path!(path, path_type=:fullpath)
46
+ Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
47
+ raise "Could not find a valid mapping for path #{path.inspect}"
48
+ end
49
+
50
+ def initialize(name, options) #:nodoc:
51
+ @scoped_path = options[:as] ? "#{options[:as]}/#{name}" : name.to_s
52
+ @singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
53
+
54
+ @class_name = (options[:class_name] || name.to_s.classify).to_s
55
+ @klass = Devise.ref(@class_name)
56
+
57
+ @path = (options[:path] || name).to_s
58
+ @path_prefix = options[:path_prefix]
59
+
60
+ @sign_out_via = options[:sign_out_via] || Devise.sign_out_via
61
+ @format = options[:format]
62
+
63
+ default_failure_app(options)
64
+ default_controllers(options)
65
+ default_path_names(options)
66
+ default_used_route(options)
67
+ default_used_helpers(options)
68
+ end
69
+
70
+ # Return modules for the mapping.
71
+ def modules
72
+ @modules ||= to.respond_to?(:devise_modules) ? to.devise_modules : []
73
+ end
74
+
75
+ # Gives the class the mapping points to.
76
+ def to
77
+ @klass.get
78
+ end
79
+
80
+ def strategies
81
+ @strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
82
+ end
83
+
84
+ def no_input_strategies
85
+ self.strategies & Devise::NO_INPUT
86
+ end
87
+
88
+ def routes
89
+ @routes ||= ROUTES.values_at(*self.modules).compact.uniq
90
+ end
91
+
92
+ def authenticatable?
93
+ @authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
94
+ end
95
+
96
+ def fullpath
97
+ "/#{@path_prefix}/#{@path}".squeeze("/")
98
+ end
99
+
100
+ # Create magic predicates for verifying what module is activated by this map.
101
+ # Example:
102
+ #
103
+ # def confirmable?
104
+ # self.modules.include?(:confirmable)
105
+ # end
106
+ #
107
+ def self.add_module(m)
108
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
109
+ def #{m}?
110
+ self.modules.include?(:#{m})
111
+ end
112
+ METHOD
113
+ end
114
+
115
+ private
116
+
117
+ def default_failure_app(options)
118
+ @failure_app = options[:failure_app] || Devise::FailureApp
119
+ if @failure_app.is_a?(String)
120
+ ref = Devise.ref(@failure_app)
121
+ @failure_app = lambda { |env| ref.get.call(env) }
122
+ end
123
+ end
124
+
125
+ def default_controllers(options)
126
+ mod = options[:module] || "devise"
127
+ @controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
128
+ @controllers.merge!(options[:controllers]) if options[:controllers]
129
+ @controllers.each { |k,v| @controllers[k] = v.to_s }
130
+ end
131
+
132
+ def default_path_names(options)
133
+ @path_names = Hash.new { |h,k| h[k] = k.to_s }
134
+ @path_names[:registration] = ""
135
+ @path_names.merge!(options[:path_names]) if options[:path_names]
136
+ end
137
+
138
+ def default_constraints(options)
139
+ @constraints = Hash.new
140
+ @constraints.merge!(options[:constraints]) if options[:constraints]
141
+ end
142
+
143
+ def default_defaults(options)
144
+ @defaults = Hash.new
145
+ @defaults.merge!(options[:defaults]) if options[:defaults]
146
+ end
147
+
148
+ def default_used_route(options)
149
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
150
+
151
+ if options.has_key?(:only)
152
+ @used_routes = self.routes & Array(options[:only]).map(&singularizer)
153
+ elsif options[:skip] == :all
154
+ @used_routes = []
155
+ else
156
+ @used_routes = self.routes - Array(options[:skip]).map(&singularizer)
157
+ end
158
+ end
159
+
160
+ def default_used_helpers(options)
161
+ singularizer = lambda { |s| s.to_s.singularize.to_sym }
162
+
163
+ if options[:skip_helpers] == true
164
+ @used_helpers = @used_routes
165
+ elsif skip = options[:skip_helpers]
166
+ @used_helpers = self.routes - Array(skip).map(&singularizer)
167
+ else
168
+ @used_helpers = self.routes
169
+ end
170
+ end
171
+ end
172
+ end