/app/models/user.rb

https://github.com/larssg/score-keeper · Ruby · 155 lines · 116 code · 30 blank · 9 comment · 11 complexity · 67053c7b8eef9132343203924f339c81 MD5 · raw file

  1. require 'digest/sha1'
  2. class User < ActiveRecord::Base
  3. # Virtual attribute for the unencrypted password
  4. attr_accessor :password
  5. belongs_to :account
  6. has_many :game_participations
  7. has_many :games, :through => :game_participations
  8. has_many :memberships
  9. has_many :comments
  10. has_many :logs
  11. has_many :teams, :through => :memberships
  12. belongs_to :last_game, :class_name => "Game", :foreign_key => "last_game_id"
  13. validates_presence_of :email
  14. validates_length_of :email, :within => 3..100
  15. validates_presence_of :login
  16. validates_length_of :login, :within => 2..100
  17. validates_uniqueness_of :login, :scope => :account_id, :case_sensitive => false, :message => 'is already taken; sorry!'
  18. validates_uniqueness_of :email, :scope => :account_id, :case_sensitive => false, :message => 'is already being used; do you already have an account?'
  19. validates_presence_of :password, :if => :password_required?
  20. validates_presence_of :password_confirmation, :if => :password_required?
  21. validates_length_of :password, :within => 4..40, :if => :password_required?
  22. validates_confirmation_of :password, :if => :password_required?
  23. validates_presence_of :name
  24. validates_presence_of :time_zone
  25. before_save :encrypt_password
  26. before_save :set_display_name
  27. before_validation :set_time_zone
  28. before_validation :set_name_from_login
  29. after_create :set_feed_token
  30. before_destroy :remove_matches
  31. default_scope order('name, display_name')
  32. has_attached_file :avatar, :styles => { :thumb => '60x60>' }
  33. # prevents a user from submitting a crafted form that bypasses activation
  34. # anything else you want your user to change should be added here.
  35. attr_accessible :login, :email, :password, :password_confirmation, :name, :display_name, :time_zone, :avatar
  36. def set_display_name
  37. return if self.name.blank?
  38. self.display_name = self.name.split[0] if self.display_name.blank?
  39. end
  40. def all_time_high(game)
  41. Membership.find(:first, :conditions => { :user_id => self.id, :game_id => game.id }, :order => 'memberships.current_ranking DESC')
  42. end
  43. def all_time_low(game)
  44. Membership.find(:first, :conditions => { :user_id => self.id, :game_id => game.id }, :order => 'memberships.current_ranking')
  45. end
  46. def position(game)
  47. game.user_positions.each_with_index do |game_participation, index|
  48. return index + 1 if game_participation.user_id == self.id
  49. end
  50. end
  51. # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
  52. def self.authenticate(login, password)
  53. u = find_by_login(login) # need to get the salt
  54. u && u.authenticated?(password) ? u : nil
  55. end
  56. # Encrypts some data with the salt.
  57. def self.encrypt(password, salt)
  58. Digest::SHA1.hexdigest("--#{salt}--#{password}--")
  59. end
  60. # Encrypts the password with the user salt
  61. def encrypt(password)
  62. self.class.encrypt(password, salt)
  63. end
  64. def authenticated?(password)
  65. crypted_password == encrypt(password)
  66. end
  67. def remember_token?
  68. remember_token_expires_at && Time.now.utc < remember_token_expires_at
  69. end
  70. # These create and unset the fields required for remembering users between browser closes
  71. def remember_me
  72. remember_me_for 2.weeks
  73. end
  74. def remember_me_for(time)
  75. remember_me_until time.from_now.utc
  76. end
  77. def remember_me_until(time)
  78. self.remember_token_expires_at = time
  79. self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
  80. save(false)
  81. end
  82. def forget_me
  83. self.remember_token_expires_at = nil
  84. self.remember_token = nil
  85. save(false)
  86. end
  87. def set_time_zone
  88. if self.time_zone.blank?
  89. self.time_zone = self.account.time_zone unless self.account.nil?
  90. self.time_zone ||= 'Copenhagen'
  91. end
  92. end
  93. def set_feed_token
  94. self.update_attribute :feed_token, encrypt("#{email}--#{5.minutes.ago.to_s}")
  95. end
  96. def set_login_token
  97. self.update_attribute :login_token, encrypt("#{email}--#{5.minutes.ago.to_s}")
  98. end
  99. protected
  100. def set_name_from_login
  101. self.name ||= self.login.humanize
  102. end
  103. def remove_matches
  104. self.memberships.each do |membership|
  105. match = membership.team.match
  106. match.postpone_ranking_update = true
  107. match.destroy
  108. end
  109. # Fix stats
  110. self.account.games.each do |game|
  111. Match.reset_rankings(game)
  112. end
  113. end
  114. # before filter
  115. def encrypt_password
  116. return if password.blank?
  117. if new_record?
  118. self.salt = Digest::SHA1.hexdigest("--#{Time.now}--#{login}--")
  119. end
  120. self.crypted_password = encrypt(password)
  121. end
  122. def password_required?
  123. crypted_password.blank? || password.present?
  124. end
  125. end