require 'sanitize' class ApiUsersController < ApiController before_filter :api_signed_in_user, :except => [:create, :calendar, :show, :signup_confirm, :auth_session_create, :complete, :finalize_update_email, :isp_scoring, :add_play, :crash_dump, :validate_data, :google_auth, :user_event, :onboardings, :update_onboarding, :show_onboarding] before_filter :auth_user, :only => [:session_settings_show, :session_history_index, :session_user_history_index, :update, :delete, :authorizations, :test_drive_status, :liking_create, :liking_destroy, # likes :following_create, :following_show, :following_destroy, # followings :recording_update, :recording_destroy, # recordings :favorite_create, :favorite_destroy, # favorites :friend_request_index, :friend_request_show, :friend_request_create, :friend_request_update, # friend requests :friend_show, :friend_destroy, # friends :notification_index, :notification_destroy, # notifications :band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations :set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy, :share_session, :share_recording, :affiliate_report, :audio_latency, :broadcast_notification, :redeem_giftcard] before_filter :ip_blacklist, :only => [:create, :redeem_giftcard] respond_to :json, :except => :calendar respond_to :ics, :only => :calendar def index @users = User.paginate(page: params[:page]) respond_with @users, responder: ApiResponder, :status => 200 end def calendar #@user=lookup_user #ics = CalendarManager.new.create_ics_feed(@user) #send_data ics, :filename => 'JamKazam', :disposition => 'inline', :type => "text/calendar" render :json => {}, :status => 200 end def show @user=lookup_user @show_teacher = true @show_profile = params[:show_profile] @show_student = params[:show_student] respond_with @user, responder: ApiResponder, :status => 200 end def authorizations @user = current_user respond_with @user, responder: ApiResponder, :status => 200 end def jamblasters @user = current_user @connection = Connection.find_by_client_id(params[:client_id]) respond_with @user, responder: ApiResponder, :status => 200 end def google_auth @user = current_user respond_with @user, responder: ApiResponder, :status => 200 end def profile_show if !guard_school_same_scope(current_user, User.find(params[:id])) raise JamPermissionError, ValidationMessages::CAN_ONLY_VIEW_SAME_SCHOOL end @profile = User.includes([{musician_instruments: :instrument}, {band_musicians: :user}, {genre_players: :genre}, :bands, :instruments, :genres, :online_presences, :performance_samples]) .find(params[:id]) @show_teacher_profile = params[:show_teacher] respond_with @profile, responder: ApiResponder, :status => 200 end # in other words, a minimal signup def create # today, this only accepts a minimal registration; it could be made to take in more if we wanted signup_hint = nil if anonymous_user signup_hint = anonymous_user.signup_hint if signup_hint && signup_hint.jam_track.nil? signup_hint = nil # it doesn't make sense to pass in signup hints that are not free jam-track centric (at least, not today) end end # recaptcha_response: params['g-recaptcha-response'] # try to autologin , because users will try to log in via signup link if(params[:email] && params[:password]) test = User.authenticate(params[:email], params[:password]) if test @user = test @autologin = true @user.school_interest = !!params[:school_interest] @user.education_interest = !!params[:education_interest] @user.retailer_interest = !!params[:retailer_interest] @user.save sign_in @user new_user(@user, signup_hint) # sets a cookie used for GA analytics (one-time new user stuff in JavaScript) respond_with_model(@user, new: true, location: lambda { return api_user_detail_url(@user.id) }) return end end options = { first_name: params[:first_name], last_name: params[:last_name], email: params[:email], password: params[:password], password_confirmation: params[:password], terms_of_service: params[:terms], location: {:country => nil, :state => nil, :city => nil}, signup_hint: signup_hint, gift_card: params[:gift_card], student: params[:student], teacher: params[:teacher], school_invitation_code: params[:school_invitation_code], school_id: params[:school_id], retailer_invitation_code: params[:retailer_invitation_code], retailer_id: params[:retailer_id], school_interest: params[:school_interest], retailer_interest: params[:retailer_interest], education_interest: params[:education_interest], affiliate_referral_id: cookies[:affiliate_visitor], origin: origin_cookie, test_drive_package: params[:test_drive_package], timezone: current_timezone } options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) @user = UserManager.new.signup(options) if @user.errors.any? respond_with_model(@user) else sign_in @user new_user(@user, signup_hint) # sets a cookie used for GA analytics (one-time new user stuff in JavaScript) respond_with_model(@user, new: true, location: lambda { return api_user_detail_url(@user.id) }) end end def profile_save end def update @user = User.find(params[:id]) @user.first_name = params[:first_name] if params.has_key?(:first_name) @user.last_name = params[:last_name] if params.has_key?(:last_name) @user.gender = params[:gender] if params.has_key?(:gender) @user.birth_date = Date.strptime(params[:birth_date], '%m-%d-%Y') if (params.has_key?(:birth_date) && params[:birth_date]) @user.city = params[:city] if params.has_key?(:city) @user.state = params[:state] if params.has_key?(:state) @user.country = params[:country] if params.has_key?(:country) @user.musician = params[:musician] if params.has_key?(:musician) @user.update_instruments(params[:instruments].nil? ? [] : params[:instruments]) if params.has_key?(:instruments) # genres @user.update_genres(params[:genres].nil? ? [] : params[:genres], GenrePlayer::PROFILE) if params.has_key?(:genres) @user.update_genres(params[:virtual_band_genres].nil? ? [] : params[:virtual_band_genres], GenrePlayer::VIRTUAL_BAND) if params.has_key?(:virtual_band_genres) @user.update_genres(params[:traditional_band_genres].nil? ? [] : params[:traditional_band_genres], GenrePlayer::TRADITIONAL_BAND) if params.has_key?(:traditional_band_genres) @user.update_genres(params[:paid_session_genres].nil? ? [] : params[:paid_session_genres], GenrePlayer::PAID_SESSION) if params.has_key?(:paid_session_genres) @user.update_genres(params[:free_session_genres].nil? ? [] : params[:free_session_genres], GenrePlayer::FREE_SESSION) if params.has_key?(:free_session_genres) @user.update_genres(params[:cowriting_genres].nil? ? [] : params[:cowriting_genres], GenrePlayer::COWRITING) if params.has_key?(:cowriting_genres) @user.show_whats_next = params[:show_whats_next] if params.has_key?(:show_whats_next) @user.show_whats_next_count = params[:show_whats_next_count] if params.has_key?(:show_whats_next_count) @user.subscribe_email = params[:subscribe_email] if params.has_key?(:subscribe_email) @user.biography = params[:biography] if params.has_key?(:biography) @user.website = params[:website] if params.has_key?(:website) @user.skill_level = params[:skill_level] if params.has_key?(:skill_level) @user.concert_count = params[:concert_count] if params.has_key?(:concert_count) @user.studio_session_count = params[:studio_session_count] if params.has_key?(:studio_session_count) # virtual band @user.virtual_band = params[:virtual_band] if params.has_key?(:virtual_band) @user.virtual_band_commitment = params[:virtual_band_commitment] if params.has_key?(:virtual_band_commitment) # traditional band @user.traditional_band = params[:traditional_band] if params.has_key?(:traditional_band) @user.traditional_band_commitment = params[:traditional_band_commitment] if params.has_key?(:traditional_band_commitment) @user.traditional_band_touring = params[:traditional_band_touring] if params.has_key?(:traditional_band_touring) # paid sessions @user.paid_sessions = params[:paid_sessions] if params.has_key?(:paid_sessions) @user.paid_sessions_hourly_rate = params[:paid_sessions_hourly_rate] if params.has_key?(:paid_sessions_hourly_rate) @user.paid_sessions_daily_rate = params[:paid_sessions_daily_rate] if params.has_key?(:paid_sessions_daily_rate) # free sessions @user.free_sessions = params[:free_sessions] if params.has_key?(:free_sessions) # co-writing @user.cowriting = params[:cowriting] if params.has_key?(:cowriting) @user.cowriting_purpose = params[:cowriting_purpose] if params.has_key?(:cowriting_purpose) @user.want_jamblaster = params[:want_jamblaster] if params.has_key?(:want_jamblaster) @user.mod_merge(params[:mods]) if params[:mods] # allow keyword of 'LATEST' to mean set the notification_seen_at to the most recent notification for this user if params.has_key?(:notification_seen_at) @user.update_notification_seen_at params[:notification_seen_at] end @user.update_online_presences(params[:online_presences]) if params.has_key?(:online_presences) @user.update_performance_samples(params[:performance_samples]) if params.has_key?(:performance_samples) @user.update_calendars(params[:calendars]) if params.has_key?(:calendars) @user.is_a_student = params[:student] if params.has_key?(:student) @user.is_a_teacher = params[:teacher] if params.has_key?(:teacher) @user.school_interest = !!params[:school_interest] @user.education_interest = !!params[:education_interest] @user.retailer_interest = !!params[:retailer_interest] @user.desired_package = LessonPackageType.find_by_package_type!(params[:desired_package]) if params.has_key?(:desired_package) if @user.save test_drive_package_details = params[:test_drive_package] test_drive_package = TestDrivePackage.find_by_name(test_drive_package_details[:name]) if test_drive_package_details @user.handle_test_drive_package(test_drive_package, test_drive_package_details) if test_drive_package end if @user.errors.any? respond_with @user, :status => :unprocessable_entity else respond_with @user, responder: ApiResponder, :status => 200 end end # a user that is created administratively has an incomplete profile # when they first visit the confirmation page by clicking the link in their email. def complete signup_token = params[:signup_token] user = User.find_by_signup_token(signup_token) if user.nil? return end user.updating_password = true user.easy_save( params[:first_name], params[:last_name], nil, # email can't be edited at this phase. We need to get them into the site, and they can edit on profile page if they really want params[:password], params[:password_confirmation], true, # musician params[:gender], params[:birth_date], params[:isp], params[:city], params[:state], params[:country], params[:instruments], params[:photo_url]) if user.errors.any? render :json => user.errors.full_messages(), :status => :unprocessable_entity else # log the user in automatically user.signup_confirm sign_in(user) respond_with user, responder: ApiResponder, :status => 200 end end def delete @user.destroy respond_with responder: ApiResponder, :status => 204 end def signup_confirm @user = UserManager.new.signup_confirm(params[:signup_token]) unless @user.errors.any? respond_with @user, responder: ApiResponder, :location => api_user_detail_url(@user) else response.status = :unprocessable_entity respond_with @user, responder: ApiResponder end end def set_password @user.set_password(params[:old_password], params[:new_password], params[:new_password_confirm]) if @user.errors.any? response.status = :unprocessable_entity respond_with @user else sign_in(@user) respond_with @user, responder: ApiResponder, status: 200 end end def reset_password begin User.reset_password(params[:email], ApplicationHelper.base_uri(request)) rescue JamRuby::JamArgumentError render :json => {:message => ValidationMessages::EMAIL_NOT_FOUND}, :status => 403 end respond_with responder: ApiResponder, :status => 204 end def reset_password_token begin User.set_password_from_token(params[:email], params[:token], params[:new_password], params[:new_password_confirm]) rescue JamRuby::JamArgumentError # FIXME # There are some other errors that can happen here, besides just EMAIL_NOT_FOUND render :json => {:message => ValidationMessages::EMAIL_NOT_FOUND}, :status => 403 end set_remember_token(@user) respond_with responder: ApiResponder, :status => 204 end ###################### AUTHENTICATION ################### def auth_session_create @user = User.authenticate(params[:email], params[:password]) if @user.nil? render :json => {:success => false}, :status => 404 else sign_in @user render :json => {:success => true}, :status => 200 end end def auth_session_delete sign_out render :json => {:success => true}, :status => 200 end ###################### SESSION SETTINGS ################### def session_settings_show respond_with :json => @user.my_session_settings.to_json, responder: ApiResponder end ###################### SESSION HISTORY ################### def session_history_index @session_history = @user.session_history(params[:id], params[:band_id], params[:genre]) end def session_user_history_index @session_user_history = @user.session_user_history(params[:id], params[:session_id]) end ###################### BANDS ######################## def band_index @bands = User.band_index(params[:id]) end ###################### LIKERS ######################## def liker_index # NOTE: liker_index.rabl template references the likers property @user = User.find(params[:id]) end ###################### LIKES ######################### def liking_index @user = User.find(params[:id]) end def liking_create @user = User.find(params[:id]) if !params[:user_id].nil? @user.create_user_liking(params[:user_id]) elsif !params[:band_id].nil? @user.create_band_liking(params[:band_id]) end respond_with @user, responder: ApiResponder, :location => api_user_liking_index_url(@user) end def liking_destroy User.delete_liking(params[:id], params[:likable_id]) respond_with responder: ApiResponder, :status => 204 end ###################### FOLLOWERS ######################## def follower_index # NOTE: follower_index.rabl template references the followers property @user = User.find(params[:id]) end ###################### FOLLOWINGS ####################### def following_index @user = User.find(params[:id]) end def following_create @user = User.find(params[:id]) if !params[:user_id].nil? @user.create_user_following(params[:user_id]) elsif !params[:band_id].nil? @user.create_band_following(params[:band_id]) end respond_with @user, responder: ApiResponder, :location => api_user_following_index_url(@user) end def following_destroy User.delete_following(params[:id], params[:followable_id]) respond_with responder: ApiResponder, :status => 204 end ###################### FAVORITES ######################## def favorite_index @user = User.find(params[:id]) end def favorite_create @favorite = UserFavorite.new() User.create_favorite(params[:id], params[:recording_id]) @user = User.find(params[:id]) respond_with @user, responder: ApiResponder, :location => api_favorite_index_url(@user) end def favorite_destroy User.delete_favorite(params[:id], params[:recording_id]) respond_with responder: ApiResponder, :status => 204 end ###################### FRIENDS ########################## def friend_request_index # get all outgoing and incoming friend requests @friend_requests = FriendRequest.where("(friend_id='#{params[:id]}' AND status is null) OR user_id='#{params[:id]}'") end def friend_request_show @friend_request = FriendRequest.find(params[:friend_request_id]) raise JamRuby::JamPermissionError, 'not allowed to view someone else\'s friend request' if @friend_request.friend_id != @user.id && @friend_request.user_id != @user.id respond_with @friend_request, responder: ApiResponder, :status => 200 end def friend_request_create @friend_request = FriendRequest.save(nil, params[:id], params[:friend_id], nil, params[:message]) respond_with @friend_request, responder: ApiResponder, :status => 201, :location => api_friend_request_detail_url(@user, @friend_request) end def friend_request_update @friend_request = FriendRequest.save(params[:friend_request_id], params[:id], params[:friend_id], params[:status], nil) respond_with @friend_request, responder: ApiResponder, :status => 200 end def friend_index # NOTE: friend_index.rabl template references the friends property @user = User.find(params[:id]) end def friend_show @friend = Friendship.find_by_user_id_and_friend_id(params[:id], params[:friend_id]) end def friend_destroy if current_user.id != params[:id] && current_user.id != params[:friend_id] render :json => {:message => "You are not allowed to delete this friendship."}, :status => 403 end # clean up both records representing this "friendship" JamRuby::Friendship.delete_all "(user_id = '#{params[:id]}' AND friend_id = '#{params[:friend_id]}') OR (user_id = '#{params[:friend_id]}' AND friend_id = '#{params[:id]}')" respond_with responder: ApiResponder, :status => 204 end ###################### NOTIFICATIONS #################### def notification_index if params[:type] == 'TEXT_MESSAGE' # you can ask for just text_message notifications raise JamArgumentError.new('can\'t be blank', 'receiver') if params[:receiver].blank? raise JamArgumentError.new('can\'t be blank', 'limit') if params[:limit].blank? raise JamArgumentError.new('can\'t be blank', 'offset') if params[:offset].blank? receiver_id = params[:receiver] limit = params[:limit].to_i limit = 20 if limit <= 0 offset = params[:offset].to_i offset = 0 if offset < 0 @notifications = Notification.joins(:source_user).where(description: 'TEXT_MESSAGE').where('(source_user_id = (?) AND target_user_id = (?)) OR (source_user_id = (?) AND target_user_id = (?))', @user.id, receiver_id, receiver_id, @user.id).offset(offset).limit(limit).order('created_at DESC') else limit = params[:limit].to_i limit = 20 if limit <= 0 offset = params[:offset].to_i offset = 0 if offset < 0 @notifications = @user.notifications.joins(:source_user).offset(offset).limit(limit) end respond_with @notifications, responder: ApiResponder, :status => 200 end def notification_destroy Notification.delete(params[:notification_id]) respond_with responder: ApiResponder, :status => 204 end def notification_create @notification = Notification.send_text_message(Sanitize.fragment(params[:message], elements: HtmlSanitize::SAFE), current_user, User.find_by_id(params[:receiver])) respond_with_model(@notification, new: true) end ##################### BAND INVITATIONS ################## def band_invitation_index @invitations = @user.received_band_invitations respond_with @invitations, responder: ApiResponder, :status => 200 end def band_invitation_show begin @invitation = BandInvitation.find(params[:invitation_id]) respond_with @invitation, responder: ApiResponder, :status => 200 rescue ActiveRecord::RecordNotFound render :json => {:message => ValidationMessages::BAND_INVITATION_NOT_FOUND}, :status => 404 end end def band_invitation_update begin @invitation = BandInvitation.save(params[:invitation_id], nil, nil, nil, params[:accepted]) respond_with @invitation, responder: ApiResponder, :status => 200 rescue ActiveRecord::RecordNotFound render :json => {:message => ValidationMessages::BAND_INVITATION_NOT_FOUND}, :status => 404 end end ###################### ACCOUNT SETTINGS ################# def begin_update_email # begins email update by sending an email for the user to confirm their new email # NOTE: if you change confirm_email_link value below, you break outstanding email changes because links in user inboxes are broken confirm_email_link = confirm_email_url + "?token=" current_user.begin_update_email(params[:update_email], params[:current_password], confirm_email_link) if current_user.errors.any? respond_with current_user, status: :unprocessable_entity else respond_with current_user, responder: ApiResponder, status: 200 end end def finalize_update_email # used when the user goes to the confirmation link in their email @user = User.finalize_update_email(params[:token]) sign_in(@user) respond_with current_user, responder: ApiResponder, status: 200 end def isp_scoring data = request.body.read score = IspScoreBatch.new score.json_scoring_data = data if score.save render :text => 'scoring recorded' else render :text => "score invalid: #{score.errors.inspect}", status: 422 end end ################# AVATAR ##################### def update_avatar original_fpfile = params[:original_fpfile] cropped_fpfile = params[:cropped_fpfile] cropped_large_fpfile = params[:cropped_large_fpfile] crop_selection = params[:crop_selection] # public bucket to allow images to be available to public @user.update_avatar(original_fpfile, cropped_fpfile, cropped_large_fpfile, crop_selection, Rails.application.config.aws_bucket_public) if @user.errors.any? respond_with @user, status: :unprocessable_entity else respond_with @user, responder: ApiResponder, status: 200 end end def delete_avatar @user.delete_avatar(Rails.application.config.aws_bucket_public) if @user.errors.any? respond_with @user, status: :unprocessable_entity else respond_with @user, responder: ApiResponder, status: 204 end end def generate_filepicker_policy # generates a soon-expiring filepicker policy so that a user can only upload to their own folder in their bucket handle = params[:handle] call = 'pick,convert,store' policy = {:expiry => (DateTime.now + 5.minutes).to_i(), :call => call, #:path => 'avatars/' + @user.id + '/.*jpg' } # if the caller specifies a handle, add it to the hash unless handle.nil? start = handle.rindex('/') + 1 policy[:handle] = handle[start..-1] end policy = Base64.urlsafe_encode64(policy.to_json) digest = OpenSSL::Digest.new('sha256') signature = OpenSSL::HMAC.hexdigest(digest, Rails.application.config.fp_secret, policy) render :json => { :signature => signature, :policy => policy }, :status => :ok end ###################### CRASH DUMPS ####################### # This is very similar to api_music_sessions#perf_upload # This should largely be moved into a library somewhere in jam-ruby. def crash_dump # example of using curl to access this API: # curl -L -T some_file -X PUT http://localhost:3000/api/dumps?client_type=[MacOSX/Win32/JamBox]&client_version=[VERSION]&client_id=[CLIENT_ID]&session_id=[SESSION_ID]×tamp=[TIMESTAMP]&fsize=10K&crash_context="Blahblahblab" # user_id is deduced if possible from the user's cookie. @dump = CrashDump.new user = User.find_by_id(params[:user_id]) @dump.client_type = params[:client_type] @dump.client_version = params[:client_version] @dump.client_id = params[:client_id] @dump.user_id = user.id if user @dump.session_id = params[:session_id] @dump.timestamp = params[:timestamp] @dump.description = params[:description] @dump.fsize = params[:fsize] @dump.crash_context = params[:crash_context] crash_date = params[:crash_date] # make sure client is passing version information - if not its too old unless (vdata = params[:version]).present? render(json: {message: "blank version data #{vdata}"}, status: :unprocessable_entity) && return end unless @dump.save # There are at least some conditions on valid dumps (need client_type) response.status = :unprocessable_entity respond_with @dump return end # This part is the piece that really needs to be decomposed into a library... if Rails.application.config.storage_type == :fog s3 = AWS::S3.new(:access_key_id => Rails.application.config.aws_access_key_id, :secret_access_key => Rails.application.config.aws_secret_access_key) bucket = s3.buckets[Rails.application.config.aws_bucket] uri = @dump.uri expire = Time.now + 5.years read_url = bucket.objects[uri].url_for(:read, :expires => expire, :'response_content_type' => 'application/octet-stream').to_s #@dump.update_attribute(:uri, read_url) write_url = bucket.objects[uri].url_for(:write, :expires => Rails.application.config.crash_dump_data_signed_url_timeout, :'response_content_type' => 'application/octet-stream').to_s logger.debug("crash_dump can read from url #{read_url}") if user body = "Client crash for user #{user.email} (#{user.name})\n" body << "Client type: #{@dump.client_type}\n" body << "Client version: #{@dump.client_version}\n" body << "Download at: #{read_url}\n" body << "User admin url: #{user.admin_url}\n" body << "Actual Crash Date: #{crash_date}\n" body << "File size: #{@dump.fsize}\n" if @dump.description == "log" body << "Log Context:\n\n#{@dump.crash_context}\n" subject = "Logs for #{@dump.client_type} - #{user.email}, on #{crash_date}" else body << "Crash Context:\n\n#{@dump.crash_context}\n" subject = "Crash for #{@dump.client_type} - #{user.email}, on #{crash_date}" end else body = "Client crash for unknown user\n" body << "Client type: #{@dump.client_type}\n" body << "Client version: #{@dump.client_version}\n" body << "Download at: #{read_url}\n" body << "Actual Crash Date: #{crash_date}\n" body << "File size: #{@dump.fsize}\n" if @dump.description == "log" body << "Log Context:\n\n#{@dump.crash_context}\n" subject = "Logs for #{@dump.client_type} - #{user.email}, on #{crash_date}" else body << "Crash Context:\n\n#{@dump.crash_context}\n" subject = "Crash for #{@dump.client_type} - #{user.email}, on #{crash_date}" end subject = "Crash for #{@dump.client_type} - unknown user), on #{crash_date}" end logger.debug("sending crash email with subject#{subject}") AdminMailer.crash_alert(subject: subject, body: body).deliver_now redirect_to write_url, status: 307 else # we should store it here to aid in development, but we don't have to until someone wants the feature # so... just return 200 render :json => {:id => @dump.id}, :status => 200 end end # user progression tracking def downloaded_client @user = current_user @user.update_progression_field(:first_downloaded_client_at) if @user.errors.any? respond_with @user, :status => :unprocessable_entity return end render :json => {}, :status => 200 end # user progression tracking def qualified_gear @user = current_user if params[:success] @user.update_progression_field(:first_certified_gear_at) connection = Connection.find_by_client_id(params[:client_id]) # update last_jam location information @user.update_addr_loc(connection, User::JAM_REASON_FTUE) if connection if !@user.errors.any? # update audio gear latency information @user.update_audio_latency(connection, params[:audio_latency]) if params[:audio_latency] end else @user.failed_qualification(params[:reason]) end if @user.errors.any? respond_with @user, :status => :unprocessable_entity return end render :json => {}, :status => 200 end # user progression tracking def social_promoted @user = current_user @user.update_progression_field(:first_social_promoted_at) if @user.errors.any? respond_with @user, :status => :unprocessable_entity return end render :json => {}, :status => 200 end def opened_jamtrack_web_player User.where(id: current_user.id).update_all(first_opened_jamtrack_web_player: Time.now) render :json => {}, :status => 200 end def user_event event = UserEvent.new event.name = params[:name] event.detail = params[:detail].to_json if params[:detail] event.user_id = current_user.id if current_user event.save render :json => {}, :status => 200 end # creates display-ready session data for sharing def share_session provider = params[:provider] music_session_id = params[:music_session] history = MusicSession.find(music_session_id) if provider == 'facebook' render json: { description: view_context.description_for_music_session(history), title: view_context.title_for_music_session(history, current_user), photo_url: view_context.facebook_image_for_music_session(history), url: share_token_url(history.share_token.token), caption: 'www.jamkazam.com' }, status: 200 elsif provider == 'twitter' render json: { message: view_context.title_for_music_session(history, current_user) }, status: 200 else render :json => {:errors => {:provider => ['not valid']}}, :status => 422 end end # creates display-ready recording data for sharing def share_recording provider = params[:provider] claimed_recording_id = params[:claimed_recording] claimed_recording = ClaimedRecording.find(claimed_recording_id) if provider == 'facebook' render json: { description: view_context.description_for_claimed_recording(claimed_recording), title: view_context.title_for_claimed_recording(claimed_recording, current_user), photo_url: view_context.facebook_image_for_claimed_recording(claimed_recording), url: share_token_url(claimed_recording.share_token.token), caption: 'www.jamkazam.com' }, status: 200 elsif provider == 'twitter' render json: { message: view_context.title_for_claimed_recording(history, current_user) + " at " + request.host_with_port }, status: 200 else render :json => {:errors => {:provider => ['not valid']}}, :status => 422 end end def affiliate_partner if oo = current_user.affiliate_partner if request.post? oo.address = params[:address] oo.tax_identifier = params[:tax_identifier] oo.save! render nothing: true elsif request.get? result = {} result['account'] = { 'address' => oo.address.clone, 'tax_identifier' => oo.tax_identifier, 'entity_type' => oo.entity_type, 'partner_name' => oo.partner_name, 'partner_id' => oo.partner_user_id, 'id' => oo.id } if txt = oo.affiliate_legalese.try(:legalese) txt = ControllerHelp.instance.simple_format(txt) end result['agreement'] = { 'legalese' => txt, 'signed_at' => oo.signed_at } #result['signups'] = oo.referrals_by_date #result['earnings'] = [['April 2015', '1000 units', '$100']] render json: result.to_json, status: 200 end else render :json => {:message => 'user not affiliate partner'}, :status => 400 end end def affiliate_report begin affiliate = User .where(:id => params[:id]) .includes(:affiliate_partner) .limit(1) .first .affiliate_partner referrals_by_date = affiliate.referrals_by_date do |by_date| by_date.inject([]) { |rr, key| rr << key } end result = { :total_count => affiliate.referral_user_count, :by_date => referrals_by_date } render json: result.to_json, status: 200 rescue render :json => {:message => $!.to_s}, :status => 400 end end def add_play if params[:id].blank? render :json => {:message => "Playable ID is required"}, :status => 400 return end play = PlayablePlay.new play.playable_id = params[:id] play.playable_type = params[:playable_type] play.player_id = params[:user_id] play.claimed_recording_id = params[:claimed_recording_id] play.ip_address = request.remote_ip play.save if play.errors.any? render :json => {:errors => play.errors}, :status => 422 else render :json => {}, :status => 201 end end # updates audio latency on the user, and associated connection def audio_latency Connection.transaction do @user.update_audio_latency(Connection.find_by_client_id(params[:client_id]), params[:audio_latency]) respond_with_model(@user) end end def udp_reachable Connection.transaction do @connection = Connection.find_by_client_id!(params[:client_id]) # deliberately don't updated_at on connection! only heartbeats do that Connection.where(:id => @connection.id).update_all(:udp_reachable => params[:udp_reachable]) respond_with_model(@connection) end end def is_network_testing Connection.transaction do @connection = Connection.find_by_client_id!(params[:client_id]) # deliberately don't updated_at on connection! only heartbeats do that Connection.where(:id => @connection.id).update_all(:is_network_testing => params[:is_network_testing]) respond_with_model(@connection) end end def validate_data unless (data = params[:data]).present? render(json: {message: "blank data #{data}"}, status: :unprocessable_entity) && return end url = nil site = params[:sitetype] if site.blank? || 'url'==site url = data elsif Utils.recording_source?(site) rec_data = Utils.extract_recording_data(site, data) if rec_data render json: {message: 'Valid Site', recording_id: rec_data["id"], recording_title: rec_data["title"], data: data}, status: 200 return else render json: {message: 'Invalid Site', data: data, errors: {site: ["Could not detect recording identifier"]}}, status: 200 return end else url = Utils.username_url(data, site) end unless url.blank? if errmsg = Utils.site_validator(url, site) render json: {message: 'Invalid Site', data: data, errors: {site: [errmsg]}}, status: 200 else render json: {message: 'Valid Site', data: data}, status: 200 end else render json: {message: "unknown validation for data '#{params[:data]}', site '#{params[:site]}'"}, status: :unprocessable_entity end end def broadcast_notification @broadcast = BroadcastNotification.next_broadcast(current_user) if @broadcast # mark it as viewed @broadcast.did_view(current_user) respond_with_model(@broadcast) else render json: {}, status: 200 end end # used to hide a broadcast notification from rotation temporarily def quiet_broadcast_notification @broadcast = BroadcastNotificationView.find_by_broadcast_notification_id_and_user_id(params[:broadcast_id], current_user.id) if @broadcast @broadcast.active_at = Date.today + 14 # 14 days in the future we'll re-instas @broadcast.save end render json: {}, status: 200 end def lookup_user User.includes([{musician_instruments: :instrument}, {band_musicians: :user}, {genre_players: :genre}, :bands, :instruments, :genres, :jam_track_rights, :affiliate_partner, :reviews, :review_summary, :recordings, :teacher => [:subjects, :instruments, :languages, :genres, :teachers_languages, :experiences_teaching, :experiences_award, :experiences_education, :reviews, :review_summary]]) .find(params[:id]) end def try_posa_card @posa_card = PosaCard.find_by_code(params[:gift_card]) if @posa_card.nil? return false end @posa_card.claim(current_user) if @posa_card.errors.any? respond_with_model(@posa_card) else if @posa_card.is_lesson_posa_card? render json: {gifted_jamclass: @posa_card.credits}, status: 200 elsif @posa_card.card_type == PosaCard::JAM_TRACKS_10 render json: {gifted_jamtracks: @posa_card.credits}, status: 200 elsif @posa_card.card_type == PosaCard::JAM_TRACKS_5 render json: {gifted_jamtracks: @posa_card.credits}, status: 200 else raise 'unknown card_type ' + @posa_card.card_type end end return true end def try_gift_card @gift_card = GiftCard.find_by_code(params[:gift_card]) if @gift_card.nil? render json: {errors: {gift_card: ['does not exist']}}, status: 422 return end if current_user.gift_cards.count >= 5 render json: {errors: {gift_card: ['has too many on account']}}, status: 422 return end if @gift_card.user if @gift_card.user == current_user render json: {errors: {gift_card: ['already redeemed by you']}}, status: 422 return else render json: {errors: {gift_card: ['already redeemed by another']}}, status: 422 return end end @gift_card.user = current_user @gift_card.save if @gift_card.errors.any? respond_with_model(@gift_card) return else UserWhitelist.card_create(current_user, 'giftcard') # apply gift card items to everything in shopping cart current_user.reload ShoppingCart.apply_gifted_jamtracks(current_user) render json: {gifted_jamtracks: current_user.gifted_jamtracks}, status: 200 end end def redeem_giftcard # first, try to find posa_card rendered = try_posa_card try_gift_card if !rendered end def test_drive_status @user = current_user @teacher = User.find(params[:teacher_id]) end def onboardings @onboardings = current_user.onboarding_users.where('onboarding_status in (?)', [User::ONBOARDING_STATUS_ASSIGNED, User::ONBOARDING_STATUS_EMAILED]).order(:onboarder_assigned_at) end def update_onboarding user = User.find(params[:id]) if params[:onboarding_lost_reason] user.onboarding_lost_reason = params[:onboarding_lost_reason] user.onboarding_lost_at = Date.today end if params[:onboarding_escalation_reason] user.onboarding_escalation_reason = params[:onboarding_escalation_reason] user.onboarding_escalated_at = Date.today end user.onboarding_email_1_sent_at = Date.today if params[:onboarding_email_1_sent_at] user.onboarding_email_2_sent_at = Date.today if params[:onboarding_email_2_sent_at] user.onboarding_email_3_sent_at = Date.today if params[:onboarding_email_3_sent_at] user.onboarding_email_4_sent_at = Date.today if params[:onboarding_email_4_sent_at] user.onboarding_email_5_sent_at = Date.today if params[:onboarding_email_5_sent_at] user.onboarding_test_session_scheduled_at = Date.today if params[:onboarding_test_session_scheduled_at] user.onboarding_test_session_at = params[:onboarding_test_session_at] if params[:onboarding_test_session_at] user.onboarding_test_session_outcome = params[:onboarding_test_session_outcome] if params[:onboarding_test_session_outcome] user.onboarding_onboarded_at = Date.today if params[:onboarding_onboarded_at] user.onboarding_onboarder_notes = params[:onboarding_onboarder_notes] if params[:onboarding_onboarder_notes] user.save user.reload @onboarding = user end def show_onboarding @onboarding = User.find(params[:id]) end ###################### RECORDINGS ####################### # def recording_index # @recordings = User.recording_index(current_user, params[:id]) # respond_with @recordings, responder: ApiResponder, :status => 200 # end # def recording_show # hide_private = false # # hide private recordings from anyone but the current user # if current_user.id != params[:id] # hide_private = true # end # @recording = Recording.find(params[:recording_id]) # if !@recording.public && hide_private # render :json => { :message => "You are not allowed to access this recording." }, :status => 403 # #respond_with "You are not allowed to access this recording.", responder: ApiResponder, :status => 403 # else # respond_with @recording, responder: ApiResponder, :status => 200 # end # end # def recording_create # @recording = Recording.save(params[:recording_id], # params[:public], # params[:description], # params[:genres], # current_user.id, # params[:id], # false) # @user = current_user # respond_with @recording, responder: ApiResponder, :status => 201, :location => api_recording_detail_url(@user, @recording) # end # def recording_update # @recording = Recording.save(params[:recording_id], # params[:public], # params[:description], # params[:genres], # current_user.id, # params[:id], # false) # respond_with @recording, responder: ApiResponder, :status => 200 # end # def recording_destroy # @recording = Recording.find(params[:recording_id]) # @recording.delete # respond_with responder: ApiResponder, :status => 204 # end end