PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/app/models/user.rb

https://github.com/eidus/incubaction-bbyidx
Ruby | 275 lines | 218 code | 46 blank | 11 comment | 20 complexity | 2c7718ddcfc96b3260356ae30e555e2d MD5 | raw file
  1. require 'digest/sha1'
  2. class User < ActiveRecord::Base
  3. acts_as_authorized_user
  4. acts_as_authorizable
  5. # Virtual attribute for the unencrypted password
  6. attr_accessor :password
  7. has_many :ideas, :foreign_key => 'inventor_id' do
  8. def recent_visible(opts = {})
  9. Idea.populate_comment_counts(
  10. find :all, opts.reverse_merge(
  11. :conditions => { :hidden => false, 'users.state' => 'active' },
  12. :include => [:tags, :inventor],
  13. :order => 'ideas.created_at desc',
  14. :limit => 10))
  15. end
  16. end
  17. has_many :currents, :foreign_key => 'inventor_id'
  18. has_many :comments, :foreign_key => 'author_id' do
  19. def recent_visible(opts = {})
  20. find :all, opts.reverse_merge(
  21. :conditions => { 'comments.hidden' => false, 'ideas.hidden' => false, 'users.state' => 'active' },
  22. :include => [:idea, :author],
  23. :order => 'comments.created_at desc',
  24. :limit => 10)
  25. end
  26. end
  27. has_many :votes do
  28. def recent_visible(opts = {})
  29. find :all, opts.reverse_merge(
  30. :include => { :idea => :inventor },
  31. :conditions => { 'ideas.hidden' => false, 'users.state' => 'active' },
  32. :order => 'votes.id desc',
  33. :limit => 10)
  34. end
  35. end
  36. has_and_belongs_to_many :life_cycle_steps, :join_table => 'life_cycle_steps_admins', :order => 'life_cycle_id, position'
  37. belongs_to :postal_code
  38. has_many :roles_users, :dependent => :delete_all
  39. has_many :roles, :through => :roles_users do
  40. def for_name(name)
  41. find :all, :conditions => { :name => name }
  42. end
  43. end
  44. has_and_belongs_to_many :subscribed_ideas, :class_name => 'Idea', :join_table => 'ideas_subscribers'
  45. has_and_belongs_to_many :subscribed_currents, :class_name => 'Current', :join_table => 'currents_subscribers'
  46. # OAuth support
  47. has_many :client_applications
  48. has_many :tokens, :class_name => 'OauthToken', :order => 'authorized_at desc', :include => [:client_application]
  49. validates_presence_of :name
  50. validates_presence_of :email
  51. validates_presence_of :zip_code
  52. validates_presence_of :password, :if => :password_required?
  53. validates_presence_of :password_confirmation, :if => :password_confirmation_required?
  54. validates_length_of :password, :within => 4..40, :if => :password_required?
  55. validates_confirmation_of :password, :if => :password_required?
  56. validates_length_of :name, :within => 4..100
  57. validates_length_of :email, :within => 3..100
  58. validates_format_of :email, :with => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
  59. validates_uniqueness_of :email, :case_sensitive => false
  60. validates_acceptance_of :terms_of_service, :allow_nil => false, :if => 'new_record?'
  61. before_save :encrypt_password, :assign_postal_code
  62. # prevents a user from submitting a crafted form that bypasses activation
  63. # anything else you want your user to change should be added here.
  64. attr_accessible :name, :email, :password, :password_confirmation, :zip_code, :terms_of_service, :tweet_ideas, :facebook_post_ideas, :notify_on_comments, :notify_on_state
  65. unless !User.table_exists?
  66. acts_as_tsearch :fields => %w(name email zip_code )
  67. end
  68. acts_as_state_machine :initial => :pending
  69. state :passive
  70. state :pending, :enter => :registered
  71. state :active, :enter => :do_activate
  72. state :suspended
  73. state :deleted, :enter => :do_delete
  74. event :register do
  75. transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| !(u.crypted_password.blank? && u.password.blank?) }
  76. end
  77. event :activate do
  78. transitions :from => :pending, :to => :active
  79. end
  80. event :suspend do
  81. transitions :from => [:passive, :pending, :active], :to => :suspended
  82. end
  83. event :delete do
  84. transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
  85. end
  86. event :unsuspend do
  87. transitions :from => :suspended, :to => :active, :guard => Proc.new { |u| !u.activated_at.blank? }
  88. transitions :from => :suspended, :to => :pending, :guard => Proc.new { |u| !u.activation_code.blank? }
  89. transitions :from => :suspended, :to => :passive
  90. end
  91. # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
  92. def self.authenticate(email, password)
  93. return nil unless user = find_by_login(email, password)
  94. user.active? ? user : nil
  95. end
  96. # Authenticates a user's login & password without checking that they are active.
  97. def self.find_by_login(email, password)
  98. u = find :first, :conditions => {:email => email} # need to get the salt
  99. u && u.authenticated?(password) ? u : nil
  100. end
  101. def self.find_top_contributors(all_time = false, opts = {})
  102. find :all, opts.reverse_merge(
  103. :conditions => [
  104. 'state = ? and (select count(*) from roles_users where roles_users.user_id = users.id) = 0', 'active'],
  105. :order => all_time ? 'contribution_points desc' : 'recent_contribution_points desc')
  106. end
  107. # Encrypts some data with the salt.
  108. def self.encrypt(password, salt)
  109. Digest::SHA1.hexdigest("--#{salt}--#{password}--")
  110. end
  111. # Encrypts the password with the user salt
  112. def encrypt(password)
  113. self.class.encrypt(password, salt)
  114. end
  115. def authenticated?(password)
  116. crypted_password == encrypt(password)
  117. end
  118. def remember_token?
  119. remember_token_expires_at && Time.now.utc < remember_token_expires_at
  120. end
  121. # These create and unset the fields required for remembering users between browser closes
  122. def remember_me
  123. remember_me_for 2.weeks
  124. end
  125. def remember_me_for(time)
  126. remember_me_until time.from_now.utc
  127. end
  128. def remember_me_until(time)
  129. self.remember_token_expires_at = time
  130. self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
  131. save(:validate => false)
  132. end
  133. def forget_me
  134. self.remember_token_expires_at = nil
  135. self.remember_token = nil
  136. save(:validate => false)
  137. end
  138. # Returns true if the user has just been activated.
  139. def recently_activated?
  140. @recently_activated
  141. end
  142. def clear_recently_activated
  143. @recently_activated = false
  144. end
  145. def reset_activation_code
  146. self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
  147. end
  148. def admin?
  149. self.has_role? 'admin'
  150. end
  151. alias_method :admin, :admin?
  152. def admin=(new_admin)
  153. if(new_admin)
  154. self.has_role 'admin'
  155. else
  156. self.has_no_role 'admin'
  157. end
  158. end
  159. def record_contribution!(contrib_type)
  160. score = CONTRIBUTION_SCORES[contrib_type]
  161. raise "Unknown contribution type: #{contrib_type.inspect}" unless score
  162. transaction do
  163. lock!
  164. self.contribution_points = (contribution_points || 0) + score
  165. self.recent_contribution_points = (recent_contribution_points || 0) + score
  166. save!
  167. end
  168. end
  169. def recalculate_contribution_points
  170. self.contribution_points = (
  171. CONTRIBUTION_SCORES[:idea] * ideas.recent_visible(:limit => nil).count +
  172. CONTRIBUTION_SCORES[:comment] * comments.recent_visible(:limit => nil).count +
  173. CONTRIBUTION_SCORES[:vote] * votes.count)
  174. end
  175. def linked_to_twitter?
  176. !(twitter_token.blank? || twitter_secret.blank? || twitter_handle.blank?)
  177. end
  178. def twitter_is_only_auth_method?
  179. linked_to_twitter? && !linked_to_facebook? && crypted_password.blank?
  180. end
  181. def unlink_twitter
  182. self.twitter_token = self.twitter_secret = self.twitter_handle = nil
  183. self.tweet_ideas = false
  184. end
  185. def linked_to_facebook?
  186. !(facebook_uid.blank? || facebook_access_token.blank?)
  187. end
  188. def facebook_is_only_auth_method?
  189. linked_to_facebook? && !linked_to_twitter? && crypted_password.blank?
  190. end
  191. def unlink_facebook
  192. self.facebook_uid = self.facebook_access_token = self.facebook_name = nil
  193. self.facebook_post_ideas = false
  194. end
  195. def count_votes
  196. votes.each { |vote| vote.count! } # Only affects votes not already counted
  197. end
  198. protected
  199. # before filter
  200. def encrypt_password
  201. return if password.blank?
  202. self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{email}--") if new_record?
  203. self.crypted_password = encrypt(password)
  204. end
  205. def password_required?
  206. return true unless password_confirmation.blank?
  207. return false if linked_to_twitter? || linked_to_facebook?
  208. crypted_password.blank? || !password.blank? || !password_confirmation.blank?
  209. end
  210. def password_confirmation_required?
  211. !password.blank?
  212. end
  213. def registered
  214. self.deleted_at = nil
  215. reset_activation_code unless linked_to_twitter? || linked_to_facebook?
  216. save!
  217. end
  218. def do_delete
  219. self.deleted_at = Time.now.utc
  220. end
  221. def do_activate
  222. @recently_activated = true
  223. self.activated_at = Time.now.utc
  224. self.deleted_at = self.activation_code = nil
  225. end
  226. def assign_postal_code
  227. self.postal_code = PostalCode.find_by_text(zip_code)
  228. end
  229. end