Guest User

Untitled

a guest
Feb 20th, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.36 KB | None | 0 0
  1. require 'digest/sha1'
  2. class User < ActiveRecord::Base
  3.  
  4. ###########################
  5. # state
  6. ###########################
  7. state_machine :state_email, :initial => 'fresh' do
  8.  
  9. before_transition :to => 'unverified', :do => :make_email_verification_code
  10. before_transition :to => 'verified', :do => :set_email_verified_attributes
  11.  
  12. event :unverify do
  13. transition :to => 'unverified', :from => %w(unverified verified fresh)
  14. end
  15.  
  16. event :verify do
  17. transition :to => 'verified', :from => %w(unverified verified fresh)
  18. end
  19. end
  20.  
  21. state_machine :state_password, :initial => 'known' do
  22.  
  23. before_transition :to => 'forgotten', :do => :make_forgot_password_code
  24. before_transition :to => 'known', :do => :clear_forgot_password_code
  25.  
  26. event :forgets_password do
  27. transition :to => 'forgotten', :from => 'known'
  28. end
  29.  
  30. event :remembers_password do
  31. transition :to => 'known', :from => 'forgotten'
  32. end
  33. end
  34.  
  35. def verified?
  36. state_email == 'verified'
  37. end
  38.  
  39. def unverified?
  40. state_email == 'unverified'
  41. end
  42.  
  43. def forgets_password?
  44. state_password == 'forgotten'
  45. end
  46.  
  47. def remembers_password?
  48. state_password == 'known'
  49. end
  50.  
  51. ###########################
  52. # attributes
  53. ###########################
  54. # Virtual attribute for the unencrypted password
  55. attr_accessor :password, :terms_and_conditions
  56.  
  57. attr_accessible :login,
  58. :email,
  59. :password,
  60. :password_confirmation,
  61. :terms_and_conditions,
  62. :news,
  63. :gender,
  64. :display_name,
  65. :year
  66.  
  67. ###########################
  68. # validations
  69. ###########################
  70. validates_presence_of :email, :message => "missing email"
  71.  
  72. validates_length_of :login, :within => 3..40, :allow_blank => true, :message => "login must be between 3 and 40 characters"
  73. validates_length_of :email, :within => 3..100, :allow_blank => true, :message => "email must be between 3 and 100 characters"
  74.  
  75. validates_uniqueness_of :login, :allow_blank => true, :message => "login is taken"
  76. validates_uniqueness_of :email, :allow_blank => true, :message => "email is taken; please contact us if this seems like a mistake"
  77.  
  78. validates_format_of :login, :with => /^[^@]+$/, :allow_blank => true, :message => "invalid login (cannot be an email address)"
  79. validates_format_of :email, :with => /(\S+)@(\S+)/, :allow_blank => true, :message => "invalid email"
  80.  
  81. validates_presence_of :password, :if => :password_required?, :message => "missing password"
  82. validates_presence_of :password_confirmation, :if => :password_required?, :message => "missing password confirmation"
  83. validates_length_of :password, :within => 4..40, :if => :password_required?, :missing => "password must be between 4 and 40 characters"
  84. validates_confirmation_of :password, :if => :password_required?, :message => "passwords do not match"
  85.  
  86. validates_presence_of :terms_and_conditions, :on => :create, :message => "please read and agree to the terms and conditions"
  87. validates_format_of :terms_and_conditions, :with => /^1$/, :on => :create, :message => "please read and agree to the terms and conditions"
  88.  
  89. validates_inclusion_of :news, :in => [true,false], :allow_blank => true
  90.  
  91. validates_inclusion_of :gender, :in => %w(m f), :allow_blank => true, :message => 'must select m or f'
  92. validates_format_of :year, :with => /^\d{4}$/, :allow_blank => true, :message => 'must select a year'
  93.  
  94. ###########################
  95. # callbacks
  96. ###########################
  97. before_save :encrypt_password, :nullify_blanks, :check_for_new_unverified_email
  98.  
  99. ###########################
  100. # public methods
  101. ###########################
  102. # Updates attributes while also marking that the email address has been
  103. # verified.
  104. def verify_email_and_update_password_attributes(attributes)
  105. self.verify(false) # the false flag tells SM not to save
  106. self.remembers_password(false) # the false flag tells SM not to save
  107. self.update_attributes(attributes.delete_if {|key, val| key.to_sym != :password && key.to_sym != :password_confirmation})
  108. end
  109.  
  110. # Authenticates a user by their login name and unencrypted password. Returns
  111. # the user or nil. Also calls remembers_password in CASE 1 of
  112. # forgot_password?. This is the main (non-fatal) flaw of the combined
  113. # email-verification/forgotten password system.
  114. def self.authenticate(login_or_email, password)
  115. u = find :first, :conditions => ["#{login_or_email =~ /@/ ? 'email' : 'login'} = ?", login_or_email]
  116. if u && u.authenticated?(password)
  117. u.remembers_password
  118. u
  119. end
  120. end
  121.  
  122. # Encrypts some data with the salt.
  123. def self.encrypt(password, salt)
  124. Digest::SHA1.hexdigest("--#{salt}--#{password}--")
  125. end
  126.  
  127. # Encrypts the password with the user salt
  128. def encrypt(password)
  129. self.class.encrypt(password, salt)
  130. end
  131.  
  132. def authenticated?(password)
  133. crypted_password == encrypt(password)
  134. end
  135.  
  136. # A customized attribute writer that sets whether or not the user is
  137. # changing the email address.
  138. def email=(new_email)
  139. unless (self.email == new_email) || new_email.blank?
  140. @email_updated = true
  141. write_attribute(:email, new_email)
  142. end
  143. end
  144.  
  145. ###########################
  146. # protected methods
  147. ###########################
  148. protected
  149.  
  150. # Before filter that encrypts a plain text password into a crypted_password.
  151. def encrypt_password
  152. return if password.blank?
  153. self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
  154. self.crypted_password = encrypt(password)
  155. end
  156.  
  157. # Before filter that ensures "NULL" values instead of blanks in DB.
  158. def nullify_blanks
  159. self.login = nil if login.blank?
  160. write_attribute(:email, nil) if email.blank?
  161. end
  162.  
  163. # If there's an email address and it's different than the one that existed
  164. # when the record was loaded we need to validate it again.
  165. def check_for_new_unverified_email
  166. unverify(false) if @email_updated && !self.unverified?
  167. end
  168.  
  169. def make_email_verification_code
  170. self.multipurpose_code = new_multipurpose_code
  171. self.email_verified_at = nil
  172. end
  173.  
  174. def make_forgot_password_code
  175. self.multipurpose_code = new_multipurpose_code
  176. end
  177.  
  178. def clear_forgot_password_code
  179. self.multipurpose_code = nil if self.verified?
  180. end
  181.  
  182. # Creates a random hash code that has oh so many uses.
  183. def new_multipurpose_code
  184. Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
  185. end
  186.  
  187. # Called to set the attributes associated with an email verification.
  188. def set_email_verified_attributes
  189. self.email_verified_at = Time.now.utc
  190. self.multipurpose_code = nil
  191. end
  192.  
  193. # Some helper methods used in validation.
  194. def present_email?
  195. !email.blank?
  196. end
  197.  
  198. def present_login?
  199. !login.blank?
  200. end
  201.  
  202. def blank_email?
  203. email.blank?
  204. end
  205.  
  206. def blank_login?
  207. login.blank?
  208. end
  209.  
  210. def password_required?
  211. crypted_password.blank? || !password.blank?
  212. end
  213. end
Add Comment
Please, Sign In to add comment