dcu-devise 1.0.7

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 (139) hide show
  1. data/CHANGELOG.rdoc +378 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +260 -0
  4. data/Rakefile +53 -0
  5. data/TODO +2 -0
  6. data/app/controllers/confirmations_controller.rb +33 -0
  7. data/app/controllers/passwords_controller.rb +41 -0
  8. data/app/controllers/registrations_controller.rb +53 -0
  9. data/app/controllers/sessions_controller.rb +44 -0
  10. data/app/controllers/unlocks_controller.rb +41 -0
  11. data/app/models/devise_mailer.rb +68 -0
  12. data/app/views/confirmations/new.html.erb +12 -0
  13. data/app/views/devise_mailer/confirmation_instructions.html.erb +5 -0
  14. data/app/views/devise_mailer/reset_password_instructions.html.erb +8 -0
  15. data/app/views/devise_mailer/unlock_instructions.html.erb +7 -0
  16. data/app/views/passwords/edit.html.erb +16 -0
  17. data/app/views/passwords/new.html.erb +12 -0
  18. data/app/views/registrations/edit.html.erb +25 -0
  19. data/app/views/registrations/new.html.erb +17 -0
  20. data/app/views/sessions/new.html.erb +17 -0
  21. data/app/views/shared/_devise_links.erb +19 -0
  22. data/app/views/unlocks/new.html.erb +12 -0
  23. data/generators/devise/USAGE +5 -0
  24. data/generators/devise/devise_generator.rb +15 -0
  25. data/generators/devise/lib/route_devise.rb +32 -0
  26. data/generators/devise/templates/migration.rb +23 -0
  27. data/generators/devise/templates/model.rb +9 -0
  28. data/generators/devise_install/USAGE +3 -0
  29. data/generators/devise_install/devise_install_generator.rb +15 -0
  30. data/generators/devise_install/templates/README +23 -0
  31. data/generators/devise_install/templates/devise.rb +105 -0
  32. data/generators/devise_views/USAGE +3 -0
  33. data/generators/devise_views/devise_views_generator.rb +21 -0
  34. data/lib/devise.rb +264 -0
  35. data/lib/devise/controllers/helpers.rb +200 -0
  36. data/lib/devise/controllers/internal_helpers.rb +129 -0
  37. data/lib/devise/controllers/url_helpers.rb +41 -0
  38. data/lib/devise/encryptors/authlogic_sha512.rb +21 -0
  39. data/lib/devise/encryptors/base.rb +20 -0
  40. data/lib/devise/encryptors/bcrypt.rb +21 -0
  41. data/lib/devise/encryptors/clearance_sha1.rb +19 -0
  42. data/lib/devise/encryptors/restful_authentication_sha1.rb +22 -0
  43. data/lib/devise/encryptors/sha1.rb +27 -0
  44. data/lib/devise/encryptors/sha512.rb +27 -0
  45. data/lib/devise/failure_app.rb +65 -0
  46. data/lib/devise/hooks/activatable.rb +15 -0
  47. data/lib/devise/hooks/rememberable.rb +32 -0
  48. data/lib/devise/hooks/timeoutable.rb +18 -0
  49. data/lib/devise/hooks/trackable.rb +18 -0
  50. data/lib/devise/locales/en.yml +35 -0
  51. data/lib/devise/mapping.rb +128 -0
  52. data/lib/devise/models.rb +117 -0
  53. data/lib/devise/models/activatable.rb +16 -0
  54. data/lib/devise/models/confirmable.rb +162 -0
  55. data/lib/devise/models/database_authenticatable.rb +144 -0
  56. data/lib/devise/models/http_authenticatable.rb +21 -0
  57. data/lib/devise/models/lockable.rb +150 -0
  58. data/lib/devise/models/recoverable.rb +80 -0
  59. data/lib/devise/models/registerable.rb +8 -0
  60. data/lib/devise/models/rememberable.rb +92 -0
  61. data/lib/devise/models/timeoutable.rb +28 -0
  62. data/lib/devise/models/token_authenticatable.rb +89 -0
  63. data/lib/devise/models/trackable.rb +16 -0
  64. data/lib/devise/models/validatable.rb +39 -0
  65. data/lib/devise/orm/active_record.rb +41 -0
  66. data/lib/devise/orm/data_mapper.rb +83 -0
  67. data/lib/devise/orm/mongo_mapper.rb +47 -0
  68. data/lib/devise/rails.rb +14 -0
  69. data/lib/devise/rails/routes.rb +125 -0
  70. data/lib/devise/rails/warden_compat.rb +25 -0
  71. data/lib/devise/schema.rb +73 -0
  72. data/lib/devise/strategies/base.rb +16 -0
  73. data/lib/devise/strategies/database_authenticatable.rb +36 -0
  74. data/lib/devise/strategies/http_authenticatable.rb +59 -0
  75. data/lib/devise/strategies/rememberable.rb +37 -0
  76. data/lib/devise/strategies/token_authenticatable.rb +37 -0
  77. data/lib/devise/test_helpers.rb +90 -0
  78. data/lib/devise/version.rb +3 -0
  79. data/rails/init.rb +2 -0
  80. data/test/controllers/helpers_test.rb +177 -0
  81. data/test/controllers/internal_helpers_test.rb +55 -0
  82. data/test/controllers/url_helpers_test.rb +47 -0
  83. data/test/devise_test.rb +74 -0
  84. data/test/encryptors_test.rb +31 -0
  85. data/test/failure_app_test.rb +44 -0
  86. data/test/integration/authenticatable_test.rb +271 -0
  87. data/test/integration/confirmable_test.rb +97 -0
  88. data/test/integration/http_authenticatable_test.rb +52 -0
  89. data/test/integration/lockable_test.rb +102 -0
  90. data/test/integration/rack_middleware_test.rb +47 -0
  91. data/test/integration/recoverable_test.rb +141 -0
  92. data/test/integration/registerable_test.rb +144 -0
  93. data/test/integration/rememberable_test.rb +71 -0
  94. data/test/integration/timeoutable_test.rb +68 -0
  95. data/test/integration/token_authenticatable_test.rb +55 -0
  96. data/test/integration/trackable_test.rb +64 -0
  97. data/test/mailers/confirmation_instructions_test.rb +86 -0
  98. data/test/mailers/reset_password_instructions_test.rb +68 -0
  99. data/test/mailers/unlock_instructions_test.rb +62 -0
  100. data/test/mapping_test.rb +148 -0
  101. data/test/models/authenticatable_test.rb +180 -0
  102. data/test/models/confirmable_test.rb +212 -0
  103. data/test/models/lockable_test.rb +202 -0
  104. data/test/models/recoverable_test.rb +138 -0
  105. data/test/models/rememberable_test.rb +135 -0
  106. data/test/models/timeoutable_test.rb +28 -0
  107. data/test/models/token_authenticatable_test.rb +51 -0
  108. data/test/models/trackable_test.rb +5 -0
  109. data/test/models/validatable_test.rb +106 -0
  110. data/test/models_test.rb +70 -0
  111. data/test/orm/active_record.rb +31 -0
  112. data/test/orm/mongo_mapper.rb +20 -0
  113. data/test/rails_app/app/active_record/admin.rb +7 -0
  114. data/test/rails_app/app/active_record/user.rb +7 -0
  115. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  116. data/test/rails_app/app/controllers/application_controller.rb +12 -0
  117. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  118. data/test/rails_app/app/controllers/users_controller.rb +16 -0
  119. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  120. data/test/rails_app/app/mongo_mapper/admin.rb +13 -0
  121. data/test/rails_app/app/mongo_mapper/user.rb +14 -0
  122. data/test/rails_app/config/boot.rb +110 -0
  123. data/test/rails_app/config/environment.rb +42 -0
  124. data/test/rails_app/config/environments/development.rb +17 -0
  125. data/test/rails_app/config/environments/production.rb +28 -0
  126. data/test/rails_app/config/environments/test.rb +28 -0
  127. data/test/rails_app/config/initializers/devise.rb +82 -0
  128. data/test/rails_app/config/initializers/inflections.rb +2 -0
  129. data/test/rails_app/config/initializers/new_rails_defaults.rb +24 -0
  130. data/test/rails_app/config/initializers/session_store.rb +15 -0
  131. data/test/rails_app/config/routes.rb +21 -0
  132. data/test/routes_test.rb +110 -0
  133. data/test/support/assertions_helper.rb +37 -0
  134. data/test/support/integration_tests_helper.rb +71 -0
  135. data/test/support/test_silencer.rb +5 -0
  136. data/test/support/tests_helper.rb +39 -0
  137. data/test/test_helper.rb +21 -0
  138. data/test/test_helpers_test.rb +57 -0
  139. metadata +213 -0
@@ -0,0 +1,22 @@
1
+ require "digest/sha1"
2
+
3
+ module Devise
4
+ module Encryptors
5
+ # = RestfulAuthenticationSha1
6
+ # Simulates Restful Authentication's default encryption mechanism.
7
+ # Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
8
+ # Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
9
+ # the initializer to silumate the default behavior.
10
+ class RestfulAuthenticationSha1 < Base
11
+
12
+ # Gererates a default password digest based on salt, pepper and the
13
+ # incoming password.
14
+ def self.digest(password, stretches, salt, pepper)
15
+ digest = pepper
16
+ stretches.times { digest = Digest::SHA1.hexdigest([digest, salt, password, pepper].flatten.join('--')) }
17
+ digest
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ require "digest/sha1"
2
+
3
+ module Devise
4
+ module Encryptors
5
+ # = Sha1
6
+ # Uses the Sha1 hash algorithm to encrypt passwords.
7
+ class Sha1 < Base
8
+
9
+ # Gererates a default password digest based on stretches, salt, pepper and the
10
+ # incoming password.
11
+ def self.digest(password, stretches, salt, pepper)
12
+ digest = pepper
13
+ stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
14
+ digest
15
+ end
16
+
17
+ private
18
+
19
+ # Generate a SHA1 digest joining args. Generated token is something like
20
+ # --arg1--arg2--arg3--argN--
21
+ def self.secure_digest(*tokens)
22
+ ::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--')
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require "digest/sha2"
2
+
3
+ module Devise
4
+ module Encryptors
5
+ # = Sha512
6
+ # Uses the Sha512 hash algorithm to encrypt passwords.
7
+ class Sha512 < Base
8
+
9
+ # Gererates a default password digest based on salt, pepper and the
10
+ # incoming password.
11
+ def self.digest(password, stretches, salt, pepper)
12
+ digest = pepper
13
+ stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
14
+ digest
15
+ end
16
+
17
+ private
18
+
19
+ # Generate a Sha512 digest joining args. Generated token is something like
20
+ # --arg1--arg2--arg3--argN--
21
+ def self.secure_digest(*tokens)
22
+ ::Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,65 @@
1
+ module Devise
2
+ # Failure application that will be called every time :warden is thrown from
3
+ # any strategy or hook. Responsible for redirect the user to the sign in
4
+ # page based on current scope and mapping. If no scope is given, redirect
5
+ # to the default_url.
6
+ class FailureApp
7
+ attr_reader :env
8
+ include Warden::Mixins::Common
9
+
10
+ cattr_accessor :default_url, :default_message, :instance_writer => false
11
+ @@default_message = :unauthenticated
12
+
13
+ def self.call(env)
14
+ new(env).respond!
15
+ end
16
+
17
+ def initialize(env)
18
+ @env = env
19
+ end
20
+
21
+ def respond!
22
+ options = @env['warden.options']
23
+ scope = options[:scope]
24
+
25
+ redirect_path = if mapping = Devise.mappings[scope]
26
+ "#{mapping.parsed_path}/#{mapping.path_names[:sign_in]}"
27
+ else
28
+ "/#{default_url}"
29
+ end
30
+ query_string = query_string_for(options)
31
+ store_location!(scope)
32
+
33
+ headers = {}
34
+ headers["Location"] = redirect_path
35
+ headers["Location"] << "?" << query_string unless query_string.empty?
36
+ headers["Content-Type"] = 'text/plain'
37
+
38
+ [302, headers, ["You are being redirected to #{redirect_path}"]]
39
+ end
40
+
41
+ # Build the proper query string based on the given message.
42
+ def query_string_for(options)
43
+ message = @env['warden'].try(:message) || options[:message] || default_message
44
+
45
+ params = case message
46
+ when Symbol
47
+ { message => true }
48
+ when String
49
+ { :message => message }
50
+ else
51
+ {}
52
+ end
53
+
54
+ Rack::Utils.build_query(params)
55
+ end
56
+
57
+ # Stores requested uri to redirect the user after signing in. We cannot use
58
+ # scoped session provided by warden here, since the user is not authenticated
59
+ # yet, but we still need to store the uri based on scope, so different scopes
60
+ # would never use the same uri to redirect.
61
+ def store_location!(scope)
62
+ session[:"#{scope}.return_to"] = request.request_uri if request && request.get?
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ # Deny user access whenever his account is not active yet.
2
+ Warden::Manager.after_set_user do |record, warden, options|
3
+ if record && record.respond_to?(:active?) && !record.active?
4
+ scope = options[:scope]
5
+ warden.logout(scope)
6
+
7
+ # If winning strategy was set, this is being called after authenticate and
8
+ # there is no need to force a redirect.
9
+ if warden.winning_strategy
10
+ warden.winning_strategy.fail!(record.inactive_message)
11
+ else
12
+ throw :warden, :scope => scope, :message => record.inactive_message
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ # After authenticate hook to verify if the user in the given scope asked to be
2
+ # remembered while he does not sign out. Generates a new remember token for
3
+ # that specific user and adds a cookie with this user info to sign in this user
4
+ # automatically without asking for credentials. Refer to rememberable strategy
5
+ # for more info.
6
+ Warden::Manager.prepend_after_authentication do |record, warden, options|
7
+ scope = options[:scope]
8
+ remember_me = warden.params[scope].try(:fetch, :remember_me, nil)
9
+
10
+ if Devise::TRUE_VALUES.include?(remember_me) &&
11
+ warden.authenticated?(scope) && record.respond_to?(:remember_me!)
12
+ record.remember_me!
13
+
14
+ warden.response.set_cookie "remember_#{scope}_token", {
15
+ :value => record.class.serialize_into_cookie(record),
16
+ :expires => record.remember_expires_at,
17
+ :path => "/"
18
+ }
19
+ end
20
+ end
21
+
22
+ # Before logout hook to forget the user in the given scope, only if rememberable
23
+ # is activated for this scope. Also clear remember token to ensure the user
24
+ # won't be remembered again.
25
+ # Notice that we forget the user if the record is frozen. This usually means the
26
+ # user was just deleted.
27
+ Warden::Manager.before_logout do |record, warden, scope|
28
+ if record.respond_to?(:forget_me!)
29
+ record.forget_me! unless record.frozen?
30
+ warden.response.delete_cookie "remember_#{scope}_token"
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ # Each time a record is set we check whether it's 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 it's 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
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope)
9
+ last_request_at = warden.session(scope)['last_request_at']
10
+
11
+ if record.timedout?(last_request_at)
12
+ warden.logout(scope)
13
+ throw :warden, :scope => scope, :message => :timeout
14
+ end
15
+
16
+ warden.session(scope)['last_request_at'] = Time.now.utc
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # After each sign in, update sign in time, sign in count and sign in IP.
2
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
3
+ scope = options[:scope]
4
+ if Devise.mappings[scope].try(:trackable?) && warden.authenticated?(scope)
5
+ old_current, new_current = record.current_sign_in_at, Time.now
6
+ record.last_sign_in_at = old_current || new_current
7
+ record.current_sign_in_at = new_current
8
+
9
+ old_current, new_current = record.current_sign_in_ip, warden.request.remote_ip
10
+ record.last_sign_in_ip = old_current || new_current
11
+ record.current_sign_in_ip = new_current
12
+
13
+ record.sign_in_count ||= 0
14
+ record.sign_in_count += 1
15
+
16
+ record.save(false)
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ link: 'Sign in'
5
+ signed_in: 'Signed in successfully.'
6
+ signed_out: 'Signed out successfully.'
7
+ unauthenticated: 'You need to sign in or sign up before continuing.'
8
+ unconfirmed: 'You have to confirm your account before continuing.'
9
+ locked: 'Your account is locked.'
10
+ invalid: 'Invalid email or password.'
11
+ invalid_token: 'Invalid authentication token.'
12
+ timeout: 'Your session expired, please sign in again to continue.'
13
+ inactive: 'Your account was not activated yet.'
14
+ passwords:
15
+ link: 'Forgot password?'
16
+ send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
17
+ updated: 'Your password was changed successfully. You are now signed in.'
18
+ confirmations:
19
+ link: "Didn't receive confirmation instructions?"
20
+ send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
21
+ confirmed: 'Your account was successfully confirmed. You are now signed in.'
22
+ registrations:
23
+ link: 'Sign up'
24
+ signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.'
25
+ updated: 'You updated your account successfully.'
26
+ destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
27
+ unlocks:
28
+ link: "Didn't receive unlock instructions?"
29
+ send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
30
+ unlocked: 'Your account was successfully unlocked. You are now signed in.'
31
+ mailer:
32
+ confirmation_instructions: 'Confirmation instructions'
33
+ reset_password_instructions: 'Reset password instructions'
34
+ unlock_instructions: 'Unlock Instructions'
35
+
@@ -0,0 +1,128 @@
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.for #=> [:authenticatable]
22
+ # # is the modules included in the class
23
+ #
24
+ class Mapping #:nodoc:
25
+ attr_reader :name, :as, :path_names, :path_prefix, :route_options
26
+
27
+ # Loop through all mappings looking for a map that matches with the requested
28
+ # path (ie /users/sign_in). If a path prefix is given, it's taken into account.
29
+ def self.find_by_path(path)
30
+ Devise.mappings.each_value do |mapping|
31
+ route = path.split("/")[mapping.as_position]
32
+ return mapping if route && mapping.as == route.to_sym
33
+ end
34
+ nil
35
+ end
36
+
37
+ # Receives an object and find a scope for it. If a scope cannot be found,
38
+ # raises an error. If a symbol is given, it's considered to be the scope.
39
+ def self.find_scope!(duck)
40
+ case duck
41
+ when String, Symbol
42
+ return duck
43
+ when Class
44
+ Devise.mappings.each_value { |m| return m.name if duck <= m.to }
45
+ else
46
+ Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) }
47
+ end
48
+
49
+ raise "Could not find a valid mapping for #{duck}"
50
+ end
51
+
52
+ # Default url options which can be used as prefix.
53
+ def self.default_url_options
54
+ {}
55
+ end
56
+
57
+ def initialize(name, options) #:nodoc:
58
+ @as = (options.delete(:as) || name).to_sym
59
+ @klass = (options.delete(:class_name) || name.to_s.classify).to_s
60
+ @name = (options.delete(:scope) || name.to_s.singularize).to_sym
61
+
62
+ @path_prefix = "/#{options.delete(:path_prefix)}/".squeeze("/")
63
+ @route_options = options || {}
64
+
65
+ @path_names = Hash.new { |h,k| h[k] = k.to_s }
66
+ @path_names.merge!(options.delete(:path_names) || {})
67
+ end
68
+
69
+ # Return modules for the mapping.
70
+ def for
71
+ @for ||= to.devise_modules
72
+ end
73
+
74
+ # Reload mapped class each time when cache_classes is false.
75
+ def to
76
+ return @to if @to
77
+ klass = @klass.constantize
78
+ @to = klass if Rails.configuration.cache_classes
79
+ klass
80
+ end
81
+
82
+ # Check if the respective controller has a module in the mapping class.
83
+ def allows?(controller)
84
+ (self.for & CONTROLLERS[controller.to_sym]).present?
85
+ end
86
+
87
+ # Return in which position in the path prefix devise should find the as mapping.
88
+ def as_position
89
+ self.path_prefix.count("/")
90
+ end
91
+
92
+ # Returns the raw path using path_prefix and as.
93
+ def raw_path
94
+ path_prefix + as.to_s
95
+ end
96
+
97
+ # Returns the parsed path taking into account the relative url root and raw path.
98
+ def parsed_path
99
+ returning (ActionController::Base.relative_url_root.to_s + raw_path) do |path|
100
+ self.class.default_url_options.each do |key, value|
101
+ path.gsub!(key.inspect, value.to_param)
102
+ end
103
+ end
104
+ end
105
+
106
+ def authenticatable?
107
+ @authenticatable ||= self.for.any? { |m| m.to_s =~ /authenticatable/ }
108
+ end
109
+
110
+ # Create magic predicates for verifying what module is activated by this map.
111
+ # Example:
112
+ #
113
+ # def confirmable?
114
+ # self.for.include?(:confirmable)
115
+ # end
116
+ #
117
+ def self.register(*modules)
118
+ modules.each do |m|
119
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
120
+ def #{m}?
121
+ self.for.include?(:#{m})
122
+ end
123
+ METHOD
124
+ end
125
+ end
126
+ Devise::Mapping.register *ALL
127
+ end
128
+ end
@@ -0,0 +1,117 @@
1
+ module Devise
2
+ module Models
3
+ autoload :Activatable, 'devise/models/activatable'
4
+ autoload :DatabaseAuthenticatable, 'devise/models/database_authenticatable'
5
+ autoload :Confirmable, 'devise/models/confirmable'
6
+ autoload :Lockable, 'devise/models/lockable'
7
+ autoload :Recoverable, 'devise/models/recoverable'
8
+ autoload :Rememberable, 'devise/models/rememberable'
9
+ autoload :Registerable, 'devise/models/registerable'
10
+ autoload :Timeoutable, 'devise/models/timeoutable'
11
+ autoload :Trackable, 'devise/models/trackable'
12
+ autoload :Validatable, 'devise/models/validatable'
13
+
14
+ # Creates configuration values for Devise and for the given module.
15
+ #
16
+ # Devise::Models.config(Devise::Authenticable, :stretches, 10)
17
+ #
18
+ # The line above creates:
19
+ #
20
+ # 1) An accessor called Devise.stretches, which value is used by default;
21
+ #
22
+ # 2) Some class methods for your model Model.stretches and Model.stretches=
23
+ # which have higher priority than Devise.stretches;
24
+ #
25
+ # 3) And an instance method stretches.
26
+ #
27
+ # To add the class methods you need to have a module ClassMethods defined
28
+ # inside the given class.
29
+ #
30
+ def self.config(mod, *accessors) #:nodoc:
31
+ accessors.each do |accessor|
32
+ mod.class_eval <<-METHOD, __FILE__, __LINE__ + 1
33
+ def #{accessor}
34
+ if defined?(@#{accessor})
35
+ @#{accessor}
36
+ elsif superclass.respond_to?(:#{accessor})
37
+ superclass.#{accessor}
38
+ else
39
+ Devise.#{accessor}
40
+ end
41
+ end
42
+
43
+ def #{accessor}=(value)
44
+ @#{accessor} = value
45
+ end
46
+ METHOD
47
+ end
48
+ end
49
+
50
+ # Include the chosen devise modules in your model:
51
+ #
52
+ # devise :authenticatable, :confirmable, :recoverable
53
+ #
54
+ # You can also give any of the devise configuration values in form of a hash,
55
+ # with specific values for this model. Please check your Devise initializer
56
+ # for a complete description on those values.
57
+ #
58
+ def devise(*modules)
59
+ raise "You need to give at least one Devise module" if modules.empty?
60
+ options = modules.extract_options!
61
+
62
+ if modules.delete(:authenticatable)
63
+ ActiveSupport::Deprecation.warn ":authenticatable as module is deprecated. Please give :database_authenticatable instead.", caller
64
+ modules << :database_authenticatable
65
+ end
66
+
67
+ @devise_modules = Devise::ALL & modules.map(&:to_sym).uniq
68
+
69
+ Devise.orm_class.included_modules_hook(self) do
70
+ devise_modules.each do |m|
71
+ include Devise::Models.const_get(m.to_s.classify)
72
+ end
73
+
74
+ options.each { |key, value| send(:"#{key}=", value) }
75
+ end
76
+ end
77
+
78
+ # Stores all modules included inside the model, so we are able to verify
79
+ # which routes are needed.
80
+ def devise_modules
81
+ @devise_modules ||= []
82
+ end
83
+
84
+ # Find an initialize a record setting an error if it can't be found.
85
+ def find_or_initialize_with_error_by(attribute, value, error=:invalid)
86
+ if value.present?
87
+ conditions = { attribute => value }
88
+ record = find(:first, :conditions => conditions)
89
+ end
90
+
91
+ unless record
92
+ record = new
93
+
94
+ if value.present?
95
+ record.send(:"#{attribute}=", value)
96
+ else
97
+ error, skip_default = :blank, true
98
+ end
99
+
100
+ add_error_on(record, attribute, error, !skip_default)
101
+ end
102
+
103
+ record
104
+ end
105
+
106
+ # Wraps add error logic in a method that works for different frameworks.
107
+ def add_error_on(record, attribute, error, add_default=true)
108
+ options = add_default ? { :default => error.to_s.gsub("_", " ") } : {}
109
+
110
+ begin
111
+ record.errors.add(attribute, error, options)
112
+ rescue ArgumentError
113
+ record.errors.add(attribute, error.to_s.gsub("_", " "))
114
+ end
115
+ end
116
+ end
117
+ end