devise 1.0.11 → 1.1.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 (176) hide show
  1. data/CHANGELOG.rdoc +59 -13
  2. data/Gemfile +23 -0
  3. data/Gemfile.lock +118 -0
  4. data/README.rdoc +116 -77
  5. data/Rakefile +4 -2
  6. data/TODO +3 -2
  7. data/app/controllers/{confirmations_controller.rb → devise/confirmations_controller.rb} +1 -1
  8. data/app/controllers/{passwords_controller.rb → devise/passwords_controller.rb} +1 -1
  9. data/app/controllers/{registrations_controller.rb → devise/registrations_controller.rb} +12 -8
  10. data/app/controllers/devise/sessions_controller.rb +23 -0
  11. data/app/controllers/{unlocks_controller.rb → devise/unlocks_controller.rb} +1 -8
  12. data/app/helpers/devise_helper.rb +17 -0
  13. data/app/mailers/devise/mailer.rb +71 -0
  14. data/app/views/devise/confirmations/new.html.erb +12 -0
  15. data/app/views/devise/passwords/edit.html.erb +16 -0
  16. data/app/views/devise/passwords/new.html.erb +12 -0
  17. data/app/views/devise/registrations/edit.html.erb +25 -0
  18. data/app/views/devise/registrations/new.html.erb +18 -0
  19. data/app/views/devise/sessions/new.html.erb +17 -0
  20. data/app/views/devise/shared/_links.erb +19 -0
  21. data/app/views/devise/unlocks/new.html.erb +12 -0
  22. data/{lib/devise → config}/locales/en.yml +16 -12
  23. data/lib/devise/controllers/helpers.rb +57 -52
  24. data/lib/devise/controllers/internal_helpers.rb +19 -50
  25. data/lib/devise/controllers/scoped_views.rb +35 -0
  26. data/lib/devise/controllers/url_helpers.rb +1 -1
  27. data/lib/devise/encryptors/authlogic_sha512.rb +0 -2
  28. data/lib/devise/encryptors/base.rb +1 -1
  29. data/lib/devise/encryptors/bcrypt.rb +2 -4
  30. data/lib/devise/encryptors/clearance_sha1.rb +0 -2
  31. data/lib/devise/encryptors/sha1.rb +6 -8
  32. data/lib/devise/encryptors/sha512.rb +6 -8
  33. data/lib/devise/failure_app.rb +76 -41
  34. data/lib/devise/hooks/activatable.rb +6 -10
  35. data/lib/devise/hooks/forgetable.rb +11 -0
  36. data/lib/devise/hooks/rememberable.rb +40 -30
  37. data/lib/devise/hooks/timeoutable.rb +7 -3
  38. data/lib/devise/hooks/trackable.rb +5 -14
  39. data/lib/devise/mapping.rb +35 -62
  40. data/lib/devise/models/authenticatable.rb +126 -0
  41. data/lib/devise/models/confirmable.rb +19 -22
  42. data/lib/devise/models/database_authenticatable.rb +26 -60
  43. data/lib/devise/models/lockable.rb +43 -28
  44. data/lib/devise/models/recoverable.rb +11 -10
  45. data/lib/devise/models/rememberable.rb +56 -26
  46. data/lib/devise/models/timeoutable.rb +1 -3
  47. data/lib/devise/models/token_authenticatable.rb +14 -43
  48. data/lib/devise/models/trackable.rb +14 -0
  49. data/lib/devise/models/validatable.rb +16 -2
  50. data/lib/devise/models.rb +16 -53
  51. data/lib/devise/modules.rb +23 -0
  52. data/lib/devise/orm/active_record.rb +10 -15
  53. data/lib/devise/orm/mongoid.rb +29 -0
  54. data/lib/devise/path_checker.rb +18 -0
  55. data/lib/devise/rails/routes.rb +232 -117
  56. data/lib/devise/rails/warden_compat.rb +17 -41
  57. data/lib/devise/rails.rb +64 -9
  58. data/lib/devise/schema.rb +47 -23
  59. data/lib/devise/strategies/authenticatable.rb +123 -0
  60. data/lib/devise/strategies/base.rb +2 -3
  61. data/lib/devise/strategies/database_authenticatable.rb +7 -22
  62. data/lib/devise/strategies/rememberable.rb +21 -7
  63. data/lib/devise/strategies/token_authenticatable.rb +31 -19
  64. data/lib/devise/test_helpers.rb +6 -6
  65. data/lib/devise/version.rb +1 -1
  66. data/lib/devise.rb +174 -157
  67. data/lib/generators/active_record/devise_generator.rb +28 -0
  68. data/{generators/devise → lib/generators/active_record}/templates/migration.rb +9 -3
  69. data/lib/generators/devise/devise_generator.rb +17 -0
  70. data/lib/generators/devise/install_generator.rb +24 -0
  71. data/lib/generators/devise/orm_helpers.rb +23 -0
  72. data/{generators/devise_install → lib/generators/devise}/templates/README +9 -7
  73. data/lib/generators/devise/templates/devise.rb +142 -0
  74. data/lib/generators/devise/views_generator.rb +63 -0
  75. data/lib/generators/devise_install_generator.rb +4 -0
  76. data/lib/generators/devise_views_generator.rb +4 -0
  77. data/lib/generators/mongoid/devise_generator.rb +17 -0
  78. data/test/controllers/helpers_test.rb +48 -19
  79. data/test/controllers/internal_helpers_test.rb +12 -16
  80. data/test/controllers/url_helpers_test.rb +21 -10
  81. data/test/devise_test.rb +16 -25
  82. data/test/encryptors_test.rb +2 -3
  83. data/test/failure_app_test.rb +106 -27
  84. data/test/integration/authenticatable_test.rb +135 -131
  85. data/test/integration/confirmable_test.rb +22 -15
  86. data/test/integration/database_authenticatable_test.rb +38 -0
  87. data/test/integration/http_authenticatable_test.rb +9 -12
  88. data/test/integration/lockable_test.rb +22 -15
  89. data/test/integration/recoverable_test.rb +6 -6
  90. data/test/integration/registerable_test.rb +42 -33
  91. data/test/integration/rememberable_test.rb +84 -22
  92. data/test/integration/timeoutable_test.rb +16 -4
  93. data/test/integration/token_authenticatable_test.rb +45 -12
  94. data/test/integration/trackable_test.rb +1 -1
  95. data/test/mailers/confirmation_instructions_test.rb +11 -17
  96. data/test/mailers/reset_password_instructions_test.rb +7 -7
  97. data/test/mailers/unlock_instructions_test.rb +7 -7
  98. data/test/mapping_test.rb +22 -95
  99. data/test/models/confirmable_test.rb +12 -19
  100. data/test/models/{authenticatable_test.rb → database_authenticatable_test.rb} +24 -56
  101. data/test/models/lockable_test.rb +32 -46
  102. data/test/models/recoverable_test.rb +7 -7
  103. data/test/models/rememberable_test.rb +118 -35
  104. data/test/models/timeoutable_test.rb +1 -1
  105. data/test/models/token_authenticatable_test.rb +5 -19
  106. data/test/models/trackable_test.rb +1 -1
  107. data/test/models/validatable_test.rb +20 -27
  108. data/test/models_test.rb +12 -5
  109. data/test/orm/active_record.rb +1 -23
  110. data/test/orm/mongoid.rb +10 -0
  111. data/test/rails_app/app/active_record/admin.rb +1 -5
  112. data/test/rails_app/app/active_record/shim.rb +2 -0
  113. data/test/rails_app/app/active_record/user.rb +3 -3
  114. data/test/rails_app/app/controllers/application_controller.rb +2 -5
  115. data/test/rails_app/app/controllers/home_controller.rb +3 -0
  116. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
  117. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
  118. data/test/rails_app/app/controllers/sessions_controller.rb +6 -0
  119. data/test/rails_app/app/controllers/users_controller.rb +7 -5
  120. data/test/rails_app/app/mongoid/admin.rb +6 -0
  121. data/test/rails_app/app/mongoid/shim.rb +16 -0
  122. data/test/rails_app/app/mongoid/user.rb +10 -0
  123. data/test/rails_app/config/application.rb +35 -0
  124. data/test/rails_app/config/boot.rb +10 -107
  125. data/test/rails_app/config/environment.rb +4 -41
  126. data/test/rails_app/config/environments/development.rb +15 -13
  127. data/test/rails_app/config/environments/production.rb +25 -20
  128. data/test/rails_app/config/environments/test.rb +33 -28
  129. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  130. data/test/rails_app/config/initializers/devise.rb +95 -38
  131. data/test/rails_app/config/initializers/secret_token.rb +2 -0
  132. data/test/rails_app/config/routes.rb +47 -25
  133. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +27 -0
  134. data/test/rails_app/db/schema.rb +86 -0
  135. data/test/routes_test.rb +62 -47
  136. data/test/support/{assertions_helper.rb → assertions.rb} +2 -15
  137. data/test/support/{tests_helper.rb → helpers.rb} +18 -3
  138. data/test/support/{integration_tests_helper.rb → integration.rb} +24 -7
  139. data/test/support/webrat/integrations/rails.rb +32 -0
  140. data/test/test_helper.rb +11 -11
  141. data/test/test_helpers_test.rb +30 -15
  142. metadata +107 -66
  143. data/app/controllers/sessions_controller.rb +0 -42
  144. data/app/models/devise_mailer.rb +0 -68
  145. data/app/views/confirmations/new.html.erb +0 -12
  146. data/app/views/passwords/edit.html.erb +0 -16
  147. data/app/views/passwords/new.html.erb +0 -12
  148. data/app/views/registrations/edit.html.erb +0 -25
  149. data/app/views/registrations/new.html.erb +0 -17
  150. data/app/views/sessions/new.html.erb +0 -17
  151. data/app/views/shared/_devise_links.erb +0 -19
  152. data/app/views/unlocks/new.html.erb +0 -12
  153. data/generators/devise/USAGE +0 -5
  154. data/generators/devise/devise_generator.rb +0 -15
  155. data/generators/devise/lib/route_devise.rb +0 -32
  156. data/generators/devise/templates/model.rb +0 -9
  157. data/generators/devise_install/USAGE +0 -3
  158. data/generators/devise_install/devise_install_generator.rb +0 -15
  159. data/generators/devise_install/templates/devise.rb +0 -105
  160. data/generators/devise_views/USAGE +0 -3
  161. data/generators/devise_views/devise_views_generator.rb +0 -21
  162. data/lib/devise/models/activatable.rb +0 -16
  163. data/lib/devise/models/http_authenticatable.rb +0 -23
  164. data/lib/devise/orm/data_mapper.rb +0 -83
  165. data/lib/devise/orm/mongo_mapper.rb +0 -52
  166. data/lib/devise/strategies/http_authenticatable.rb +0 -59
  167. data/rails/init.rb +0 -2
  168. data/test/integration/rack_middleware_test.rb +0 -47
  169. data/test/orm/mongo_mapper.rb +0 -20
  170. data/test/rails_app/app/mongo_mapper/admin.rb +0 -13
  171. data/test/rails_app/app/mongo_mapper/user.rb +0 -14
  172. data/test/rails_app/config/initializers/new_rails_defaults.rb +0 -24
  173. data/test/rails_app/config/initializers/session_store.rb +0 -15
  174. /data/app/views/{devise_mailer → devise/mailer}/confirmation_instructions.html.erb +0 -0
  175. /data/app/views/{devise_mailer → devise/mailer}/reset_password_instructions.html.erb +0 -0
  176. /data/app/views/{devise_mailer → devise/mailer}/unlock_instructions.html.erb +0 -0
@@ -14,11 +14,7 @@ module Devise
14
14
  # # creates a new token and send it with instructions about how to reset the password
15
15
  # User.find(1).send_reset_password_instructions
16
16
  module Recoverable
17
- def self.included(base)
18
- base.class_eval do
19
- extend ClassMethods
20
- end
21
- end
17
+ extend ActiveSupport::Concern
22
18
 
23
19
  # Update password saving the record and clearing token. Returns true if
24
20
  # the passwords are valid and the record was saved, false otherwise.
@@ -32,20 +28,20 @@ module Devise
32
28
  # Resets reset password token and send reset password instructions by email
33
29
  def send_reset_password_instructions
34
30
  generate_reset_password_token!
35
- ::DeviseMailer.deliver_reset_password_instructions(self)
31
+ ::Devise.mailer.reset_password_instructions(self).deliver
36
32
  end
37
33
 
38
34
  protected
39
35
 
40
36
  # Generates a new random token for reset password
41
37
  def generate_reset_password_token
42
- self.reset_password_token = Devise.friendly_token
38
+ self.reset_password_token = self.class.reset_password_token
43
39
  end
44
40
 
45
41
  # Resets the reset password token with and save the record without
46
42
  # validating
47
43
  def generate_reset_password_token!
48
- generate_reset_password_token && save(false)
44
+ generate_reset_password_token && save(:validate => false)
49
45
  end
50
46
 
51
47
  # Removes reset_password token
@@ -60,10 +56,15 @@ module Devise
60
56
  # Attributes must contain the user email
61
57
  def send_reset_password_instructions(attributes={})
62
58
  recoverable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
63
- recoverable.send_reset_password_instructions unless recoverable.new_record?
59
+ recoverable.send_reset_password_instructions if recoverable.persisted?
64
60
  recoverable
65
61
  end
66
62
 
63
+ # Generate a token checking if one does not already exist in the database.
64
+ def reset_password_token
65
+ generate_token(:reset_password_token)
66
+ end
67
+
67
68
  # Attempt to find a user by it's reset_password_token to reset it's
68
69
  # password. If a user is found, reset it's password and automatically
69
70
  # try saving the record. If not user is found, returns a new user
@@ -71,7 +72,7 @@ module Devise
71
72
  # Attributes must contain reset_password_token, password and confirmation
72
73
  def reset_password_by_token(attributes={})
73
74
  recoverable = find_or_initialize_with_error_by(:reset_password_token, attributes[:reset_password_token])
74
- recoverable.reset_password!(attributes[:password], attributes[:password_confirmation]) unless recoverable.new_record?
75
+ recoverable.reset_password!(attributes[:password], attributes[:password_confirmation]) if recoverable.persisted?
75
76
  recoverable
76
77
  end
77
78
  end
@@ -1,5 +1,6 @@
1
1
  require 'devise/strategies/rememberable'
2
2
  require 'devise/hooks/rememberable'
3
+ require 'devise/hooks/forgetable'
3
4
 
4
5
  module Devise
5
6
  module Models
@@ -17,7 +18,15 @@ module Devise
17
18
  # blocked and will have to enter his credentials again.
18
19
  # This configuration is also used to calculate the expires
19
20
  # time for the cookie created to remember the user.
20
- # By default remember_for is 2.weeks.
21
+ # 2.weeks by default.
22
+ #
23
+ # remember_across_browsers: if true, a valid remember token can be
24
+ # re-used between multiple browsers.
25
+ # True by default.
26
+ #
27
+ # extend_remember_period: if true, extends the user's remember period
28
+ # when remembered via cookie.
29
+ # False by default.
21
30
  #
22
31
  # Examples:
23
32
  #
@@ -30,21 +39,19 @@ module Devise
30
39
  # # lookup the user based on the incoming cookie information
31
40
  # User.serialize_from_cookie(cookie_string)
32
41
  module Rememberable
42
+ extend ActiveSupport::Concern
33
43
 
34
- def self.included(base)
35
- base.class_eval do
36
- extend ClassMethods
37
-
38
- # Remember me option available in after_authentication hook.
39
- attr_accessor :remember_me
40
- end
44
+ included do
45
+ # Remember me option available in after_authentication hook.
46
+ attr_accessor :remember_me
41
47
  end
42
48
 
43
- # Generate a new remember token and save the record without validations.
44
- def remember_me!
45
- self.remember_token = Devise.friendly_token
46
- self.remember_created_at = Time.now.utc
47
- save(false)
49
+ # Generate a new remember token and save the record without validations
50
+ # unless remember_across_browsers is true and the user already has a valid token.
51
+ def remember_me!(extend_period=false)
52
+ self.remember_token = self.class.remember_token if generate_remember_token?
53
+ self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period)
54
+ save(:validate => false)
48
55
  end
49
56
 
50
57
  # Removes the remember token only if it exists, and save the record
@@ -53,18 +60,13 @@ module Devise
53
60
  if remember_token
54
61
  self.remember_token = nil
55
62
  self.remember_created_at = nil
56
- save(false)
63
+ save(:validate => false)
57
64
  end
58
65
  end
59
66
 
60
- # Checks whether the incoming token matches or not with the record token.
61
- def valid_remember_token?(token)
62
- remember_token && !remember_expired? && remember_token == token
63
- end
64
-
65
67
  # Remember token should be expired if expiration time not overpass now.
66
68
  def remember_expired?
67
- remember_expires_at <= Time.now.utc
69
+ remember_created_at && (remember_expires_at <= Time.now.utc)
68
70
  end
69
71
 
70
72
  # Remember token expires at created time + remember_for configuration
@@ -72,20 +74,48 @@ module Devise
72
74
  remember_created_at + self.class.remember_for
73
75
  end
74
76
 
77
+ def cookie_domain
78
+ self.class.cookie_domain
79
+ end
80
+
81
+ def cookie_domain?
82
+ self.class.cookie_domain != false
83
+ end
84
+
85
+ protected
86
+
87
+ # Generate a token unless remember_across_browsers is true and there is
88
+ # an existing remember_token or the existing remember_token has expried.
89
+ def generate_remember_token? #:nodoc:
90
+ !(self.class.remember_across_browsers && remember_token) || remember_expired?
91
+ end
92
+
93
+ # Generate a timestamp if extend_remember_period is true, if no remember_token
94
+ # exists, or if an existing remember token has expired.
95
+ def generate_remember_timestamp?(extend_period) #:nodoc:
96
+ extend_period || remember_created_at.nil? || remember_expired?
97
+ end
98
+
75
99
  module ClassMethods
76
100
  # Create the cookie key using the record id and remember_token
77
101
  def serialize_into_cookie(record)
78
- "#{record.id}::#{record.remember_token}"
102
+ [record.id, record.remember_token]
79
103
  end
80
104
 
81
105
  # Recreate the user based on the stored cookie
82
- def serialize_from_cookie(cookie)
83
- record_id, record_token = cookie.split('::')
84
- record = find(:first, :conditions => { :id => record_id }) if record_id
85
- record if record.try(:valid_remember_token?, record_token)
106
+ def serialize_from_cookie(id, remember_token)
107
+ conditions = { :id => id, :remember_token => remember_token }
108
+ record = find(:first, :conditions => conditions)
109
+ record if record && !record.remember_expired?
110
+ end
111
+
112
+ # Generate a token checking if one does not already exist in the database.
113
+ def remember_token
114
+ generate_token(:remember_token)
86
115
  end
87
116
 
88
- Devise::Models.config(self, :remember_for)
117
+ Devise::Models.config(self, :remember_for, :remember_across_browsers,
118
+ :extend_remember_period, :cookie_domain)
89
119
  end
90
120
  end
91
121
  end
@@ -11,9 +11,7 @@ module Devise
11
11
  #
12
12
  # timeout_in: the time you want to timeout the user session without activity.
13
13
  module Timeoutable
14
- def self.included(base)
15
- base.extend ClassMethods
16
- end
14
+ extend ActiveSupport::Concern
17
15
 
18
16
  # Checks whether the user session has expired based on configured time.
19
17
  def timedout?(last_access)
@@ -2,8 +2,11 @@ require 'devise/strategies/token_authenticatable'
2
2
 
3
3
  module Devise
4
4
  module Models
5
- # Token Authenticatable Module, responsible for generate authentication token and validating
6
- # authenticity of a user while signing in using an authentication token (say follows an URL).
5
+ # The TokenAuthenticatable module is responsible for generating an authentication token and
6
+ # validating the authenticity of the same while signing in.
7
+ #
8
+ # This module only provides a few helpers to help you manage the token. Creating and resetting
9
+ # the token is your responsibility.
7
10
  #
8
11
  # == Configuration:
9
12
  #
@@ -12,18 +15,8 @@ module Devise
12
15
  #
13
16
  # +token_authentication_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
14
17
  #
15
- # == Examples:
16
- #
17
- # User.authenticate_with_token(:auth_token => '123456789') # returns authenticated user or nil
18
- # User.find(1).valid_authentication_token?('rI1t6PKQ8yP7VetgwdybB') # returns true/false
19
- #
20
18
  module TokenAuthenticatable
21
- def self.included(base)
22
- base.class_eval do
23
- extend ClassMethods
24
- before_save :ensure_authentication_token
25
- end
26
- end
19
+ extend ActiveSupport::Concern
27
20
 
28
21
  # Generate new authentication token (a.k.a. "single access token").
29
22
  def reset_authentication_token
@@ -33,7 +26,7 @@ module Devise
33
26
  # Generate new authentication token and save the record.
34
27
  def reset_authentication_token!
35
28
  reset_authentication_token
36
- self.save
29
+ self.save(:validate => false)
37
30
  end
38
31
 
39
32
  # Generate authentication token unless already exists.
@@ -46,43 +39,21 @@ module Devise
46
39
  self.reset_authentication_token! if self.authentication_token.blank?
47
40
  end
48
41
 
49
- # Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
50
- # is the user authentication token.
51
- def valid_authentication_token?(incoming_auth_token)
52
- incoming_auth_token.present? && incoming_auth_token == self.authentication_token
42
+ # Hook called after token authentication.
43
+ def after_token_authentication
53
44
  end
54
45
 
55
46
  module ClassMethods
56
- ::Devise::Models.config(self, :token_authentication_key)
57
-
58
- # Authenticate a user based on authentication token.
59
- def authenticate_with_token(attributes)
60
- token = attributes[self.token_authentication_key]
61
- resource = self.find_for_token_authentication(token)
62
- resource if resource.try(:valid_authentication_token?, token)
47
+ def find_for_token_authentication(conditions)
48
+ find_for_authentication(:authentication_token => conditions[token_authentication_key])
63
49
  end
64
50
 
51
+ # Generate a token checking if one does not already exist in the database.
65
52
  def authentication_token
66
- ::Devise.friendly_token
53
+ generate_token(:authentication_token)
67
54
  end
68
55
 
69
- protected
70
-
71
- # Find first record based on conditions given (ie by the sign in form).
72
- # Overwrite to add customized conditions, create a join, or maybe use a
73
- # namedscope to filter records while authenticating.
74
- #
75
- # == Example:
76
- #
77
- # def self.find_for_token_authentication(token, conditions = {})
78
- # conditions = {:active => true}
79
- # self.find_by_authentication_token(token, :conditions => conditions)
80
- # end
81
- #
82
- def find_for_token_authentication(token)
83
- self.find(:first, :conditions => { :authentication_token => token})
84
- end
85
-
56
+ ::Devise::Models.config(self, :token_authentication_key)
86
57
  end
87
58
  end
88
59
  end
@@ -11,6 +11,20 @@ module Devise
11
11
  # * last_sign_in_at - Holds the remote ip of the previous sign in
12
12
  #
13
13
  module Trackable
14
+ def update_tracked_fields!(request)
15
+ old_current, new_current = self.current_sign_in_at, Time.now
16
+ self.last_sign_in_at = old_current || new_current
17
+ self.current_sign_in_at = new_current
18
+
19
+ old_current, new_current = self.current_sign_in_ip, request.remote_ip
20
+ self.last_sign_in_ip = old_current || new_current
21
+ self.current_sign_in_ip = new_current
22
+
23
+ self.sign_in_count ||= 0
24
+ self.sign_in_count += 1
25
+
26
+ save(:validate => false)
27
+ end
14
28
  end
15
29
  end
16
30
  end
@@ -11,17 +11,18 @@ module Devise
11
11
  :validates_confirmation_of, :validates_length_of ].freeze
12
12
 
13
13
  def self.included(base)
14
+ base.extend ClassMethods
14
15
  assert_validations_api!(base)
15
16
 
16
17
  base.class_eval do
17
18
  validates_presence_of :email
18
19
  validates_uniqueness_of :email, :scope => authentication_keys[1..-1], :case_sensitive => false, :allow_blank => true
19
- validates_format_of :email, :with => EMAIL_REGEX, :allow_blank => true
20
+ validates_format_of :email, :with => email_regexp, :allow_blank => true
20
21
 
21
22
  with_options :if => :password_required? do |v|
22
23
  v.validates_presence_of :password
23
24
  v.validates_confirmation_of :password
24
- v.validates_length_of :password, :within => 6..20, :allow_blank => true
25
+ v.validates_length_of :password, :within => password_length, :allow_blank => true
25
26
  end
26
27
  end
27
28
  end
@@ -34,6 +35,19 @@ module Devise
34
35
  "to the following methods: #{unavailable_validations.to_sentence}."
35
36
  end
36
37
  end
38
+
39
+ protected
40
+
41
+ # Checks whether a password is needed or not. For validations only.
42
+ # Passwords are always required if it's a new record, or if the password
43
+ # or confirmation are being set somewhere.
44
+ def password_required?
45
+ !persisted? || !password.nil? || !password_confirmation.nil?
46
+ end
47
+
48
+ module ClassMethods
49
+ Devise::Models.config(self, :email_regexp, :password_length)
50
+ end
37
51
  end
38
52
  end
39
53
  end
data/lib/devise/models.rb CHANGED
@@ -1,16 +1,5 @@
1
1
  module Devise
2
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
3
  # Creates configuration values for Devise and for the given module.
15
4
  #
16
5
  # Devise::Models.config(Devise::Authenticable, :stretches, 10)
@@ -49,14 +38,14 @@ module Devise
49
38
 
50
39
  # Include the chosen devise modules in your model:
51
40
  #
52
- # devise :authenticatable, :confirmable, :recoverable
41
+ # devise :database_authenticatable, :confirmable, :recoverable
53
42
  #
54
43
  # You can also give any of the devise configuration values in form of a hash,
55
44
  # with specific values for this model. Please check your Devise initializer
56
45
  # for a complete description on those values.
57
46
  #
58
47
  def devise(*modules)
59
- raise "You need to give at least one Devise module" if modules.empty?
48
+ include Devise::Models::Authenticatable
60
49
  options = modules.extract_options!
61
50
 
62
51
  if modules.delete(:authenticatable)
@@ -64,54 +53,28 @@ module Devise
64
53
  modules << :database_authenticatable
65
54
  end
66
55
 
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) }
56
+ if modules.delete(:activatable)
57
+ ActiveSupport::Deprecation.warn ":activatable as module is deprecated. It's included in your model by default.", caller
75
58
  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
59
 
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)
60
+ if modules.delete(:http_authenticatable)
61
+ ActiveSupport::Deprecation.warn ":http_authenticatable as module is deprecated and is on by default. Revert by setting :http_authenticatable => false.", caller
89
62
  end
90
63
 
91
- unless record
92
- record = new
64
+ self.devise_modules += Devise::ALL & modules.map(&:to_sym).uniq
93
65
 
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)
66
+ devise_modules_hook! do
67
+ devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) }
68
+ options.each { |key, value| send(:"#{key}=", value) }
101
69
  end
102
-
103
- record
104
70
  end
105
71
 
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
72
+ # The hook which is called inside devise. So your ORM can include devise
73
+ # compatibility stuff.
74
+ def devise_modules_hook!
75
+ yield
115
76
  end
116
77
  end
117
78
  end
79
+
80
+ require 'devise/models/authenticatable'
@@ -0,0 +1,23 @@
1
+ require 'active_support/core_ext/object/with_options'
2
+
3
+ Devise.with_options :model => true do |d|
4
+ # Strategies first
5
+ d.with_options :strategy => true do |s|
6
+ s.add_module :database_authenticatable, :controller => :sessions, :route => :session
7
+ s.add_module :token_authenticatable, :controller => :sessions, :route => :session
8
+ s.add_module :rememberable
9
+ end
10
+
11
+ # Misc after
12
+ d.add_module :recoverable, :controller => :passwords, :route => :password
13
+ d.add_module :registerable, :controller => :registrations, :route => :registration
14
+ d.add_module :validatable
15
+
16
+ # The ones which can sign out after
17
+ d.add_module :confirmable, :controller => :confirmations, :route => :confirmation
18
+ d.add_module :lockable, :controller => :unlocks, :route => :unlock
19
+ d.add_module :timeoutable
20
+
21
+ # Stats for last, so we make sure the user is really signed in
22
+ d.add_module :trackable
23
+ end
@@ -3,7 +3,7 @@ module Devise
3
3
  # This module contains some helpers and handle schema (migrations):
4
4
  #
5
5
  # create_table :accounts do |t|
6
- # t.authenticatable
6
+ # t.database_authenticatable
7
7
  # t.confirmable
8
8
  # t.recoverable
9
9
  # t.rememberable
@@ -19,23 +19,18 @@ module Devise
19
19
  # add_index "accounts", ["reset_password_token"], :name => "reset_password_token", :unique => true
20
20
  #
21
21
  module ActiveRecord
22
- # Required ORM hook. Just yield the given block in ActiveRecord.
23
- def self.included_modules_hook(klass)
24
- yield
25
- end
26
-
27
- include Devise::Schema
22
+ module Schema
23
+ include Devise::Schema
28
24
 
29
- # Tell how to apply schema methods.
30
- def apply_schema(name, type, options={})
31
- column name, type.to_s.downcase.to_sym, options
25
+ # Tell how to apply schema methods.
26
+ def apply_devise_schema(name, type, options={})
27
+ column name, type.to_s.downcase.to_sym, options
28
+ end
32
29
  end
33
30
  end
34
31
  end
35
32
  end
36
33
 
37
- if defined?(ActiveRecord)
38
- ActiveRecord::Base.extend Devise::Models
39
- ActiveRecord::ConnectionAdapters::Table.send :include, Devise::Orm::ActiveRecord
40
- ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Orm::ActiveRecord
41
- end
34
+ ActiveRecord::Base.extend Devise::Models
35
+ ActiveRecord::ConnectionAdapters::Table.send :include, Devise::Orm::ActiveRecord::Schema
36
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Orm::ActiveRecord::Schema
@@ -0,0 +1,29 @@
1
+ module Devise
2
+ module Orm
3
+ module Mongoid
4
+ module Hook
5
+ def devise_modules_hook!
6
+ extend Schema
7
+ yield
8
+ return unless Devise.apply_schema
9
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
10
+ end
11
+ end
12
+
13
+ module Schema
14
+ include Devise::Schema
15
+
16
+ # Tell how to apply schema methods
17
+ def apply_devise_schema(name, type, options={})
18
+ type = Time if type == DateTime
19
+ field name, { :type => type }.merge(options)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ Mongoid::Document::ClassMethods.class_eval do
27
+ include Devise::Models
28
+ include Devise::Orm::Mongoid::Hook
29
+ end
@@ -0,0 +1,18 @@
1
+ module Devise
2
+ class PathChecker
3
+ include Rails.application.routes.url_helpers
4
+
5
+ def self.default_url_options(*args)
6
+ ApplicationController.default_url_options(*args)
7
+ end
8
+
9
+ def initialize(env, scope)
10
+ @current_path = "/#{env["SCRIPT_NAME"]}/#{env["PATH_INFO"]}".squeeze("/")
11
+ @scope = scope
12
+ end
13
+
14
+ def signing_out?
15
+ @current_path == send("destroy_#{@scope}_session_path")
16
+ end
17
+ end
18
+ end