2013-03-15 04:22:31 +00:00
include Devise :: Models
2012-08-06 03:01:00 +00:00
module JamRuby
class User < ActiveRecord :: Base
2013-03-15 04:22:31 +00:00
#devise: for later: :trackable
2013-05-31 01:59:37 +00:00
devise :database_authenticatable ,
2013-05-14 19:02:22 +00:00
:recoverable , :rememberable
2012-08-18 18:48:43 +00:00
2013-03-15 04:22:31 +00:00
2013-05-31 01:59:37 +00:00
attr_accessible :first_name , :last_name , :email , :city , :password , :password_confirmation , :state , :country , :subscribe_email , :terms_of_service , :original_fpfile , :cropped_fpfile , :cropped_s3_path , :photo_url , :crop_selection
2013-05-14 19:02:22 +00:00
# updating_password corresponds to a lost_password
2013-05-31 01:59:37 +00:00
attr_accessor :updating_password , :updating_email , :updated_email , :update_email_confirmation_url , :administratively_created , :current_password , :setting_password , :confirm_current_password , :updating_avatar
2012-11-07 13:10:41 +00:00
2012-11-13 07:40:06 +00:00
# authorizations (for facebook, etc -- omniauth)
2012-11-13 21:21:04 +00:00
has_many :user_authorizations , :class_name = > " JamRuby::UserAuthorization "
2012-11-13 02:52:05 +00:00
2012-10-29 10:45:47 +00:00
# connections (websocket-gateway)
2012-10-02 05:02:02 +00:00
has_many :connections , :class_name = > " JamRuby::Connection "
2012-10-01 21:27:32 +00:00
2012-10-29 10:45:47 +00:00
# friend requests
2012-10-14 02:18:20 +00:00
has_many :friend_requests , :class_name = > " JamRuby::FriendRequest "
2012-10-29 10:45:47 +00:00
# instruments
2012-11-21 19:48:39 +00:00
has_many :musician_instruments , :class_name = > " JamRuby::MusicianInstrument "
2012-10-30 05:42:16 +00:00
has_many :instruments , :through = > :musician_instruments , :class_name = > " JamRuby::Instrument "
2012-11-07 13:10:41 +00:00
2012-10-29 10:45:47 +00:00
# bands
2012-11-21 19:48:39 +00:00
has_many :band_musicians , :class_name = > " JamRuby::BandMusician "
2012-10-30 05:42:16 +00:00
has_many :bands , :through = > :band_musicians , :class_name = > " JamRuby::Band "
2012-10-14 02:18:20 +00:00
2012-11-16 02:08:37 +00:00
# recordings
2013-01-22 22:03:23 +00:00
has_many :owned_recordings , :class_name = > " JamRuby::Recording "
2013-04-25 06:50:52 +00:00
has_many :recordings , :through = > :claimed_recordings , :class_name = > " JamRuby::Recording "
has_many :claimed_recordings , :class_name = > " JamRuby::ClaimedRecording " , :inverse_of = > :user
2012-11-16 02:08:37 +00:00
2012-12-04 03:39:57 +00:00
# user likers (a musician has likers and may have likes too; fans do not have likers)
2012-12-17 06:01:48 +00:00
has_many :likers , :class_name = > " JamRuby::UserLiker " , :foreign_key = > " user_id " , :inverse_of = > :user
2012-12-04 03:39:57 +00:00
has_many :inverse_likers , :through = > :likers , :class_name = > " JamRuby::User " , :foreign_key = > " liker_id "
2012-11-03 13:54:55 +00:00
2012-12-04 03:39:57 +00:00
# user likes (fans and musicians have likes)
2012-12-17 06:01:48 +00:00
has_many :likes , :class_name = > " JamRuby::UserLike " , :foreign_key = > " liker_id " , :inverse_of = > :user
2012-12-04 03:39:57 +00:00
has_many :inverse_likes , :through = > :followings , :class_name = > " JamRuby::User " , :foreign_key = > " user_id "
2012-11-04 13:33:51 +00:00
2012-12-04 03:39:57 +00:00
# band likes
2012-12-17 06:01:48 +00:00
has_many :band_likes , :class_name = > " JamRuby::BandLiker " , :foreign_key = > " liker_id " , :inverse_of = > :user
2012-12-04 03:39:57 +00:00
has_many :inverse_band_likes , :through = > :band_likes , :class_name = > " JamRuby::Band " , :foreign_key = > " band_id "
2012-12-17 06:01:48 +00:00
# followers
2013-04-27 03:24:13 +00:00
has_many :user_followers , :class_name = > " JamRuby::UserFollower " , :foreign_key = > " user_id "
has_many :followers , :through = > :user_followers , :class_name = > " JamRuby::User "
has_many :inverse_user_followers , :through = > :followers , :class_name = > " JamRuby::UserFollower " , :foreign_key = > " follower_id "
has_many :inverse_followers , :through = > :inverse_user_followers , :source = > :user , :class_name = > " JamRuby::User "
2012-12-17 06:01:48 +00:00
# user followings
2013-04-27 03:24:13 +00:00
has_many :user_followings , :class_name = > " JamRuby::UserFollowing " , :foreign_key = > " follower_id "
has_many :followings , :through = > :user_followings , :class_name = > " JamRuby::User "
has_many :inverse_user_followings , :through = > :followings , :class_name = > " JamRuby::UserFollowing " , :foreign_key = > " user_id "
has_many :inverse_followings , :through = > :inverse_user_followings , :source = > :user , :class_name = > " JamRuby::User "
2012-12-17 06:01:48 +00:00
# band followings
2013-04-28 19:06:17 +00:00
has_many :b_followings , :class_name = > " JamRuby::BandFollowing " , :foreign_key = > " follower_id "
has_many :band_followings , :through = > :b_followings , :class_name = > " JamRuby::Band "
has_many :inverse_b_followings , :through = > :band_followings , :class_name = > " JamRuby::BandFollowing " , :foreign_key = > " band_id "
has_many :inverse_band_followings , :through = > :inverse_band_followings , :source = > :band , :class_name = > " JamRuby::Band "
2012-12-17 06:01:48 +00:00
2013-03-31 18:07:46 +00:00
# notifications
has_many :notifications , :class_name = > " JamRuby::Notification " , :foreign_key = > " target_user_id "
has_many :inverse_notifications , :through = > :notifications , :class_name = > " JamRuby::User "
2012-10-29 10:45:47 +00:00
# friends
2012-10-26 10:33:39 +00:00
has_many :friendships , :class_name = > " JamRuby::Friendship " , :foreign_key = > " user_id "
has_many :friends , :through = > :friendships , :class_name = > " JamRuby::User "
2012-10-01 21:27:32 +00:00
has_many :inverse_friendships , :class_name = > " JamRuby::Friendship " , :foreign_key = > " friend_id "
2012-10-26 10:33:39 +00:00
has_many :inverse_friends , :through = > :inverse_friendships , :source = > :user , :class_name = > " JamRuby::User "
2012-11-03 19:32:27 +00:00
# connections / music sessions
2012-10-03 03:50:23 +00:00
has_many :created_music_sessions , :foreign_key = > " user_id " , :inverse_of = > :user , :class_name = > " JamRuby::MusicSession " # sessions *created* by the user
2012-11-02 06:51:52 +00:00
has_many :music_sessions , :through = > :connections , :class_name = > " JamRuby::MusicSession "
2012-10-26 10:33:39 +00:00
2012-11-04 03:02:11 +00:00
# invitations
2012-10-26 10:33:39 +00:00
has_many :received_invitations , :foreign_key = > " receiver_id " , :inverse_of = > :receiver , :class_name = > " JamRuby::Invitation "
has_many :sent_invitations , :foreign_key = > " sender_id " , :inverse_of = > :sender , :class_name = > " JamRuby::Invitation "
2012-11-07 13:10:41 +00:00
2012-11-25 19:37:54 +00:00
# fan invitations
2012-11-16 02:50:03 +00:00
has_many :received_fan_invitations , :foreign_key = > " receiver_id " , :inverse_of = > :receiver , :class_name = > " JamRuby::FanInvitation "
has_many :sent_fan_invitations , :foreign_key = > " sender_id " , :inverse_of = > :sender , :class_name = > " JamRuby::FanInvitation "
2012-11-24 18:22:44 +00:00
# band invitations
has_many :received_band_invitations , :inverse_of = > :receiver , :foreign_key = > " user_id " , :class_name = > " JamRuby::BandInvitation "
has_many :sent_band_invitations , :inverse_of = > :sender , :foreign_key = > " creator_id " , :class_name = > " JamRuby::BandInvitation "
2013-01-06 20:46:48 +00:00
# session history
has_many :music_session_histories , :foreign_key = > " user_id " , :class_name = > " JamRuby::MusicSessionHistory "
2013-01-15 02:13:45 +00:00
# saved tracks
2013-01-22 19:15:52 +00:00
has_many :recorded_tracks , :foreign_key = > " user_id " , :class_name = > " JamRuby::RecordedTrack " , :inverse_of = > :user
2013-01-15 02:13:45 +00:00
2013-03-15 04:22:31 +00:00
# invited users
has_many :invited_users , :foreign_key = > " sender_id " , :class_name = > " JamRuby::InvitedUser "
2012-11-09 06:51:17 +00:00
# This causes the authenticate method to be generated (among other stuff)
2013-03-15 04:22:31 +00:00
#has_secure_password
2012-08-06 03:01:00 +00:00
before_save { | user | user . email = email . downcase }
2012-12-09 04:05:54 +00:00
before_save :create_remember_token , :if = > :should_validate_password?
2013-05-31 01:59:37 +00:00
before_save :stringify_avatar_info , :if = > :updating_avatar
2012-11-03 15:38:00 +00:00
2013-03-15 04:22:31 +00:00
validates :first_name , presence : true , length : { maximum : 50 }
validates :last_name , presence : true , length : { maximum : 50 }
2012-08-06 03:01:00 +00:00
VALID_EMAIL_REGEX = / \ A[ \ w+ \ -.]+@[a-z \ d \ -.]+ \ .[a-z]+ \ z /i
validates :email , presence : true , format : { with : VALID_EMAIL_REGEX } ,
uniqueness : { case_sensitive : false }
2013-05-13 03:27:12 +00:00
validates :update_email , presence : true , format : { with : VALID_EMAIL_REGEX } ,
2013-05-10 12:10:33 +00:00
uniqueness : { case_sensitive : false } , :if = > :updating_email
2012-08-06 03:01:00 +00:00
2013-06-22 02:28:42 +00:00
2013-05-14 19:02:22 +00:00
validates_length_of :password , minimum : 6 , maximum : 100 , :if = > :should_validate_password?
2012-10-07 04:57:23 +00:00
validates_presence_of :password_confirmation , :if = > :should_validate_password?
validates_confirmation_of :password , :if = > :should_validate_password?
2013-05-14 19:02:22 +00:00
2013-03-15 04:22:31 +00:00
validates :terms_of_service , :acceptance = > { :accept = > true , :on = > :create , :allow_nil = > false }
validates :subscribe_email , :inclusion = > { :in = > [ nil , true , false ] }
2013-06-22 02:28:42 +00:00
validates :musician , :inclusion = > { :in = > [ true , false ] }
2013-03-15 04:22:31 +00:00
validate :validate_musician_instruments
2013-05-14 19:02:22 +00:00
validate :validate_current_password
validate :validate_update_email
2013-03-15 04:22:31 +00:00
2013-06-22 02:28:42 +00:00
2013-05-31 01:59:37 +00:00
validate :validate_avatar_info
2013-03-15 04:22:31 +00:00
def validate_musician_instruments
errors . add ( :musician_instruments , ValidationMessages :: INSTRUMENT_MINIMUM_NOT_MET ) if ! administratively_created && musician && musician_instruments . length == 0
errors . add ( :musician_instruments , ValidationMessages :: INSTRUMENT_LIMIT_EXCEEDED ) if ! administratively_created && musician && musician_instruments . length > 5
end
2013-05-14 19:02:22 +00:00
def validate_current_password
2013-05-10 12:10:33 +00:00
# checks if the user put in their current password (used when changing your email, for instance)
2013-05-14 19:02:22 +00:00
errors . add ( :current_password , ValidationMessages :: NOT_YOUR_PASSWORD ) if should_confirm_existing_password? && ! valid_password? ( self . current_password )
2013-05-10 12:10:33 +00:00
end
2013-05-14 19:02:22 +00:00
def validate_update_email
2013-05-13 03:27:12 +00:00
if updating_email && self . update_email == self . email
errors . add ( :update_email , ValidationMessages :: EMAIL_MATCHES_CURRENT )
elsif updating_email && User . find_by_email ( self . update_email ) != nil
errors . add ( :update_email , ValidationMessages :: EMAIL_ALREADY_TAKEN )
end
2013-05-10 12:10:33 +00:00
end
2012-08-29 13:21:30 +00:00
2013-05-31 01:59:37 +00:00
def validate_avatar_info
if updating_avatar
# we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io)
errors . add ( :original_fpfile , ValidationMessages :: INVALID_FPFILE ) if self . original_fpfile . nil? || self . original_fpfile [ " key " ] . nil? || self . original_fpfile [ " url " ] . nil?
errors . add ( :cropped_fpfile , ValidationMessages :: INVALID_FPFILE ) if self . cropped_fpfile . nil? || self . cropped_fpfile [ " key " ] . nil? || self . cropped_fpfile [ " url " ] . nil?
end
end
2012-10-14 02:18:20 +00:00
def online
2012-11-09 06:29:05 +00:00
@online || = ! self . connections . nil? && self . connections . size > 0
2012-10-14 02:18:20 +00:00
end
2012-11-18 02:59:59 +00:00
def name
return " #{ first_name } #{ last_name } "
end
2012-11-07 13:10:41 +00:00
def location
2013-01-06 12:34:16 +00:00
loc = self . city . blank? ? '' : self . city
loc = loc . blank? ? self . state : " #{ loc } , #{ self . state } " unless self . state . blank?
2013-03-03 00:40:58 +00:00
#loc = loc.blank? ? self.country : "#{loc}, #{self.country}" unless self.country.blank?
2013-01-06 12:34:16 +00:00
loc
end
def location = location_hash
unless location_hash . blank?
self . city = location_hash [ :city ]
self . state = location_hash [ :state ]
self . country = location_hash [ :country ]
end if self . city . blank?
2012-11-07 13:10:41 +00:00
end
2013-03-15 04:22:31 +00:00
def musician?
return musician
end
2012-10-07 04:57:23 +00:00
def should_validate_password?
2013-03-15 04:22:31 +00:00
( updating_password || new_record? )
2013-03-01 13:35:50 +00:00
end
2013-05-10 12:10:33 +00:00
def should_confirm_existing_password?
2013-05-14 19:02:22 +00:00
confirm_current_password
2013-05-10 12:10:33 +00:00
end
2013-03-01 13:35:50 +00:00
def end_user_created?
return ! administratively_created
2012-10-07 04:57:23 +00:00
end
2012-08-26 18:28:08 +00:00
2012-10-07 18:02:26 +00:00
def friends? ( user )
return self . friends . exists? ( user )
end
2012-11-06 04:47:50 +00:00
def friend_count
return self . friends . size
end
2012-12-04 03:39:57 +00:00
def liker_count
2012-12-17 07:02:20 +00:00
return self . likers . size
end
def like_count
return self . likes . size
end
def band_like_count
return self . band_likes . size
2012-12-04 03:39:57 +00:00
end
2012-11-06 04:47:50 +00:00
def follower_count
return self . followers . size
end
def following_count
2012-12-17 07:02:20 +00:00
return self . followings . size
end
def band_following_count
return self . band_followings . size
2012-11-06 04:47:50 +00:00
end
2012-12-04 03:39:57 +00:00
def recording_count
return self . recordings . size
end
def session_count
return self . music_sessions . size
end
def confirm_email!
2012-12-09 04:05:54 +00:00
self . email_confirmed = true
end
def my_session_settings
unless self . session_settings . nil?
return JSON . parse ( self . session_settings )
else
return " "
end
2012-12-04 03:39:57 +00:00
end
2013-01-06 20:46:48 +00:00
def session_history ( user_id , band_id = nil , genre = nil )
return MusicSessionHistory . index ( self , user_id , band_id , genre )
end
def session_user_history ( user_id , session_id )
return MusicSessionUserHistory . where ( " music_session_id=' #{ session_id } ' " )
end
2013-06-24 21:31:40 +00:00
# always returns a non-null value for photo-url,
# using the generic avatar if no user photo available
def resolved_photo_url
if self . photo_url == nil || self . photo_url == ''
# lame that this isn't environment, but boy this is hard to pass all the way down from jam-web!
" http://www.jamkazam.com/assets/shared/avatar_generic.png "
else
return self . photo_url
end
end
2012-10-07 04:57:23 +00:00
def to_s
return email unless email . nil?
2012-11-15 03:24:30 +00:00
if ! first_name . nil? && ! last_name . nil?
return first_name + ' ' + last_name
end
2012-10-07 04:57:23 +00:00
return id
2012-08-29 13:21:30 +00:00
end
2012-12-14 03:32:23 +00:00
def set_password ( old_password , new_password , new_password_confirmation )
2013-05-14 19:02:22 +00:00
# so that UserObserver knows to send a confirmation email on success
self . setting_password = true
# so that should_validate_password? fires
self . updating_password = true
attributes = { :password = > new_password , :password_confirmation = > new_password_confirmation }
# taken liberally from Devise::DatabaseAuthenticatable.update_with_password
if valid_password? ( old_password )
update_attributes ( attributes )
else
self . assign_attributes ( attributes )
self . valid?
2013-05-14 22:33:02 +00:00
self . errors . add ( :current_password , old_password . blank? ? :blank : :invalid )
2013-05-14 19:02:22 +00:00
end
#clean_up_passwords
2012-12-22 00:56:16 +00:00
end
def self . set_password_from_token ( email , token , new_password , new_password_confirmation )
user = User . find_by_email ( email )
if user . nil? || user . reset_password_token != token || Time . now - user . reset_password_token_created > 3 . days
raise JamRuby :: JamArgumentError
end
user . reset_password_token = nil
user . reset_password_token_created = nil
user . change_password ( new_password , new_password_confirmation )
user . save
end
def change_password ( new_password , new_password_confirmation )
2012-12-14 03:32:23 +00:00
# FIXME: Should verify that the new password meets certain quality criteria. Really, maybe that should be a
# verification step.
2012-12-22 00:56:16 +00:00
self . updating_password = true
2012-12-14 03:32:23 +00:00
self . password = new_password
self . password_confirmation = new_password_confirmation
2012-12-14 09:16:54 +00:00
UserMailer . password_changed ( self ) . deliver
2012-12-13 17:15:47 +00:00
end
2013-06-24 21:31:40 +00:00
def self . reset_password ( email , reset_password_url )
2012-12-22 00:56:16 +00:00
user = User . find_by_email ( email )
raise JamRuby :: JamArgumentError if user . nil?
user . reset_password_token = SecureRandom . urlsafe_base64
user . reset_password_token_created = Time . now
user . save
2013-06-24 21:31:40 +00:00
UserMailer . password_reset ( user , reset_password_url ) . deliver
2012-12-28 07:30:03 +00:00
user
2012-12-22 00:56:16 +00:00
end
2012-12-17 07:02:20 +00:00
def self . band_index ( user_id )
bands = Band . joins ( :band_musicians )
. where ( :bands_musicians = > { :user_id = > " #{ user_id } " } )
return bands
end
def self . recording_index ( current_user , user_id )
hide_private = false
# hide private recordings from anyone but the current user
if current_user . id != user_id
hide_private = true
end
if hide_private
recordings = Recording . joins ( :musician_recordings )
. where ( :musicians_recordings = > { :user_id = > " #{ user_id } " } , :public = > true )
else
recordings = Recording . joins ( :musician_recordings )
. where ( :musicians_recordings = > { :user_id = > " #{ user_id } " } )
end
return recordings
end
2012-12-13 17:15:47 +00:00
2013-03-15 04:22:31 +00:00
def easy_save ( first_name , last_name , email , password , password_confirmation , musician , gender ,
birth_date , internet_service_provider , city , state , country , instruments , photo_url )
2012-11-22 08:27:23 +00:00
2012-11-11 04:23:38 +00:00
# first name
2012-11-21 19:48:39 +00:00
unless first_name . nil?
2013-03-15 04:22:31 +00:00
self . first_name = first_name
2012-11-11 04:23:38 +00:00
end
# last name
2012-11-21 19:48:39 +00:00
unless last_name . nil?
2013-03-15 04:22:31 +00:00
self . last_name = last_name
2012-11-11 04:23:38 +00:00
end
2012-11-03 13:54:55 +00:00
# email
2013-05-10 12:10:33 +00:00
# !! Email is changed in a dedicated method, 'update_email'
#unless email.nil?
# self.email = email
#end
2012-11-03 13:54:55 +00:00
# password
2012-11-21 19:48:39 +00:00
unless password . nil?
2013-03-15 04:22:31 +00:00
self . password = password
2012-10-29 10:45:47 +00:00
end
2012-11-03 13:54:55 +00:00
# password confirmation
2012-11-21 19:48:39 +00:00
unless password_confirmation . nil?
2013-03-15 04:22:31 +00:00
self . password_confirmation = password_confirmation
2012-11-03 13:54:55 +00:00
end
# musician flag
2012-11-21 19:48:39 +00:00
unless musician . nil?
2013-03-15 04:22:31 +00:00
self . musician = musician
2012-11-03 13:54:55 +00:00
end
2012-11-13 02:52:05 +00:00
# gender
2012-11-21 19:48:39 +00:00
unless gender . nil?
2013-03-15 04:22:31 +00:00
self . gender = gender
2012-11-13 02:52:05 +00:00
end
# birthdate
2012-11-21 19:48:39 +00:00
unless birth_date . nil?
2013-03-15 04:22:31 +00:00
self . birth_date = birth_date
2012-11-13 02:52:05 +00:00
end
# ISP
2012-11-21 19:48:39 +00:00
unless internet_service_provider . nil?
2013-03-15 04:22:31 +00:00
self . internet_service_provider = internet_service_provider
2012-11-13 02:52:05 +00:00
end
2012-11-06 02:55:08 +00:00
# city
2012-11-21 19:48:39 +00:00
unless city . nil?
2013-03-15 04:22:31 +00:00
self . city = city
2012-11-06 02:55:08 +00:00
end
# state
2012-11-21 19:48:39 +00:00
unless state . nil?
2013-03-15 04:22:31 +00:00
self . state = state
2012-11-06 02:55:08 +00:00
end
# country
2012-11-21 19:48:39 +00:00
unless country . nil?
2013-03-15 04:22:31 +00:00
self . country = country
2012-11-06 02:55:08 +00:00
end
2012-11-03 13:54:55 +00:00
# instruments
2012-11-21 19:48:39 +00:00
unless instruments . nil?
UserManager . active_record_transaction do | user_manager |
2012-11-03 13:54:55 +00:00
# delete all instruments for this user first
2013-03-15 04:22:31 +00:00
unless self . new_record?
MusicianInstrument . delete_all ( [ " user_id = ? " , self . id ] )
2012-11-03 19:32:27 +00:00
end
2012-11-03 13:54:55 +00:00
# loop through each instrument in the array and save to the db
2012-11-25 19:37:54 +00:00
instruments . each do | musician_instrument_param |
instrument = Instrument . find ( musician_instrument_param [ :instrument_id ] )
musician_instrument = MusicianInstrument . new
2013-03-15 04:22:31 +00:00
musician_instrument . user = self
2012-11-25 19:37:54 +00:00
musician_instrument . instrument = instrument
musician_instrument . proficiency_level = musician_instrument_param [ :proficiency_level ]
musician_instrument . priority = musician_instrument_param [ :priority ]
musician_instrument . save
2013-03-15 04:22:31 +00:00
self . musician_instruments << musician_instrument
2012-11-03 13:54:55 +00:00
end
end
2012-10-29 10:45:47 +00:00
end
2012-11-03 13:54:55 +00:00
2012-11-28 05:26:53 +00:00
# photo url
unless photo_url . nil?
2013-03-15 04:22:31 +00:00
self . photo_url = photo_url
2012-11-28 05:26:53 +00:00
end
2013-03-15 04:22:31 +00:00
self . updated_at = Time . now . getutc
self . save
end
# helper method for creating / updating a User
def self . save ( id , updater_id , first_name , last_name , email , password , password_confirmation , musician , gender ,
birth_date , internet_service_provider , city , state , country , instruments , photo_url )
if id . nil?
user = User . new ( )
else
user = User . find ( id )
end
if user . id != updater_id
raise PermissionError , ValidationMessages :: PERMISSION_VALIDATION_ERROR
end
user . easy_save ( first_name , last_name , email , password , password_confirmation , musician , gender ,
birth_date , internet_service_provider , city , state , country , instruments , photo_url )
2012-10-29 10:45:47 +00:00
return user
end
2013-05-14 19:02:22 +00:00
def begin_update_email ( email , current_password , confirmation_url )
2013-05-10 12:10:33 +00:00
# sets the user model in a state such that it's expecting to have it's email updated
# two columns matter for this; 'update_email_token' and 'update_email'
# confirmation_link is odd in the sense that it can likely only come from www.jamkazam.com (jam-web)
# an observer should be set up to send an email based on this activity
2013-05-14 19:02:22 +00:00
self . updating_email = self . confirm_current_password = true
self . current_password = current_password
2013-05-10 12:10:33 +00:00
self . update_email = email
self . update_email_token = SecureRandom . urlsafe_base64
self . update_email_confirmation_url = " #{ confirmation_url } #{ self . update_email_token } "
self . save
end
def self . finalize_update_email ( update_email_token )
# updates the user model to have a new email address
user = User . find_by_update_email_token! ( update_email_token )
user . updated_email = true
user . email = user . update_email
user . update_email_token = nil
user . save
return user
end
2012-12-17 06:01:48 +00:00
def self . create_user_like ( user_id , liker_id )
liker = UserLiker . new ( )
liker . user_id = user_id
liker . liker_id = liker_id
liker . save
end
def self . delete_like ( user_id , band_id , liker_id )
if ! user_id . nil?
JamRuby :: UserLiker . delete_all " (user_id = ' #{ user_id } ' AND liker_id = ' #{ liker_id } ') "
elsif ! band_id . nil?
JamRuby :: BandLiker . delete_all " (band_id = ' #{ band_id } ' AND liker_id = ' #{ liker_id } ') "
end
end
def self . create_band_like ( band_id , liker_id )
liker = BandLiker . new ( )
liker . band_id = band_id
liker . liker_id = liker_id
liker . save
end
def self . delete_band_like ( band_id , liker_id )
JamRuby :: BandLiker . delete_all " (band_id = ' #{ band_id } ' AND liker_id = ' #{ liker_id } ') "
end
2012-11-21 19:48:39 +00:00
def self . create_user_following ( user_id , follower_id )
2012-11-22 08:27:23 +00:00
follower = UserFollower . new ( )
follower . user_id = user_id
follower . follower_id = follower_id
follower . save
2012-11-21 19:48:39 +00:00
end
2012-12-04 03:39:57 +00:00
def self . delete_following ( user_id , band_id , follower_id )
if ! user_id . nil?
JamRuby :: UserFollower . delete_all " (user_id = ' #{ user_id } ' AND follower_id = ' #{ follower_id } ') "
elsif ! band_id . nil?
JamRuby :: BandFollower . delete_all " (band_id = ' #{ band_id } ' AND follower_id = ' #{ follower_id } ') "
end
2012-11-21 19:48:39 +00:00
end
def self . create_band_following ( band_id , follower_id )
2012-11-22 08:27:23 +00:00
follower = BandFollower . new ( )
follower . band_id = band_id
follower . follower_id = follower_id
follower . save
2012-11-21 19:48:39 +00:00
end
def self . delete_band_following ( band_id , follower_id )
JamRuby :: BandFollower . delete_all " (band_id = ' #{ band_id } ' AND follower_id = ' #{ follower_id } ') "
end
def self . create_favorite ( user_id , recording_id )
2012-11-22 08:27:23 +00:00
favorite = UserFavorite . new ( )
favorite . user_id = user_id
favorite . recording_id = recording_id
favorite . save
2012-11-21 19:48:39 +00:00
end
def self . delete_favorite ( user_id , recording_id )
JamRuby :: UserFavorite . delete_all " (user_id = ' #{ user_id } ' AND recording_id = ' #{ recording_id } ') "
end
2012-12-09 04:05:54 +00:00
def self . save_session_settings ( user , music_session )
unless user . nil?
2012-12-10 05:53:21 +00:00
# only save genre id and description
genres = [ ]
unless music_session . genres . nil?
music_session . genres . each do | genre |
g = Hash . new
g [ " id " ] = genre . id
g [ " description " ] = genre . description
genres << g
end
end
# only save invitation receiver id and name
invitees = [ ]
unless music_session . invitations . nil?
music_session . invitations . each do | invitation |
i = Hash . new
i [ " id " ] = invitation . receiver . id
i [ " name " ] = invitation . receiver . name
invitees << i
end
end
2012-12-09 04:05:54 +00:00
session_settings = { :band_id = > music_session . band_id ,
:musician_access = > music_session . musician_access ,
:approval_required = > music_session . approval_required ,
:fan_chat = > music_session . fan_chat ,
:fan_access = > music_session . fan_access ,
:description = > music_session . description ,
2012-12-10 05:53:21 +00:00
:genres = > genres ,
:invitees = > invitees
2012-12-09 04:05:54 +00:00
} . to_json
user . session_settings = session_settings
user . save
end
end
2012-11-21 19:48:39 +00:00
# throws ActiveRecord::RecordNotFound if instrument is invalid
# throws an email delivery error if unable to connect out to SMTP
2013-03-15 04:22:31 +00:00
def self . signup ( first_name , last_name , email , password , password_confirmation , terms_of_service , subscribe_email ,
2013-06-22 02:28:42 +00:00
location , instruments , birth_date , musician , photo_url , invited_user , signup_confirm_url )
2012-11-21 19:48:39 +00:00
user = User . new
2012-11-07 13:10:41 +00:00
2012-11-21 19:48:39 +00:00
UserManager . active_record_transaction do | user_manager |
user . first_name = first_name
user . last_name = last_name
user . email = email
2013-03-15 04:22:31 +00:00
user . subscribe_email = subscribe_email
user . terms_of_service = terms_of_service
2013-06-22 02:28:42 +00:00
user . musician = musician
2012-11-21 19:48:39 +00:00
2013-03-15 04:22:31 +00:00
# FIXME: Setting random password for social network logins. This
2012-11-21 19:48:39 +00:00
# is because we have validations all over the place on this.
# The right thing would be to have this null
2013-03-15 04:22:31 +00:00
# Seth: I think we need a flag in the signature of signup to say 'social_signup=true'. If that flag is set,
# then you can do use.updating_password = false and instead set a null password
2012-11-21 19:48:39 +00:00
if password . nil?
2013-03-15 04:22:31 +00:00
user . password = user . password_confirmation = SecureRandom . urlsafe_base64
2012-11-21 19:48:39 +00:00
else
user . password = password
user . password_confirmation = password_confirmation
end
2012-11-14 05:37:18 +00:00
2012-11-21 19:48:39 +00:00
user . admin = false
2013-03-15 04:22:31 +00:00
user . city = location [ :city ]
user . state = location [ :state ]
user . country = location [ :country ]
user . birth_date = birth_date
2013-06-22 02:28:42 +00:00
if user . musician # only update instruments if the user is a musician
unless instruments . nil?
instruments . each do | musician_instrument_param |
instrument = Instrument . find ( musician_instrument_param [ :instrument_id ] )
musician_instrument = MusicianInstrument . new
musician_instrument . user = user
musician_instrument . instrument = instrument
musician_instrument . proficiency_level = musician_instrument_param [ :proficiency_level ]
musician_instrument . priority = musician_instrument_param [ :priority ]
user . musician_instruments << musician_instrument
end
2012-11-21 19:48:39 +00:00
end
end
2012-11-28 05:26:53 +00:00
user . photo_url = photo_url
2012-11-15 09:30:55 +00:00
2013-03-15 04:22:31 +00:00
if invited_user . nil?
user . can_invite = Limits :: USERS_CAN_INVITE
user . email_confirmed = false
user . signup_token = SecureRandom . urlsafe_base64
else
# if you are invited by an admin, we'll say you can invite too.
# but if not, then you can not invite
user . can_invite = invited_user . invited_by_administrator?
# if you came in from an invite and used the same email to signup,
# then we know you are a real human and that your email is valid.
# lucky! we'll log you in immediately
if invited_user . email . casecmp ( user . email ) . zero?
user . email_confirmed = true
user . signup_token = nil
else
user . email_confirmed = false
user . signup_token = SecureRandom . urlsafe_base64
end
# now that the user is saved, let's
if invited_user . autofriend && ! invited_user . sender . nil?
# hookup this user with the sender
Friendship . save_using_models ( user , invited_user . sender )
end
invited_user . accept!
invited_user . save
if invited_user . errors . any?
raise ActiveRecord :: Rollback
end
end
2013-01-04 10:13:39 +00:00
2012-11-21 19:48:39 +00:00
user . save
2012-11-15 09:30:55 +00:00
2012-11-21 19:48:39 +00:00
if user . errors . any?
raise ActiveRecord :: Rollback
else
2013-03-15 04:22:31 +00:00
# don't send an signup email if the user was invited already *and* they used the same email that they were invited with
if ! invited_user . nil? && invited_user . email . casecmp ( user . email ) . zero?
else
# FIXME:
# It's not standard to require a confirmation when a user signs up with Facebook.
# We should stop asking for it.
#
# any errors here should also rollback the transaction; that's OK. If emails aren't going to be delivered,
# it's already a really bad situation; make user signup again
UserMailer . welcome_message ( user , signup_confirm_url . nil? ? nil : ( signup_confirm_url + " / " + user . signup_token ) ) . deliver
end
2012-11-14 05:37:18 +00:00
end
end
2012-11-21 19:48:39 +00:00
return user
end
2012-11-14 05:37:18 +00:00
2012-12-09 20:56:35 +00:00
# this is intended to be development-mode or test-mode only; VRFS-149
# it creates or updates one user per developer, so that we aren't in the business
# of constantly recreating users as we create new dev environments
# We guard against this code running in production mode,
# because otherwise it's a bit of uncomfortable code
# to have sitting around
def self . create_dev_user ( first_name , last_name , email , password ,
city , state , country , instruments , photo_url )
if Environment . mode == " production "
# short-circuit out
return
end
user = User . find_or_create_by_email ( email )
User . transaction do
user . first_name = first_name
user . last_name = last_name
user . email = email
user . password = password
user . password_confirmation = password
user . admin = true
user . email_confirmed = true
user . musician = true
user . city = city
user . state = state
user . country = country
2013-03-15 04:22:31 +00:00
user . terms_of_service = true
2012-12-09 20:56:35 +00:00
if instruments . nil?
instruments = [ { :instrument_id = > " acoustic guitar " , :proficiency_level = > 3 , :priority = > 1 } ]
end
unless user . new_record?
MusicianInstrument . delete_all ( [ " user_id = ? " , user . id ] )
end
instruments . each do | musician_instrument_param |
instrument = Instrument . find ( musician_instrument_param [ :instrument_id ] )
musician_instrument = MusicianInstrument . new
musician_instrument . user = user
musician_instrument . instrument = instrument
musician_instrument . proficiency_level = musician_instrument_param [ :proficiency_level ]
musician_instrument . priority = musician_instrument_param [ :priority ]
user . musician_instruments << musician_instrument
end
2013-05-31 01:59:37 +00:00
if photo_url . nil?
user . photo_url = photo_url
end
2012-12-09 20:56:35 +00:00
user . signup_token = nil
user . save
if user . errors . any?
raise ActiveRecord :: Rollback
end
end
return user
end
2013-03-15 04:22:31 +00:00
def signup_confirm
self . signup_token = nil
self . confirm_email!
self . save
end
2013-05-31 01:59:37 +00:00
def update_avatar ( original_fpfile , cropped_fpfile , crop_selection , aws_bucket )
self . updating_avatar = true
cropped_s3_path = cropped_fpfile [ " key " ]
return self . update_attributes (
:original_fpfile = > original_fpfile ,
:cropped_fpfile = > cropped_fpfile ,
:cropped_s3_path = > cropped_s3_path ,
:crop_selection = > crop_selection ,
:photo_url = > S3Util . url ( aws_bucket , cropped_s3_path , :secure = > false )
)
end
def delete_avatar ( aws_bucket )
User . transaction do
unless self . cropped_s3_path . nil?
S3Util . delete ( aws_bucket , File . dirname ( self . cropped_s3_path ) + '/cropped.jpg' )
S3Util . delete ( aws_bucket , self . cropped_s3_path )
end
return self . update_attributes (
:original_fpfile = > nil ,
:cropped_fpfile = > nil ,
:cropped_s3_path = > nil ,
:photo_url = > nil ,
:crop_selection = > nil
)
end
end
2012-11-21 19:48:39 +00:00
# throws RecordNotFound if signup token is invalid; i.e., if it's nil, empty string, or not belonging to a user
def self . signup_confirm ( signup_token )
if signup_token . nil? || signup_token . empty?
# there are plenty of confirmed users with nil signup_tokens, so we can't look on it
raise ActiveRecord :: RecordNotFound
2012-11-14 05:37:18 +00:00
else
2012-11-21 19:48:39 +00:00
UserManager . active_record_transaction do | user_manager |
# throws ActiveRecord::RecordNotFound if invalid
user = User . find_by_signup_token! ( signup_token )
2013-03-15 04:22:31 +00:00
user . signup_confirm
2012-11-21 19:48:39 +00:00
return user
end
2012-11-14 05:37:18 +00:00
end
end
2012-11-21 19:48:39 +00:00
# if valid credentials are supplied for an 'active' user, returns the user
# if not authenticated, returns nil
def self . authenticate ( email , password )
2013-06-22 02:28:42 +00:00
# remove email_confirmed restriction due to VRFS-378
2012-11-21 19:48:39 +00:00
# we only allow users that have confirmed email to authenticate
2013-06-22 02:28:42 +00:00
# user = User.where('email_confirmed=true').find_by_email(email)
user = User . find_by_email ( email )
2012-11-14 05:37:18 +00:00
2013-03-15 04:22:31 +00:00
if user && user . valid_password? ( password )
2012-11-14 05:37:18 +00:00
return user
2012-11-21 19:48:39 +00:00
else
return nil
2012-11-14 05:37:18 +00:00
end
end
2013-01-14 04:50:38 +00:00
def self . search ( query , options = { :limit = > 10 } )
2012-11-14 05:37:18 +00:00
2013-01-14 04:50:38 +00:00
# only issue search if at least 2 characters are specified
if query . nil? || query . length < 2
return [ ]
2012-11-07 13:10:41 +00:00
end
2013-06-09 01:38:00 +00:00
# save query for use in instrument search
search_criteria = query
2013-01-14 04:50:38 +00:00
# create 'anded' statement
query = Search . create_tsquery ( query )
2012-11-07 13:10:41 +00:00
2013-01-14 04:50:38 +00:00
if query . nil? || query . length == 0
return [ ]
2012-11-07 13:10:41 +00:00
end
2013-06-22 02:28:42 +00:00
# remove email_confirmed restriction due to VRFS-378
# .where("email_confirmed = true AND (name_tsv @@ to_tsquery('jamenglish', ?) OR users.id in (select user_id from musicians_instruments where instrument_id like '%#{search_criteria.downcase}%'))", query)
2013-06-09 01:38:00 +00:00
return query = User
2013-06-22 02:28:42 +00:00
. where ( " (name_tsv @@ to_tsquery('jamenglish', ?) OR users.id in (select user_id from musicians_instruments where instrument_id like '% #{ search_criteria . downcase } %')) " , query )
. limit ( options [ :limit ] )
2013-01-14 04:50:38 +00:00
end
2012-11-07 13:10:41 +00:00
2013-03-15 04:22:31 +00:00
# devise compatibility
2012-11-25 19:37:54 +00:00
2013-03-15 04:22:31 +00:00
#def encrypted_password
# logger.debug("password digest returned #{self.password_digest}")
# self.password_digest
#end
2012-11-25 19:37:54 +00:00
2013-03-15 04:22:31 +00:00
#def encrypted_password=(encrypted_password)
# self.password_digest = encrypted_password
#end
2012-11-25 19:37:54 +00:00
2013-03-15 04:22:31 +00:00
# end devise compatibility
private
def create_remember_token
self . remember_token = SecureRandom . urlsafe_base64
2012-11-25 19:37:54 +00:00
end
2013-05-31 01:59:37 +00:00
def stringify_avatar_info
# fpfile comes in as a hash, which is a easy-to-use and validate form. However, we store it as a VARCHAR,
# so we need t oconvert it to JSON before storing it (otherwise it gets serialized as a ruby object)
# later, when serving this data out to the REST API, we currently just leave it as a string and make a JSON capable
# client parse it, because it's very rare when it's needed at all
self . original_fpfile = original_fpfile . to_json if ! original_fpfile . nil?
self . cropped_fpfile = cropped_fpfile . to_json if ! cropped_fpfile . nil?
self . crop_selection = crop_selection . to_json if ! crop_selection . nil?
end
2012-08-06 03:01:00 +00:00
end
2012-08-22 03:07:01 +00:00
end