-
-
Notifications
You must be signed in to change notification settings - Fork 457
/
user.rb
158 lines (135 loc) · 4.25 KB
/
user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require 'digest/sha1'
module Clearance
module User
extend ActiveSupport::Concern
# Hook for all Clearance::User modules.
#
# If you need to override parts of Clearance::User,
# extend and include à la carte.
#
# @example
# include Clearance::User::Callbacks
#
# @see Validations
# @see Callbacks
included do
attr_accessor :password_changing
attr_reader :password
include Validations
include Callbacks
include (Clearance.configuration.password_strategy || Clearance::PasswordStrategies::SHA1)
end
module ClassMethods
# Authenticate with email and password.
#
# @param [String, String] email and password
# @return [User, nil] authenticated user or nil
# @example
# User.authenticate("email@example.com", "password")
def authenticate(email, password)
return nil unless user = find_by_email(email.to_s.downcase)
return user if user.authenticated?(password)
end
end
module Validations
extend ActiveSupport::Concern
# Hook for validations.
#
# :email must be present, unique, formatted
#
# If password is required,
# :password must be present, confirmed
included do
validates_presence_of :email, :unless => :email_optional?
validates_uniqueness_of :email, :allow_blank => true
validates_format_of :email, :with => %r{^[a-z0-9!#\$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$}i, :allow_blank => true
validates_presence_of :password, :unless => :password_optional?
end
end
module Callbacks
extend ActiveSupport::Concern
# Hook for callbacks.
#
# salt, token, password encryption are handled before_save.
included do
before_validation :downcase_email
before_create :generate_remember_token
end
end
# Set the remember token.
#
# @deprecated Use {#reset_remember_token!} instead
def remember_me!
warn "[DEPRECATION] remember_me!: use reset_remember_token! instead"
reset_remember_token!
end
# Reset the remember token.
#
# @example
# user.reset_remember_token!
def reset_remember_token!
generate_remember_token
save(:validate => false)
end
# Mark my account as forgotten password.
#
# @example
# user.forgot_password!
def forgot_password!
generate_confirmation_token
save(:validate => false)
end
# Update my password.
#
# @return [true, false] password was updated or not
# @example
# user.update_password('new-password')
def update_password(new_password)
self.password_changing = true
self.password = new_password
if valid?
self.confirmation_token = nil
generate_remember_token
end
save
end
def password=(unencrypted_password)
@password = unencrypted_password
encrypt_password
end
protected
def generate_random_code(length = 20)
if RUBY_VERSION >= '1.9'
SecureRandom.hex(length).encode('UTF-8')
else
SecureRandom.hex(length)
end
end
def generate_remember_token
self.remember_token = generate_random_code
end
def generate_confirmation_token
self.confirmation_token = generate_random_code
end
# Always false. Override to allow other forms of authentication
# (username, facebook, etc).
# @return [Boolean] true if the email field be left blank for this user
def email_optional?
false
end
# True if the password has been set and the password is not being
# updated and we are not updating the password. Override to allow
# other forms of authentication (username, facebook, etc).
# @return [Boolean] true if the password field can be left blank for this user
def password_optional?
encrypted_password.present? && password.blank? && password_changing.blank?
end
def password_required?
# warn "[DEPRECATION] password_required?: use !password_optional? instead"
!password_optional?
end
def downcase_email
self.email = email.to_s.downcase
end
end
end