graffititracker_devise 1.0.11

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 +410 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +272 -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 +42 -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 +277 -0
  35. data/lib/devise/controllers/helpers.rb +226 -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 +72 -0
  46. data/lib/devise/hooks/activatable.rb +15 -0
  47. data/lib/devise/hooks/rememberable.rb +33 -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 +130 -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 +167 -0
  55. data/lib/devise/models/database_authenticatable.rb +144 -0
  56. data/lib/devise/models/http_authenticatable.rb +23 -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 +52 -0
  68. data/lib/devise/rails.rb +14 -0
  69. data/lib/devise/rails/routes.rb +133 -0
  70. data/lib/devise/rails/warden_compat.rb +63 -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 +184 -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 +340 -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 +82 -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 +158 -0
  101. data/test/models/authenticatable_test.rb +180 -0
  102. data/test/models/confirmable_test.rb +228 -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 +25 -0
  132. data/test/routes_test.rb +131 -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 +279 -0
@@ -0,0 +1,16 @@
1
+ require 'devise/hooks/activatable'
2
+
3
+ module Devise
4
+ module Models
5
+ # This module implements the default API required in activatable hook.
6
+ module Activatable
7
+ def active?
8
+ true
9
+ end
10
+
11
+ def inactive_message
12
+ :inactive
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,167 @@
1
+ require 'devise/models/activatable'
2
+
3
+ module Devise
4
+ module Models
5
+
6
+ # Confirmable is responsible to verify if an account is already confirmed to
7
+ # sign in, and to send emails with confirmation instructions.
8
+ # Confirmation instructions are sent to the user email after creating a
9
+ # record, after updating it's email and also when manually requested by
10
+ # a new confirmation instruction request.
11
+ # Whenever the user update it's email, his account is automatically unconfirmed,
12
+ # it means it won't be able to sign in again without confirming the account
13
+ # again through the email that was sent.
14
+ #
15
+ # Configuration:
16
+ #
17
+ # confirm_within: the time you want the user will have to confirm it's account
18
+ # without blocking his access. When confirm_within is zero, the
19
+ # user won't be able to sign in without confirming. You can
20
+ # use this to let your user access some features of your
21
+ # application without confirming the account, but blocking it
22
+ # after a certain period (ie 7 days). By default confirm_within is
23
+ # zero, it means users always have to confirm to sign in.
24
+ #
25
+ # Examples:
26
+ #
27
+ # User.find(1).confirm! # returns true unless it's already confirmed
28
+ # User.find(1).confirmed? # true/false
29
+ # User.find(1).send_confirmation_instructions # manually send instructions
30
+ # User.find(1).resend_confirmation! # generates a new token and resent it
31
+ module Confirmable
32
+ include Devise::Models::Activatable
33
+
34
+ def self.included(base)
35
+ base.class_eval do
36
+ extend ClassMethods
37
+
38
+ before_create :generate_confirmation_token, :if => :confirmation_required?
39
+ after_create :send_confirmation_instructions, :if => :confirmation_required?
40
+ end
41
+ end
42
+
43
+ # Confirm a user by setting it's confirmed_at to actual time. If the user
44
+ # is already confirmed, add en error to email field
45
+ def confirm!
46
+ unless_confirmed do
47
+ self.confirmation_token = nil
48
+ self.confirmed_at = Time.now
49
+ save(false)
50
+ end
51
+ end
52
+
53
+ # Verifies whether a user is confirmed or not
54
+ def confirmed?
55
+ !new_record? && !confirmed_at.nil?
56
+ end
57
+
58
+ # Send confirmation instructions by email
59
+ def send_confirmation_instructions
60
+ generate_confirmation_token! if self.confirmation_token.nil?
61
+ ::DeviseMailer.deliver_confirmation_instructions(self)
62
+ end
63
+
64
+ # Resend confirmation token. This method does not need to generate a new token.
65
+ def resend_confirmation_token
66
+ unless_confirmed { send_confirmation_instructions }
67
+ end
68
+
69
+ # Overwrites active? from Devise::Models::Activatable for confirmation
70
+ # by verifying whether an user is active to sign in or not. If the user
71
+ # is already confirmed, it should never be blocked. Otherwise we need to
72
+ # calculate if the confirm time has not expired for this user.
73
+ def active?
74
+ super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
75
+ end
76
+
77
+ # The message to be shown if the account is inactive.
78
+ def inactive_message
79
+ !confirmed? ? :unconfirmed : super
80
+ end
81
+
82
+ # If you don't want confirmation to be sent on create, neither a code
83
+ # to be generated, call skip_confirmation!
84
+ def skip_confirmation!
85
+ self.confirmed_at = Time.now
86
+ @skip_confirmation = true
87
+ end
88
+
89
+ protected
90
+
91
+ # Callback to overwrite if confirmation is required or not.
92
+ def confirmation_required?
93
+ !@skip_confirmation
94
+ end
95
+
96
+ # Checks if the confirmation for the user is within the limit time.
97
+ # We do this by calculating if the difference between today and the
98
+ # confirmation sent date does not exceed the confirm in time configured.
99
+ # Confirm_in is a model configuration, must always be an integer value.
100
+ #
101
+ # Example:
102
+ #
103
+ # # confirm_within = 1.day and confirmation_sent_at = today
104
+ # confirmation_period_valid? # returns true
105
+ #
106
+ # # confirm_within = 5.days and confirmation_sent_at = 4.days.ago
107
+ # confirmation_period_valid? # returns true
108
+ #
109
+ # # confirm_within = 5.days and confirmation_sent_at = 5.days.ago
110
+ # confirmation_period_valid? # returns false
111
+ #
112
+ # # confirm_within = 0.days
113
+ # confirmation_period_valid? # will always return false
114
+ #
115
+ def confirmation_period_valid?
116
+ confirmation_sent_at && confirmation_sent_at.utc >= self.class.confirm_within.ago
117
+ end
118
+
119
+ # Checks whether the record is confirmed or not, yielding to the block
120
+ # if it's already confirmed, otherwise adds an error to email.
121
+ def unless_confirmed
122
+ unless confirmed?
123
+ yield
124
+ else
125
+ self.class.add_error_on(self, :email, :already_confirmed)
126
+ false
127
+ end
128
+ end
129
+
130
+ # Generates a new random token for confirmation, and stores the time
131
+ # this token is being generated
132
+ def generate_confirmation_token
133
+ self.confirmed_at = nil
134
+ self.confirmation_token = Devise.friendly_token
135
+ self.confirmation_sent_at = Time.now.utc
136
+ end
137
+
138
+ def generate_confirmation_token!
139
+ generate_confirmation_token && save(false)
140
+ end
141
+
142
+ module ClassMethods
143
+ # Attempt to find a user by it's email. If a record is found, send new
144
+ # confirmation instructions to it. If not user is found, returns a new user
145
+ # with an email not found error.
146
+ # Options must contain the user email
147
+ def send_confirmation_instructions(attributes={})
148
+ confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
149
+ confirmable.resend_confirmation_token unless confirmable.new_record?
150
+ confirmable
151
+ end
152
+
153
+ # Find a user by it's confirmation token and try to confirm it.
154
+ # If no user is found, returns a new user with an error.
155
+ # If the user is already confirmed, create an error for the user
156
+ # Options must have the confirmation_token
157
+ def confirm_by_token(confirmation_token)
158
+ confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
159
+ confirmable.confirm! unless confirmable.new_record?
160
+ confirmable
161
+ end
162
+
163
+ Devise::Models.config(self, :confirm_within)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,144 @@
1
+ require 'devise/strategies/database_authenticatable'
2
+
3
+ module Devise
4
+ module Models
5
+ # Authenticable Module, responsible for encrypting password and validating
6
+ # authenticity of a user while signing in.
7
+ #
8
+ # Configuration:
9
+ #
10
+ # You can overwrite configuration values by setting in globally in Devise,
11
+ # using devise method or overwriting the respective instance method.
12
+ #
13
+ # pepper: encryption key used for creating encrypted password. Each time
14
+ # password changes, it's gonna be encrypted again, and this key
15
+ # is added to the password and salt to create a secure hash.
16
+ # Always use `rake secret' to generate a new key.
17
+ #
18
+ # stretches: defines how many times the password will be encrypted.
19
+ #
20
+ # encryptor: the encryptor going to be used. By default :sha1.
21
+ #
22
+ # authentication_keys: parameters used for authentication. By default [:email]
23
+ #
24
+ # Examples:
25
+ #
26
+ # User.authenticate('email@test.com', 'password123') # returns authenticated user or nil
27
+ # User.find(1).valid_password?('password123') # returns true/false
28
+ #
29
+ module DatabaseAuthenticatable
30
+ def self.included(base)
31
+ base.class_eval do
32
+ extend ClassMethods
33
+
34
+ attr_reader :password, :current_password
35
+ attr_accessor :password_confirmation
36
+ end
37
+ end
38
+
39
+ # TODO Remove me in next release
40
+ def old_password
41
+ ActiveSupport::Deprecation.warn "old_password is deprecated, please use current_password instead", caller
42
+ @old_password
43
+ end
44
+
45
+ # Regenerates password salt and encrypted password each time password is set,
46
+ # and then trigger any "after_changed_password"-callbacks.
47
+ def password=(new_password)
48
+ @password = new_password
49
+
50
+ if @password.present?
51
+ self.password_salt = self.class.encryptor_class.salt
52
+ self.encrypted_password = password_digest(@password)
53
+ end
54
+ end
55
+
56
+ # Verifies whether an incoming_password (ie from sign in) is the user password.
57
+ def valid_password?(incoming_password)
58
+ Devise.secure_compare(password_digest(incoming_password), self.encrypted_password)
59
+ end
60
+
61
+ # Checks if a resource is valid upon authentication.
62
+ def valid_for_authentication?(attributes)
63
+ valid_password?(attributes[:password])
64
+ end
65
+
66
+ # Set password and password confirmation to nil
67
+ def clean_up_passwords
68
+ self.password = self.password_confirmation = nil
69
+ end
70
+
71
+ # Update record attributes when :current_password matches, otherwise returns
72
+ # error on :current_password. It also automatically rejects :password and
73
+ # :password_confirmation if they are blank.
74
+ def update_with_password(params={})
75
+ current_password = params.delete(:current_password)
76
+
77
+ if params[:password].blank?
78
+ params.delete(:password)
79
+ params.delete(:password_confirmation) if params[:password_confirmation].blank?
80
+ end
81
+
82
+ result = if valid_password?(current_password)
83
+ update_attributes(params)
84
+ else
85
+ message = current_password.blank? ? :blank : :invalid
86
+ self.class.add_error_on(self, :current_password, message, false)
87
+ self.attributes = params
88
+ false
89
+ end
90
+
91
+ clean_up_passwords unless result
92
+ result
93
+ end
94
+
95
+ protected
96
+
97
+ # Checks whether a password is needed or not. For validations only.
98
+ # Passwords are always required if it's a new record, or if the password
99
+ # or confirmation are being set somewhere.
100
+ def password_required?
101
+ new_record? || !password.nil? || !password_confirmation.nil?
102
+ end
103
+
104
+ # Digests the password using the configured encryptor.
105
+ def password_digest(password)
106
+ self.class.encryptor_class.digest(password, self.class.stretches, self.password_salt, self.class.pepper)
107
+ end
108
+
109
+ module ClassMethods
110
+ Devise::Models.config(self, :pepper, :stretches, :encryptor, :authentication_keys)
111
+
112
+ # Authenticate a user based on configured attribute keys. Returns the
113
+ # authenticated user if it's valid or nil.
114
+ def authenticate(attributes={})
115
+ return unless authentication_keys.all? { |k| attributes[k].present? }
116
+ conditions = attributes.slice(*authentication_keys)
117
+ resource = find_for_authentication(conditions)
118
+ resource if resource.try(:valid_for_authentication?, attributes)
119
+ end
120
+
121
+ # Returns the class for the configured encryptor.
122
+ def encryptor_class
123
+ @encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
124
+ end
125
+
126
+ protected
127
+
128
+ # Find first record based on conditions given (ie by the sign in form).
129
+ # Overwrite to add customized conditions, create a join, or maybe use a
130
+ # namedscope to filter records while authenticating.
131
+ # Example:
132
+ #
133
+ # def self.find_for_authentication(conditions={})
134
+ # conditions[:active] = true
135
+ # find(:first, :conditions => conditions)
136
+ # end
137
+ #
138
+ def find_for_authentication(conditions)
139
+ find(:first, :conditions => conditions)
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,23 @@
1
+ require 'devise/strategies/http_authenticatable'
2
+
3
+ module Devise
4
+ module Models
5
+ # Adds HttpAuthenticatable behavior to your model. It expects that your
6
+ # model class responds to authenticate method
7
+ # (which for example is defined in authenticatable).
8
+ module HttpAuthenticatable
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+ Devise::Models.config(self, :authentication_keys)
15
+
16
+ # Authenticate an user using http.
17
+ def authenticate_with_http(username, password)
18
+ authenticate(authentication_keys.first => username, :password => password)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,150 @@
1
+ require 'devise/models/activatable'
2
+
3
+ module Devise
4
+ module Models
5
+
6
+ # Handles blocking a user access after a certain number of attempts.
7
+ # Lockable accepts two different strategies to unlock a user after it's
8
+ # blocked: email and time. The former will send an email to the user when
9
+ # the lock happens, containing a link to unlock it's account. The second
10
+ # will unlock the user automatically after some configured time (ie 2.hours).
11
+ # It's also possible to setup lockable to use both email and time strategies.
12
+ #
13
+ # Configuration:
14
+ #
15
+ # maximum_attempts: how many attempts should be accepted before blocking the user.
16
+ # unlock_strategy: unlock the user account by :time, :email or :both.
17
+ # unlock_in: the time you want to lock the user after to lock happens. Only
18
+ # available when unlock_strategy is :time or :both.
19
+ #
20
+ module Lockable
21
+ include Devise::Models::Activatable
22
+
23
+ def self.included(base)
24
+ base.class_eval do
25
+ extend ClassMethods
26
+ end
27
+ end
28
+
29
+ # Lock an user setting it's locked_at to actual time.
30
+ def lock_access!
31
+ return true if access_locked?
32
+ self.locked_at = Time.now
33
+
34
+ if self.class.unlock_strategy_enabled?(:email)
35
+ generate_unlock_token
36
+ send_unlock_instructions
37
+ end
38
+
39
+ save(false)
40
+ end
41
+
42
+ # Unlock an user by cleaning locket_at and failed_attempts.
43
+ def unlock_access!
44
+ if_access_locked do
45
+ self.locked_at = nil
46
+ self.failed_attempts = 0
47
+ self.unlock_token = nil
48
+ save(false)
49
+ end
50
+ end
51
+
52
+ # Verifies whether a user is locked or not.
53
+ def access_locked?
54
+ locked_at && !lock_expired?
55
+ end
56
+
57
+ # Send unlock instructions by email
58
+ def send_unlock_instructions
59
+ ::DeviseMailer.deliver_unlock_instructions(self)
60
+ end
61
+
62
+ # Resend the unlock instructions if the user is locked.
63
+ def resend_unlock_token
64
+ if_access_locked { send_unlock_instructions }
65
+ end
66
+
67
+ # Overwrites active? from Devise::Models::Activatable for locking purposes
68
+ # by verifying whether an user is active to sign in or not based on locked?
69
+ def active?
70
+ super && !access_locked?
71
+ end
72
+
73
+ # Overwrites invalid_message from Devise::Models::Authenticatable to define
74
+ # the correct reason for blocking the sign in.
75
+ def inactive_message
76
+ access_locked? ? :locked : super
77
+ end
78
+
79
+ # Overwrites valid_for_authentication? from Devise::Models::Authenticatable
80
+ # for verifying whether an user is allowed to sign in or not. If the user
81
+ # is locked, it should never be allowed.
82
+ def valid_for_authentication?(attributes)
83
+ if result = super
84
+ self.failed_attempts = 0
85
+ else
86
+ self.failed_attempts += 1
87
+ lock_access! if failed_attempts > self.class.maximum_attempts
88
+ end
89
+ save(false) if changed?
90
+ result
91
+ end
92
+
93
+ protected
94
+
95
+ # Generates unlock token
96
+ def generate_unlock_token
97
+ self.unlock_token = Devise.friendly_token
98
+ end
99
+
100
+ # Tells if the lock is expired if :time unlock strategy is active
101
+ def lock_expired?
102
+ if self.class.unlock_strategy_enabled?(:time)
103
+ locked_at && locked_at < self.class.unlock_in.ago
104
+ else
105
+ false
106
+ end
107
+ end
108
+
109
+ # Checks whether the record is locked or not, yielding to the block
110
+ # if it's locked, otherwise adds an error to email.
111
+ def if_access_locked
112
+ if access_locked?
113
+ yield
114
+ else
115
+ self.class.add_error_on(self, :email, :not_locked)
116
+ false
117
+ end
118
+ end
119
+
120
+ module ClassMethods
121
+ # Attempt to find a user by it's email. If a record is found, send new
122
+ # unlock instructions to it. If not user is found, returns a new user
123
+ # with an email not found error.
124
+ # Options must contain the user email
125
+ def send_unlock_instructions(attributes={})
126
+ lockable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
127
+ lockable.resend_unlock_token unless lockable.new_record?
128
+ lockable
129
+ end
130
+
131
+ # Find a user by it's unlock token and try to unlock it.
132
+ # If no user is found, returns a new user with an error.
133
+ # If the user is not locked, creates an error for the user
134
+ # Options must have the unlock_token
135
+ def unlock_access_by_token(unlock_token)
136
+ lockable = find_or_initialize_with_error_by(:unlock_token, unlock_token)
137
+ lockable.unlock_access! unless lockable.new_record?
138
+ lockable
139
+ end
140
+
141
+ # Is the unlock enabled for the given unlock strategy?
142
+ def unlock_strategy_enabled?(strategy)
143
+ [:both, strategy].include?(self.unlock_strategy)
144
+ end
145
+
146
+ Devise::Models.config(self, :maximum_attempts, :unlock_strategy, :unlock_in)
147
+ end
148
+ end
149
+ end
150
+ end