diff --git a/admin/Gemfile b/admin/Gemfile
index 7ca5eda28..8a4306801 100644
--- a/admin/Gemfile
+++ b/admin/Gemfile
@@ -1,4 +1,4 @@
-source 'https://rubygems.org'
+source 'http://rubygems.org'
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
diff --git a/admin/app/controllers/artifacts_controller.rb b/admin/app/controllers/artifacts_controller.rb
index 8e7012eff..3fb5cc5cc 100644
--- a/admin/app/controllers/artifacts_controller.rb
+++ b/admin/app/controllers/artifacts_controller.rb
@@ -11,12 +11,16 @@ class ArtifactsController < ApplicationController
file = params[:file]
environment = params[:environment]
- @artifact = ArtifactUpdate.find_or_create_by_product_and_environment(product, environment)
+ ArtifactUpdate.transaction do
+ # VRFS-1071: Postpone client update notification until installer is available for download
+ ArtifactUpdate.connection.execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED')
+ @artifact = ArtifactUpdate.find_or_create_by_product_and_environment(product, environment)
- @artifact.version = version
- @artifact.uri = file
+ @artifact.version = version
+ @artifact.uri = file
- @artifact.save
+ @artifact.save
+ end
unless @artifact.errors.any?
render :json => {}, :status => :ok
diff --git a/admin/config/boot.rb b/admin/config/boot.rb
index 2b59194e5..56e91c277 100644
--- a/admin/config/boot.rb
+++ b/admin/config/boot.rb
@@ -12,7 +12,9 @@ module Rails
class Server
alias :default_options_alias :default_options
def default_options
- default_options_alias.merge!(:Port => 3333)
+ default_options_alias.merge!(
+ :Port => 3333 + ENV['JAM_INSTANCE'].to_i,
+ :pid => File.expand_path("tmp/pids/server-#{ENV['JAM_INSTANCE'].to_i}.pid"))
end
end
end
\ No newline at end of file
diff --git a/admin/script/package/jam-admin.conf b/admin/script/package/jam-admin.conf
index 43e8a34cc..c429d3209 100644
--- a/admin/script/package/jam-admin.conf
+++ b/admin/script/package/jam-admin.conf
@@ -6,4 +6,10 @@ stop on runlevel [016]
setuid jam-admin
setgid jam-admin
+pre-start script
+ set -e
+ mkdir -p /var/run/jam-admin
+ chown jam-admin:jam-admin /var/run/jam-admin
+end script
+
exec start-stop-daemon --start --chdir /var/lib/jam-admin --exec /var/lib/jam-admin/script/package/upstart-run.sh
diff --git a/admin/script/package/post-install.sh b/admin/script/package/post-install.sh
index 9949dce43..1ed894877 100755
--- a/admin/script/package/post-install.sh
+++ b/admin/script/package/post-install.sh
@@ -14,9 +14,7 @@ mkdir -p /var/lib/$NAME/log
mkdir -p /var/lib/$NAME/tmp
mkdir -p /etc/$NAME
mkdir -p /var/log/$NAME
-mkdir -p /var/run/$NAME
chown -R $USER:$GROUP /var/lib/$NAME
chown -R $USER:$GROUP /etc/$NAME
chown -R $USER:$GROUP /var/log/$NAME
-chown -R $USER:$GROUP /var/run/$NAME
diff --git a/db/Gemfile b/db/Gemfile
index 45bf466d6..0b7addf09 100644
--- a/db/Gemfile
+++ b/db/Gemfile
@@ -1,4 +1,4 @@
-source 'https://rubygems.org'
+source 'http://rubygems.org'
# Assumes you have already cloned pg_migrate_ruby in your workspace
# $ cd [workspace]
diff --git a/db/manifest b/db/manifest
index ec3b567a2..042e0661c 100755
--- a/db/manifest
+++ b/db/manifest
@@ -96,4 +96,6 @@ ms_user_history_add_instruments.sql
icecast_config_changed.sql
invited_users_facebook_support.sql
first_recording_at.sql
-share_token.sql
\ No newline at end of file
+share_token.sql
+facebook_signup.sql
+audiomixer_mp3.sql
\ No newline at end of file
diff --git a/db/up/audiomixer_mp3.sql b/db/up/audiomixer_mp3.sql
new file mode 100644
index 000000000..d48cfed01
--- /dev/null
+++ b/db/up/audiomixer_mp3.sql
@@ -0,0 +1,9 @@
+-- add idea of a mix having mp3 as well as ogg
+
+ALTER TABLE mixes RENAME COLUMN md5 TO ogg_md5;
+ALTER TABLE mixes RENAME COLUMN length TO ogg_length;
+ALTER TABLE mixes RENAME COLUMN url TO ogg_url;
+
+ALTER TABLE mixes ADD COLUMN mp3_md5 VARCHAR(100);
+ALTER TABLE mixes ADD COLUMN mp3_length INTEGER;
+ALTER TABLE mixes ADD COLUMN mp3_url VARCHAR(1024);
\ No newline at end of file
diff --git a/db/up/facebook_signup.sql b/db/up/facebook_signup.sql
new file mode 100644
index 000000000..d27ec0cdd
--- /dev/null
+++ b/db/up/facebook_signup.sql
@@ -0,0 +1,16 @@
+-- when a user authorizes our application to signup, we create this row
+CREATE UNLOGGED TABLE facebook_signups (
+ id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
+ lookup_id VARCHAR(255) UNIQUE NOT NULL,
+ last_name VARCHAR(100),
+ first_name VARCHAR(100),
+ gender VARCHAR(1),
+ email VARCHAR(1024),
+ uid VARCHAR(1024),
+ token VARCHAR(1024),
+ token_expires_at TIMESTAMP,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+ALTER TABLE user_authorizations ADD CONSTRAINT user_authorizations_uniqkey UNIQUE (provider, uid);
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb
index 6ab7a51bb..aa036793d 100755
--- a/ruby/lib/jam_ruby.rb
+++ b/ruby/lib/jam_ruby.rb
@@ -35,6 +35,7 @@ require "jam_ruby/resque/resque_hooks"
require "jam_ruby/resque/scheduled/audiomixer_retry"
require "jam_ruby/resque/scheduled/icecast_config_retry"
require "jam_ruby/resque/scheduled/icecast_source_check"
+require "jam_ruby/resque/scheduled/cleanup_facebook_signup"
require "jam_ruby/mq_router"
require "jam_ruby/base_manager"
require "jam_ruby/connection_manager"
@@ -117,6 +118,7 @@ require "jam_ruby/models/icecast_server_socket"
require "jam_ruby/models/icecast_template_socket"
require "jam_ruby/models/icecast_server_group"
require "jam_ruby/models/icecast_mount_template"
+require "jam_ruby/models/facebook_signup"
include Jampb
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb
index a6abfd81a..d5c91c673 100644
--- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb
+++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb
@@ -13,7 +13,7 @@
<% end %>
<%= user.biography %>
-Profile
+Profile
|
|
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb
index c69f9965f..13e391154 100644
--- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb
+++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb
@@ -1,7 +1,7 @@
New JamKazam Musicians in your Area
<% @new_nearby.each do |user| %>
-<%= user.name %> (http://<%= @host %>/#/profile/<%= user.id %>)
+<%= user.name %> (http://<%= @host %>/client#/profile/<%= user.id %>)
<%= user.location %>
<% user.instruments.collect { |inst| inst.description }.join(', ') %>
<%= user.biography %>
diff --git a/ruby/lib/jam_ruby/models/facebook_signup.rb b/ruby/lib/jam_ruby/models/facebook_signup.rb
new file mode 100644
index 000000000..9e232b2a1
--- /dev/null
+++ b/ruby/lib/jam_ruby/models/facebook_signup.rb
@@ -0,0 +1,15 @@
+module JamRuby
+ class FacebookSignup < ActiveRecord::Base
+
+ before_create :generate_lookup_id
+
+ def self.delete_old
+ FacebookSignup.where("created_at < :week", {:week => 1.week.ago}).delete_all
+ end
+
+ private
+ def generate_lookup_id
+ self.lookup_id = SecureRandom.urlsafe_base64
+ end
+ end
+end
diff --git a/ruby/lib/jam_ruby/models/invited_user.rb b/ruby/lib/jam_ruby/models/invited_user.rb
index 228fc024f..cebc0d25e 100644
--- a/ruby/lib/jam_ruby/models/invited_user.rb
+++ b/ruby/lib/jam_ruby/models/invited_user.rb
@@ -65,7 +65,7 @@ module JamRuby
def generate_signup_url
if 'development'==Rails.env
- "http://jamkazamdev.local:3000/signup?invitation_code=#{self.invitation_code}"
+ "http://localhost:3000/signup?invitation_code=#{self.invitation_code}"
else
"http://www.jamkazam.com/signup?invitation_code=#{self.invitation_code}"
end
diff --git a/ruby/lib/jam_ruby/models/mix.rb b/ruby/lib/jam_ruby/models/mix.rb
index 66a58e1e5..9ec1c1e66 100644
--- a/ruby/lib/jam_ruby/models/mix.rb
+++ b/ruby/lib/jam_ruby/models/mix.rb
@@ -17,7 +17,8 @@ module JamRuby
mix = Mix.new
mix.recording = recording
mix.save
- mix.url = construct_filename(mix.created_at, recording.id, mix.id)
+ mix.ogg_url = construct_filename(mix.created_at, recording.id, mix.id, type='ogg')
+ mix.mp3_url = construct_filename(mix.created_at, recording.id, mix.id, type='mp3')
if mix.save
mix.enqueue
end
@@ -27,7 +28,7 @@ module JamRuby
def enqueue
begin
- Resque.enqueue(AudioMixer, self.id, self.sign_put)
+ Resque.enqueue(AudioMixer, self.id, self.sign_put(3600 * 24, 'ogg'), self.sign_put(3600 * 24, 'mp3'))
rescue
# implies redis is down. we don't update started_at
false
@@ -51,10 +52,12 @@ module JamRuby
save
end
- def finish(length, md5)
+ def finish(ogg_length, ogg_md5, mp3_length, mp3_md5)
self.completed_at = Time.now
- self.length = length
- self.md5 = md5
+ self.ogg_length = ogg_length
+ self.ogg_md5 = ogg_md5
+ self.mp3_length = mp3_length
+ self.mp3_md5 = mp3_md5
self.completed = true
if save
Notification.send_recording_master_mix_complete(recording)
@@ -74,41 +77,56 @@ module JamRuby
manifest["timeline"] << { "timestamp" => 0, "mix" => mix_params }
manifest["output"] = { "codec" => "vorbis" }
- manifest["recording_id"] = self.id
+ manifest["recording_id"] = self.recording.id
manifest
end
- def s3_url
- s3_manager.s3_url(url)
+ def s3_url(type='ogg')
+ if type == 'ogg'
+ s3_manager.s3_url(ogg_url)
+ else
+ s3_manager.s3_url(mp3_url)
+ end
+
+
end
def is_completed
completed
end
- def sign_url(expiration_time = 120)
+ def sign_url(expiration_time = 120, type='ogg')
# expire link in 1 minute--the expectation is that a client is immediately following this link
- s3_manager.sign_url(self.url, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false})
+ if type == 'ogg'
+ s3_manager.sign_url(self.ogg_url, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false})
+ else
+ s3_manager.sign_url(self.mp3_url, {:expires => expiration_time, :response_content_type => 'audio/mp3', :secure => false})
+ end
end
- def sign_put(expiration_time = 3600 * 24)
- s3_manager.sign_url(self.url, {:expires => expiration_time, :content_type => 'audio/ogg', :secure => false}, :put)
+ def sign_put(expiration_time = 3600 * 24, type='ogg')
+ if type == 'ogg'
+ s3_manager.sign_url(self.ogg_url, {:expires => expiration_time, :content_type => 'audio/ogg', :secure => false}, :put)
+ else
+ s3_manager.sign_url(self.mp3_url, {:expires => expiration_time, :content_type => 'audio/mp3', :secure => false}, :put)
+ end
end
private
def delete_s3_files
- s3_manager.delete(filename)
+ s3_manager.delete(filename(type='ogg'))
+ s3_manager.delete(filename(type='mp3'))
end
- def filename
+ def filename(type='ogg')
# construct a path for s3
- Mix.construct_filename(self.created_at, self.recording.id, self.id)
+ Mix.construct_filename(self.created_at, self.recording.id, self.id, type)
end
- def self.construct_filename(created_at, recording_id, id)
+ def self.construct_filename(created_at, recording_id, id, type='ogg')
raise "unknown ID" unless id
- "recordings/#{created_at.strftime('%m-%d-%Y')}/#{recording_id}/mix-#{id}.ogg"
+ "recordings/#{created_at.strftime('%m-%d-%Y')}/#{recording_id}/mix-#{id}.#{type}"
end
end
end
diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb
index 450385067..beba63625 100644
--- a/ruby/lib/jam_ruby/models/recording.rb
+++ b/ruby/lib/jam_ruby/models/recording.rb
@@ -105,9 +105,6 @@ module JamRuby
end
end
- connection = Connection.where(:user_id => owner.id).where(:music_session_id => music_session.id).first
- Notification.send_recording_started(music_session, connection, owner)
-
recording
end
@@ -122,9 +119,6 @@ module JamRuby
self.save
end
- connection = Connection.where(:user_id => self.owner.id).where(:music_session_id => music_session.id).first
- Notification.send_recording_ended(music_session, connection, self.owner)
-
self
end
@@ -214,9 +208,9 @@ module JamRuby
:type => "mix",
:id => mix.id.to_s,
:recording_id => mix.recording_id,
- :length => mix.length,
- :md5 => mix.md5,
- :url => mix.url,
+ :length => mix.ogg_length,
+ :md5 => mix.ogg_md5,
+ :url => mix.ogg_url,
:created_at => mix.created_at,
:next => mix.id
}
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index 00011b407..e137b8a81 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -697,8 +697,23 @@ module JamRuby
# throws ActiveRecord::RecordNotFound if instrument is invalid
# throws an email delivery error if unable to connect out to SMTP
- def self.signup(first_name, last_name, email, password, password_confirmation, terms_of_service,
- location, instruments, birth_date, musician, photo_url, invited_user, signup_confirm_url)
+ def self.signup(options)
+
+ first_name = options[:first_name]
+ last_name = options[:last_name]
+ email = options[:email]
+ password = options[:password]
+ password_confirmation = options[:password_confirmation]
+ terms_of_service = options[:terms_of_service]
+ location = options[:location]
+ instruments = options[:instruments]
+ birth_date = options[:birth_date]
+ musician = options[:musician]
+ photo_url = options[:photo_url]
+ invited_user = options[:invited_user]
+ fb_signup = options[:fb_signup]
+ signup_confirm_url = options[:signup_confirm_url]
+
user = User.new
UserManager.active_record_transaction do |user_manager|
@@ -744,11 +759,25 @@ module JamRuby
user.photo_url = photo_url
+ unless fb_signup.nil?
+ user.update_fb_authorization(fb_signup)
+
+ if fb_signup.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
+ end
if invited_user.nil?
user.can_invite = Limits::USERS_CAN_INVITE
- user.email_confirmed = false
- user.signup_token = SecureRandom.urlsafe_base64
+
+ unless user.email_confirmed # important that the only time this goes true is if some other mechanism, like fb_signup, set this high
+ user.email_confirmed = false
+ user.signup_token = SecureRandom.urlsafe_base64
+ end
else
# if you are invited by an admin, we'll say you can invite too.
# but if not, then you can not invite
@@ -785,15 +814,10 @@ module JamRuby
if user.errors.any?
raise ActiveRecord::Rollback
else
- # 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?
+ # don't send an signup email if email is already confirmed
+ if user.email_confirmed
UserMailer.welcome_message(user).deliver
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.confirm_email(user, signup_confirm_url.nil? ? nil : (signup_confirm_url + "/" + user.signup_token) ).deliver
@@ -941,6 +965,30 @@ module JamRuby
end
end
+ # updates an existing user_authorization for facebook, or creates a new one if none exist
+ def update_fb_authorization(fb_signup)
+ if fb_signup.uid && fb_signup.token && fb_signup.token_expires_at
+
+ user_authorization = nil
+
+ unless self.new_record?
+ # see if this user has an existing user_authorization for this provider
+ user_authorization = UserAuthorization.find_by_user_id_and_provider(self.id, 'facebook')
+ end
+
+ if user_authorization.nil?
+ self.user_authorizations.build provider: 'facebook',
+ uid: fb_signup.uid,
+ token: fb_signup.token,
+ token_expiration: fb_signup.token_expires_at
+ else
+ user_authorization.uid = fb_signup.uid
+ user_authorization.token = fb_signup.token
+ user_authorization.token_expiration = fb_signup.token_expires_at
+ end
+ end
+ end
+
def provides_location?
!self.city.blank? && (!self.state.blank? || !self.country.blank?)
end
diff --git a/ruby/lib/jam_ruby/models/user_authorization.rb b/ruby/lib/jam_ruby/models/user_authorization.rb
index 5f7c97e25..47061e17e 100644
--- a/ruby/lib/jam_ruby/models/user_authorization.rb
+++ b/ruby/lib/jam_ruby/models/user_authorization.rb
@@ -9,8 +9,10 @@ module JamRuby
belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "user_id"
validates :provider, :uid, :presence => true
+ validates_uniqueness_of :uid, scope: :provider
# token and token_expiration can be missing
-
+
+
end
end
diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb
index 3424b11d0..dd1a304e0 100644
--- a/ruby/lib/jam_ruby/resque/audiomixer.rb
+++ b/ruby/lib/jam_ruby/resque/audiomixer.rb
@@ -13,14 +13,16 @@ module JamRuby
@@log = Logging.logger[AudioMixer]
- attr_accessor :mix_id, :manifest, :manifest_file, :output_filename, :error_out_filename, :postback_output_url,
+ attr_accessor :mix_id, :manifest, :manifest_file, :output_filename, :error_out_filename,
+ :postback_ogg_url, :postback_mp3_url,
:error_reason, :error_detail
- def self.perform(mix_id, postback_output_url)
+ def self.perform(mix_id, postback_ogg_url, postback_mp3_url)
JamWebEventMachine.run_wait_stop do
audiomixer = AudioMixer.new()
- audiomixer.postback_output_url = postback_output_url
+ audiomixer.postback_ogg_url = postback_ogg_url
+ audiomixer.postback_mp3_url = postback_mp3_url
audiomixer.mix_id = mix_id
audiomixer.run
end
@@ -123,12 +125,13 @@ module JamRuby
# make a suitable location to store the output mix, and pass the chosen filepath into the manifest
def prepare_output
- @output_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-output-#{@manifest[:recording_id]}", '.ogg'], nil)
+ @output_ogg_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-output-#{@manifest[:recording_id]}", '.ogg'], nil)
+ @output_mp3_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-output-#{@manifest[:recording_id]}", '.mp3'], nil)
# update manifest so that audiomixer writes here
- @manifest[:output][:filename] = @output_filename
+ @manifest[:output][:filename] = @output_ogg_filename
- @@log.debug("output ogg file: #{@output_filename}")
+ @@log.debug("output ogg file: #{@output_ogg_filename}, output mp3 file: #{@output_mp3_filename}")
end
# make a suitable location to store an output error file, which will be populated on failure to help diagnose problems.
@@ -157,39 +160,62 @@ module JamRuby
end
def postback
- raise "no output file after mix" unless File.exist? @output_filename
- @@log.debug("posting mix to #{@postback_output_url}")
+ @@log.debug("posting ogg mix to #{@postback_ogg_url}")
- uri = URI.parse(@postback_output_url)
+ uri = URI.parse(@postback_ogg_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Put.new(uri.request_uri)
response = nil
- File.open(@output_filename,"r") do |f|
+ File.open(@output_ogg_filename,"r") do |f|
request.body_stream=f
request["Content-Type"] = "audio/ogg"
- request.add_field('Content-Length', File.size(@output_filename))
+ request.add_field('Content-Length', File.size(@output_ogg_filename))
response = http.request(request)
end
response_code = response.code.to_i
unless response_code >= 200 && response_code <= 299
- @error_reason = "postback-mix-to-s3"
- raise "unable to put to url: #{@postback_output_url}, status: #{response.code}, body: #{response.body}"
+ @error_reason = "postback-ogg-mix-to-s3"
+ raise "unable to put to url: #{@postback_ogg_url}, status: #{response.code}, body: #{response.body}"
+ end
+
+
+ @@log.debug("posting mp3 mix to #{@postback_mp3_url}")
+
+ uri = URI.parse(@postback_mp3_url)
+ http = Net::HTTP.new(uri.host, uri.port)
+ request = Net::HTTP::Put.new(uri.request_uri)
+
+ response = nil
+ File.open(@output_mp3_filename,"r") do |f|
+ request.body_stream=f
+ request["Content-Type"] = "audio/mp3"
+ request.add_field('Content-Length', File.size(@output_mp3_filename))
+ response = http.request(request)
+ end
+
+ response_code = response.code.to_i
+ unless response_code >= 200 && response_code <= 299
+ @error_reason = "postback-mp3-mix-to-s3"
+ raise "unable to put to url: #{@postback_mp3_url}, status: #{response.code}, body: #{response.body}"
end
end
def post_success(mix)
- raise "no output file after mix" unless File.exist? @output_filename
- length = File.size(@output_filename)
+ ogg_length = File.size(@output_ogg_filename)
+ ogg_md5 = Digest::MD5.new
+ File.open(@output_ogg_filename, 'rb').each {|line| ogg_md5.update(line)}
- md5 = Digest::MD5.new
- File.open(@output_filename, 'rb').each {|line| md5.update(line)}
+ mp3_length = File.size(@output_mp3_filename)
+ mp3_md5 = Digest::MD5.new
+ File.open(@output_mp3_filename, 'rb').each {|line| mp3_md5.update(line)}
- mix.finish(length, md5.to_s)
+
+ mix.finish(ogg_length, ogg_md5.to_s, mp3_length, mp3_md5.to_s)
end
def post_error(mix, e)
@@ -233,16 +259,12 @@ module JamRuby
execute(@manifest_file)
- if $? == 0
- postback
- post_success(mix)
- @@log.info("audiomixer job successful. mix_id #{mix_id}")
- else
- parse_error_out
- error_msg = "audiomixer job failed status=#{$?} error_reason=#{error_reason} error_detail=#{error_detail}"
- @@log.info(error_msg)
- raise error_msg
- end
+ postback
+
+ post_success(mix)
+
+ @@log.info("audiomixer job successful. mix_id #{mix_id}")
+
rescue Exception => e
post_error(mix, e)
raise
@@ -260,20 +282,41 @@ module JamRuby
unless File.exist? APP_CONFIG.audiomixer_path
@@log.error("unable to find audiomixer")
- error_msg = "audiomixer job failed status=#{$?} error_reason=#{error_reason} error_detail=#{error_detail}"
+ error_msg = "audiomixer job failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}"
@@log.info(error_msg)
@error_reason = "unable-find-appmixer"
@error_detail = APP_CONFIG.audiomixer_path
raise error_msg
end
-
audiomixer_cmd = "#{APP_CONFIG.audiomixer_path} #{manifest_file}"
-
@@log.debug("executing #{audiomixer_cmd}")
system(audiomixer_cmd)
+
+ unless $? == 0
+ parse_error_out
+ error_msg = "audiomixer job failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}"
+ @@log.info(error_msg)
+ raise error_msg
+ end
+
+ raise "no output ogg file after mix" unless File.exist? @output_ogg_filename
+
+ ffmpeg_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{@output_ogg_filename}\" -ab 128k -metadata JamRecordingId=#{@manifest[:recording_id]} -metadata JamMixId=#{@mix_id} -metadata JamType=Mix \"#{@output_mp3_filename}\""
+
+ system(ffmpeg_cmd)
+
+ unless $? == 0
+ @error_reason = 'ffmpeg-failed'
+ @error_detail = $?.to_s
+ error_msg = "ffmpeg failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}"
+ @@log.info(error_msg)
+ raise error_msg
+ end
+
+ raise "no output mp3 file after conversion" unless File.exist? @output_mp3_filename
end
def symbolize_keys(obj)
diff --git a/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb b/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb
new file mode 100644
index 000000000..a2cbab476
--- /dev/null
+++ b/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb
@@ -0,0 +1,19 @@
+
+module JamRuby
+ class CleanupFacebookSignup
+
+ @queue = :cleanup_facebook_signup
+
+ @@log = Logging.logger[CleanupFacebookSignup]
+
+
+ def self.perform
+ @@log.debug("waking up")
+
+ FacebookSignup.delete_old
+
+ @@log.debug("done")
+ end
+
+ end
+end
diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb
index 68b71c553..a8eda4e0a 100644
--- a/ruby/spec/factories.rb
+++ b/ruby/spec/factories.rb
@@ -317,4 +317,14 @@ FactoryGirl.define do
association :authentication, :factory => :icecast_user_authentication
end
+ factory :facebook_signup, :class => JamRuby::FacebookSignup do
+ sequence(:lookup_id) { |n| "lookup-#{n}"}
+ sequence(:first_name) { |n| "first-#{n}"}
+ sequence(:last_name) { |n| "last-#{n}"}
+ gender 'M'
+ sequence(:email) { |n| "jammin-#{n}@jamkazam.com"}
+ sequence(:uid) { |n| "uid-#{n}"}
+ sequence(:token) { |n| "token-#{n}"}
+ token_expires_at Time.now
+ end
end
diff --git a/ruby/spec/jam_ruby/models/facebook_signup_spec.rb b/ruby/spec/jam_ruby/models/facebook_signup_spec.rb
new file mode 100644
index 000000000..6edbab157
--- /dev/null
+++ b/ruby/spec/jam_ruby/models/facebook_signup_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe FacebookSignup do
+
+ it "does not delete new one" do
+ new_signup = FactoryGirl.create(:facebook_signup)
+
+ FacebookSignup.delete_old
+
+ FacebookSignup.find(new_signup)
+ end
+
+ it "does delete old one" do
+ old_signup = FactoryGirl.create(:facebook_signup, :created_at => 10.days.ago)
+
+ FacebookSignup.delete_old
+
+ FacebookSignup.find_by_id(old_signup.id).should be_nil
+ end
+end
diff --git a/ruby/spec/jam_ruby/models/mix_spec.rb b/ruby/spec/jam_ruby/models/mix_spec.rb
index bb361bc99..359100423 100755
--- a/ruby/spec/jam_ruby/models/mix_spec.rb
+++ b/ruby/spec/jam_ruby/models/mix_spec.rb
@@ -26,11 +26,19 @@ describe Mix do
end
it "should record when a mix has finished" do
- Mix.find(@mix.id).finish(10000, "md5hash")
+ Mix.find(@mix.id).finish(10000, "md5hash", 10000, "md5hash")
@mix.reload
@mix.completed_at.should_not be_nil
- @mix.length.should == 10000
- @mix.md5.should == "md5hash"
+ @mix.ogg_length.should == 10000
+ @mix.ogg_md5.should == "md5hash"
+ end
+
+ it "create a good manifest" do
+ Mix.find(@mix.id).finish(10000, "md5hash", 10000, "md5hash")
+ @mix.reload
+ manifest = @mix.manifest
+ manifest["recording_id"].should == @recording.id
+ manifest["files"].length.should == 1
end
it "signs url" do
@@ -40,7 +48,7 @@ describe Mix do
it "mixes are restricted by user" do
- @mix.finish(1, "abc")
+ @mix.finish(1, "abc", 1, "def")
@mix.reload
@mix.errors.any?.should be_false
diff --git a/ruby/spec/jam_ruby/models/user_spec.rb b/ruby/spec/jam_ruby/models/user_spec.rb
index a29179a8a..a069e7ee0 100644
--- a/ruby/spec/jam_ruby/models/user_spec.rb
+++ b/ruby/spec/jam_ruby/models/user_spec.rb
@@ -397,6 +397,34 @@ describe User do
end
end
+ describe "user_authorizations" do
+
+ it "can create" do
+ @user.user_authorizations.build provider: 'facebook',
+ uid: '1',
+ token: '1',
+ token_expiration: Time.now
+ @user.save!
+ end
+
+ it "fails on duplicate" do
+ @user.user_authorizations.build provider: 'facebook',
+ uid: '1',
+ token: '1',
+ token_expiration: Time.now
+ @user.save!
+
+ @user2 = FactoryGirl.create(:user)
+ @user2.user_authorizations.build provider: 'facebook',
+ uid: '1',
+ token: '1',
+ token_expiration: Time.now
+ @user2.save.should be_false
+ @user2.errors[:user_authorizations].should == ['is invalid']
+ end
+
+
+ end
=begin
describe "update avatar" do
diff --git a/ruby/spec/jam_ruby/resque/audiomixer_spec.rb b/ruby/spec/jam_ruby/resque/audiomixer_spec.rb
index 5b27e35d7..5411acc39 100644
--- a/ruby/spec/jam_ruby/resque/audiomixer_spec.rb
+++ b/ruby/spec/jam_ruby/resque/audiomixer_spec.rb
@@ -233,8 +233,8 @@ describe AudioMixer do
@mix.reload
@mix.completed.should be_true
- @mix.length.should == 0
- @mix.md5.should == 'd41d8cd98f00b204e9800998ecf8427e' # that's the md5 of a touched file, which is what the stubbed :execute does
+ @mix.ogg_length.should == 0
+ @mix.ogg_md5.should == 'd41d8cd98f00b204e9800998ecf8427e' # that's the md5 of a touched file, which is what the stubbed :execute does
end
it "bails out with no error if already completed" do
diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb
index 52d00aea6..8886ac7bb 100644
--- a/ruby/spec/support/utilities.rb
+++ b/ruby/spec/support/utilities.rb
@@ -21,6 +21,10 @@ def app_config
ENV['AUDIOMIXER_PATH'] || audiomixer_workspace_path || "/var/lib/audiomixer/audiomixer/audiomixerapp"
end
+ def ffmpeg_path
+ ENV['FFMPEG_PATH'] || '/usr/local/bin/ffmpeg'
+ end
+
def icecast_reload_cmd
'true' # as in, /bin/true
end
diff --git a/web/Gemfile b/web/Gemfile
index ac5e4551f..93b0ffd53 100644
--- a/web/Gemfile
+++ b/web/Gemfile
@@ -1,4 +1,4 @@
-source 'https://rubygems.org'
+source 'http://rubygems.org'
unless ENV["LOCAL_DEV"] == "1"
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
diff --git a/web/app/assets/images/content/button_facebook_signin.png b/web/app/assets/images/content/button_facebook_signin.png
new file mode 100644
index 000000000..08b15b7ba
Binary files /dev/null and b/web/app/assets/images/content/button_facebook_signin.png differ
diff --git a/web/app/assets/javascripts/bandProfile.js b/web/app/assets/javascripts/bandProfile.js
index 7551163e3..8cae06e1b 100644
--- a/web/app/assets/javascripts/bandProfile.js
+++ b/web/app/assets/javascripts/bandProfile.js
@@ -152,12 +152,14 @@
$('#btn-follow-band').text('STOP FOLLOWING');
$('#btn-follow-band').click(function() {
removeFollowing(true, bandId);
+ return false;
});
}
else {
$('#btn-follow-band').text('FOLLOW');
$('#btn-follow-band').click(function() {
addFollowing(true, bandId);
+ return false;
});
}
}
@@ -176,12 +178,14 @@
$btnFollowMember.text('UN-FOLLOW');
$btnFollowMember.click(function() {
removeFollowing(false, userId);
+ return false;
});
}
else {
$btnFollowMember.text('FOLLOW');
$btnFollowMember.click(function() {
addFollowing(false, userId);
+ return false;
});
}
}
@@ -385,7 +389,7 @@
var template = $('#template-band-profile-members').html();
var memberHtml = context.JK.fillTemplate(template, {
userId: musician.id,
- profile_url: "/#/profile/" + musician.id,
+ profile_url: "/client#/profile/" + musician.id,
avatar_url: context.JK.resolveAvatarUrl(musician.photo_url),
name: musician.name,
location: musician.location,
@@ -424,6 +428,8 @@
$divMember.remove();
})
.fail(app.ajaxError);
+
+ return false;
});
}
else {
@@ -475,7 +481,8 @@
$("#btn-edit-band-profile").click(function() {
$('div[layout-id="band/setup"] .hdn-band-id').val(bandId);
- context.location = "#/band/setup";
+ context.location = "/client#/band/setup";
+ return false;
});
}
diff --git a/web/app/assets/javascripts/findBand.js b/web/app/assets/javascripts/findBand.js
index 3fcfb3960..bcedec98b 100644
--- a/web/app/assets/javascripts/findBand.js
+++ b/web/app/assets/javascripts/findBand.js
@@ -106,7 +106,7 @@
playerVals = {
player_name: aPlayer.name,
- profile_url: '/#/profile/' + aPlayer.user_id,
+ profile_url: '/client#/profile/' + aPlayer.user_id,
avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url),
player_instruments: player_instrs
};
@@ -126,7 +126,7 @@
bVals = {
avatar_url: context.JK.resolveAvatarUrl(bb.photo_url),
- profile_url: "/#/profile/" + bb.id,
+ profile_url: "/client#/profile/" + bb.id,
band_name: bb.name,
band_location: bb.city + ', ' + bb.state,
genres: bgenres,
diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js
index 91ecca218..9293852c9 100644
--- a/web/app/assets/javascripts/findMusician.js
+++ b/web/app/assets/javascripts/findMusician.js
@@ -106,14 +106,14 @@
aFollow = mm['followings'][jj];
followVals = {
musician_name: aFollow.name,
- profile_url: '/#/profile/' + aFollow.user_id,
+ profile_url: '/client#/profile/' + aFollow.user_id,
avatar_url: context.JK.resolveAvatarUrl(aFollow.photo_url),
};
follows += context.JK.fillTemplate(fTemplate, followVals);
if (2 == jj) break;
}
var actionVals = {
- profile_url: "/#/profile/" + mm.id,
+ profile_url: "/client#/profile/" + mm.id,
friend_class: 'button-' + (mm['is_friend'] ? 'grey' : 'orange'),
friend_caption: (mm.is_friend ? 'DIS':'')+'CONNECT',
follow_class: 'button-' + (mm['is_following'] ? 'grey' : 'orange'),
@@ -124,7 +124,7 @@
mVals = {
avatar_url: context.JK.resolveAvatarUrl(mm.photo_url),
- profile_url: "/#/profile/" + mm.id,
+ profile_url: "/client#/profile/" + mm.id,
musician_name: mm.name,
musician_location: mm.city + ', ' + mm.state,
instruments: instr_logos,
diff --git a/web/app/assets/javascripts/homeScreen.js b/web/app/assets/javascripts/homeScreen.js
index 9f94bc624..fd6d58ec9 100644
--- a/web/app/assets/javascripts/homeScreen.js
+++ b/web/app/assets/javascripts/homeScreen.js
@@ -88,7 +88,7 @@
events();
$('.profile').on('click', function() {
- context.location = '#/profile/' + context.JK.currentUserId;
+ context.location = '/client#/profile/' + context.JK.currentUserId;
});
};
diff --git a/web/app/assets/javascripts/invitationDialog.js b/web/app/assets/javascripts/invitationDialog.js
index 8fd550df9..044b54bbf 100644
--- a/web/app/assets/javascripts/invitationDialog.js
+++ b/web/app/assets/javascripts/invitationDialog.js
@@ -212,6 +212,9 @@
};
function fbFeedDialogCallback(response) {
//console.log("feedback dialog closed: " + response['post_id'])
+ if (response['post_id']) {
+ context.JK.GA.trackServiceInvitations(context.JK.GA.InvitationTypes.facebook, 1);
+ }
}
FB.ui(obj, fbFeedDialogCallback);
}
diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js
index 2ffa8bb9f..fa3ae4ea3 100644
--- a/web/app/assets/javascripts/jam_rest.js
+++ b/web/app/assets/javascripts/jam_rest.js
@@ -199,6 +199,19 @@
});
}
+ function login(options) {
+ var url = '/api/auths/login';
+
+ return $.ajax({
+ type: "POST",
+ dataType: "json",
+ url: url,
+ processData: false,
+ contentType: 'application/json',
+ data: JSON.stringify(options)
+ });
+ }
+
function getUserDetail(options) {
var id = getId(options);
@@ -813,6 +826,7 @@
this.createBandInvitation = createBandInvitation;
this.updateBandInvitation = updateBandInvitation;
this.removeBandMember = removeBandMember;
+ this.login = login;
return this;
};
diff --git a/web/app/assets/javascripts/jamkazam.js b/web/app/assets/javascripts/jamkazam.js
index d9ec02fba..fba55b8f8 100644
--- a/web/app/assets/javascripts/jamkazam.js
+++ b/web/app/assets/javascripts/jamkazam.js
@@ -322,10 +322,17 @@
var hash = context.location.hash;
+ try { context.RouteMap.parse(hash); }
+ catch(e) {
+ console.log("ignoring bogus screen name: %o", hash)
+ hash = null;
+ }
+
var url = '#/home';
if (hash) {
url = hash;
}
+
logger.debug("Changing screen to " + url);
context.location = url;
}
diff --git a/web/app/assets/javascripts/playbackControls.js b/web/app/assets/javascripts/playbackControls.js
index cf1df1323..1df7e6f1c 100644
--- a/web/app/assets/javascripts/playbackControls.js
+++ b/web/app/assets/javascripts/playbackControls.js
@@ -168,6 +168,7 @@
currentTimeMs = playbackDurationMs;
stopPlay();
endReached = true;
+ console.log("end reached");
}
else {
return;
diff --git a/web/app/assets/javascripts/searchResults.js b/web/app/assets/javascripts/searchResults.js
index ad14a5d84..7795f4076 100644
--- a/web/app/assets/javascripts/searchResults.js
+++ b/web/app/assets/javascripts/searchResults.js
@@ -91,7 +91,7 @@
var args = {
userId: val.id,
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
- profile_url: "/#/profile/" + val.id,
+ profile_url: "/client#/profile/" + val.id,
userName: val.name,
location: val.location,
instruments: getInstrumentHtml(val.instruments)
@@ -104,7 +104,7 @@
var invitationSentHtml = context.JK.fillTemplate($(selector).html(), {
userId: val.id,
first_name: val.first_name,
- profile_url: "/#/profile/" + val.id
+ profile_url: "/client#/profile/" + val.id
});
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
@@ -154,7 +154,7 @@
var searchResultHtml = context.JK.fillTemplate($(template_name).html(), {
userId: val.id,
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
- profile_url: "/#/profile/" + val.id,
+ profile_url: "/client#/profile/" + val.id,
userName: val.name,
location: val.location
});
diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js
index 95ac0cde9..0a3fc572f 100644
--- a/web/app/assets/javascripts/sessionList.js
+++ b/web/app/assets/javascripts/sessionList.js
@@ -93,7 +93,7 @@
var photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
var musicianVals = {
avatar_url: photoUrl,
- profile_url: "/#/profile/" + id,
+ profile_url: "/client#/profile/" + id,
musician_name: name,
instruments: instrumentLogoHtml
};
diff --git a/web/app/assets/javascripts/shareDialog.js b/web/app/assets/javascripts/shareDialog.js
index 042cb43ec..53e477470 100644
--- a/web/app/assets/javascripts/shareDialog.js
+++ b/web/app/assets/javascripts/shareDialog.js
@@ -5,6 +5,7 @@
context.JK.ShareDialog = function(app, entityId, entityType) {
var logger = context.JK.logger;
var rest = context.JK.Rest();
+ var dialogId = '#share-dialog'
function socialShare() {
var shareWithFacebook = $('.share-with-facebook').is(':checked');
@@ -24,10 +25,17 @@
if (onOff) {
- }
- else {
+ $(dialogId + ' .dialog-share-button').unbind('click').click(function(e) {
- }
+
+ return false;
+ })
+ }
+
+ this.fb_login = function() {
+ FB.login(function(response) {
+ handle_fblogin_response(response);
+ }, {scope:'publish_stream'});
}
function showDialog() {
@@ -93,69 +101,6 @@
}
}
- /*function showEmailDialog() {
- $('#invitation-dialog').show();
- $('#invitation-textarea-container').show();
- $('#invitation-checkbox-container').hide();
- $('#btn-send-invitation').show();
- $('#btn-next-invitation').hide();
- clearTextFields();
- app.layout.showDialog('inviteUsers')
- }
-
- function showGoogleDialog() {
- $('#invitation-dialog').show();
- $('#invitation-textarea-container').hide();
- $('#invitation-checkbox-container').show();
- $('#btn-send-invitation').hide();
- $('#btn-next-invitation').show();
- clearTextFields();
-
- app.layout.showDialog('inviteUsers')
-
- $('#invitation-checkboxes').html('Loading your contacts...
');
- window._oauth_callback = function() {
- window._oauth_win.close();
- window._oauth_win = null;
- window._oauth_callback = null;
- $.ajax({
- type: "GET",
- url: "/gmail_contacts",
- success: function(response) {
- $('#invitation-checkboxes').html('');
- for (var i in response) {
- $('#invitation-checkboxes').append("");
- }
-
- $('.invitation-checkbox').change(function() {
- var checkedBoxes = $('.invitation-checkbox:checkbox:checked');
- var emails = '';
- for (var i = 0; i < checkedBoxes.length; i++) {
- emails += $(checkedBoxes[i]).data('email') + ', ';
- }
- emails = emails.replace(/, $/, '');
- // track how many of these came from google
- $('#txt-emails').val(emails).data('google_invite_count', checkedBoxes.length);
- });
- },
- error: function() {
- $('#invitation-checkboxes').html("Load failed!");
- }
- });
-
- };
- window._oauth_win = window.open("/auth/google_login", "_blank", "height=500,width=500,menubar=no,resizable=no,status=no");
- }
-
- function showFacebookDialog() {
- window._oauth_callback = function() {
- window._oauth_win.close();
- window._oauth_win = null;
- window._oauth_callback = null;
- };
- window._oauth_win = window.open("/auth/facebook_login", "_blank", "height=500,width=500,menubar=no,resizable=no,status=no");
- }*/
-
function clearTextFields() {
}
@@ -175,9 +120,9 @@
'afterHide': afterHide
};
- app.bindDialog('shareSessionRecording', dialogBindings);
+ app.bindDialog('shareRecording', dialogBindings);
- initDialog();
+ // callFB(fbAppID);
};
this.initialize = initialize;
diff --git a/web/app/assets/javascripts/web/signinDialog.js b/web/app/assets/javascripts/web/signinDialog.js
new file mode 100644
index 000000000..5d1f4e989
--- /dev/null
+++ b/web/app/assets/javascripts/web/signinDialog.js
@@ -0,0 +1,87 @@
+(function(context,$) {
+
+ "use strict";
+
+ context.JK = context.JK || {};
+
+ context.JK.SigninDialog = function(app) {
+ var logger = context.JK.logger;
+ var rest = context.JK.Rest();
+ var dialogId = '#signin-dialog';
+
+ function reset() {
+ $(dialogId + ' #signin-form').removeClass('login-error')
+
+ $(dialogId + ' input[name=email]').val('');
+ $(dialogId + ' input[name=password]').val('');
+ $(dialogId + ' input[name=remember_me]').attr('checked', 'checked')
+ }
+
+ function login() {
+ var email = $(dialogId + ' input[name=email]').val();
+ var password = $(dialogId + ' input[name=password]').val();
+ var rememberMe = $(dialogId + ' input[name=remember_me]').is(':checked')
+
+ rest.login({email: email, password: password, remember_me: rememberMe})
+ .done(function() {
+ app.layout.closeDialog('signin-dialog')
+ window.location = '/client'
+ })
+ .fail(function(jqXHR) {
+ if(jqXHR.status == 422) {
+ $(dialogId + ' #signin-form').addClass('login-error')
+ }
+ else {
+ app.notifyServerError(jqXHR, "Unable to log in")
+ }
+ })
+ }
+
+ function events() {
+ $(dialogId + ' .signin-cancel').click(function(e) {
+ app.layout.closeDialog('signin-dialog');
+ e.stopPropagation();
+ return false;
+ });
+
+ $(dialogId + ' #signin-form').submit(function(e) {
+ login();
+ return false;
+ });
+
+ $(dialogId + ' .signin-submit').click(function(e) {
+ login();
+ return false;
+ });
+
+ $(dialogId + ' .show-signup-dialog').click(function(e) {
+ app.layout.closeDialog('signin-dialog')
+ app.layout.showDialog('signup-dialog')
+ return false;
+ })
+ }
+
+ function beforeShow() {
+ reset();
+ }
+
+ function afterHide() {
+
+ }
+
+ function initialize(){
+
+ var dialogBindings = {
+ 'beforeShow' : beforeShow,
+ 'afterHide': afterHide
+ };
+
+ app.bindDialog('signin-dialog', dialogBindings);
+
+ events();
+ }
+
+ this.initialize = initialize;
+
+ }
+})(window, jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/web/signupDialog.js b/web/app/assets/javascripts/web/signupDialog.js
index 5320d5a88..fc126cb57 100644
--- a/web/app/assets/javascripts/web/signupDialog.js
+++ b/web/app/assets/javascripts/web/signupDialog.js
@@ -10,8 +10,17 @@
var dialogId = '#signup-dialog';
function events() {
+ $(dialogId + ' .signup-cancel').click(function(e) {
+ app.layout.closeDialog('signup-dialog');
+ e.stopPropagation();
+ return false;
+ });
-
+ $(dialogId + ' .show-signin-dialog').click(function(e) {
+ app.layout.closeDialog('signup-dialog')
+ app.layout.showDialog('signin-dialog')
+ return false;
+ })
}
function beforeShow() {
diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js
index 920e82019..e59c4512b 100644
--- a/web/app/assets/javascripts/web/web.js
+++ b/web/app/assets/javascripts/web/web.js
@@ -7,6 +7,7 @@
//= require globals
//= require facebook_helper
//= require web/signupDialog
+//= require web/signinDialog
//= require invitationDialog
//= require shareDialog
//= require layout
@@ -21,3 +22,4 @@
//= require web/congratulations
//= require web/sessions
//= require web/recordings
+//= require web/welcome
diff --git a/web/app/assets/javascripts/web/welcome.js b/web/app/assets/javascripts/web/welcome.js
index 7d4728e03..582e6d220 100644
--- a/web/app/assets/javascripts/web/welcome.js
+++ b/web/app/assets/javascripts/web/welcome.js
@@ -10,8 +10,16 @@
e.preventDefault();
return false;
});
+
+ $('#signin').click(function(e) {
+ context.JK.app.layout.showDialog('signin-dialog');
+ e.preventDefault();
+ return false;
+ });
}
- initialize()
+ $(function() {
+ initialize();
+ })
})(window, jQuery);
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss
index a7a4d6584..807a4ae93 100644
--- a/web/app/assets/stylesheets/client/content.css.scss
+++ b/web/app/assets/stylesheets/client/content.css.scss
@@ -190,13 +190,17 @@
font-size:24px;
}
-.content-wrapper select, .content-wrapper textarea, .content-wrapper input[type=text], .content-wrapper input[type=password], div.friendbox, .ftue-inner input[type=text], .ftue-inner input[type=password], .dialog-inner textarea, .dialog-inner input[type=text], .dialog-inner select {
- font-family:"Raleway", arial, sans-serif;
- background-color:#c5c5c5;
- border:none;
- -webkit-box-shadow: inset 2px 2px 3px 0px #888;
- box-shadow: inset 2px 2px 3px 0px #888;
- color:#666;
+.content-wrapper, .dialog, .dialog-inner, .ftue-inner {
+
+ select, textarea, input[type=text], input[type=password], div.friendbox {
+ font-family:"Raleway", arial, sans-serif;
+ background-color:#c5c5c5;
+ border:none;
+ -webkit-box-shadow: inset 2px 2px 3px 0px #888;
+ box-shadow: inset 2px 2px 3px 0px #888;
+ color:#666;
+ }
+
}
.create-session-description {
diff --git a/web/app/assets/stylesheets/client/screen_common.css.scss b/web/app/assets/stylesheets/client/screen_common.css.scss
index fe9d3497b..fbc3dbdf9 100644
--- a/web/app/assets/stylesheets/client/screen_common.css.scss
+++ b/web/app/assets/stylesheets/client/screen_common.css.scss
@@ -353,7 +353,6 @@ small, .small {font-size:11px;}
position:absolute;
left:50%;
top:20%;
- margin-left:-150px;
background-color:#333;
border: 1px solid #ed3618;
z-index:1000;
diff --git a/web/app/assets/stylesheets/client/user_dropdown.css.scss b/web/app/assets/stylesheets/client/user_dropdown.css.scss
index 42e8081af..79096c8b8 100644
--- a/web/app/assets/stylesheets/client/user_dropdown.css.scss
+++ b/web/app/assets/stylesheets/client/user_dropdown.css.scss
@@ -9,7 +9,6 @@
#profile {
float: right;
height: 54px;
- margin-top: 30px;
text-align: right;
ul {
diff --git a/web/app/assets/stylesheets/users/signinDialog.css.scss b/web/app/assets/stylesheets/users/signinDialog.css.scss
new file mode 100644
index 000000000..3bcb8cc63
--- /dev/null
+++ b/web/app/assets/stylesheets/users/signinDialog.css.scss
@@ -0,0 +1,56 @@
+#signin-dialog {
+ height:auto;
+}
+
+#signin-dialog {
+
+ div.field {
+ width:100%;
+ }
+
+ div.overlay-inner {
+ height:auto;
+ }
+
+ label {
+ margin-bottom:2px;
+ }
+
+ div.email {
+ margin-top:5px;
+ }
+
+ div.password {
+ margin-top:20px;
+ }
+
+ div.actions {
+ margin-top:20px;
+ }
+
+ .login-error {
+ background-color: #330000;
+ border: 1px solid #990000;
+ padding:4px;
+
+ div.actions {
+ margin-top:10px;
+ }
+ }
+
+ .login-error-msg {
+ display:none;
+ margin-top:10px;
+ text-align:center;
+ color:#F00;
+ font-size:11px;
+ }
+
+ .login-error .login-error-msg {
+ display:block;
+ }
+
+ input[type=text], input[type=password]{
+ box-sizing: border-box;
+ }
+}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css
index 712b85f30..d2d554ed6 100644
--- a/web/app/assets/stylesheets/web/web.css
+++ b/web/app/assets/stylesheets/web/web.css
@@ -14,4 +14,5 @@
*= require web/recordings
*= require web/welcome
#= require web/sessions
+*= require users/signinDialog
*/
\ No newline at end of file
diff --git a/web/app/controllers/api_auths_controller.rb b/web/app/controllers/api_auths_controller.rb
new file mode 100644
index 000000000..00001a7e4
--- /dev/null
+++ b/web/app/controllers/api_auths_controller.rb
@@ -0,0 +1,22 @@
+class ApiAuthsController < ApiController
+
+ respond_to :json
+
+ def login
+ user = User.authenticate(params[:email], params[:password])
+
+ if user.nil?
+ render :json => {}, :status => 422
+ else
+ if jkclient_agent?
+ user.update_progression_field(:first_ran_client_at)
+ end
+
+ @session_only_cookie = !jkclient_agent? && !params[:remember_me]
+
+ sign_in user
+
+ render :json => {}, :status => :ok
+ end
+ end
+end
diff --git a/web/app/controllers/api_mixes_controller.rb b/web/app/controllers/api_mixes_controller.rb
index 60944c480..26e9ded8d 100644
--- a/web/app/controllers/api_mixes_controller.rb
+++ b/web/app/controllers/api_mixes_controller.rb
@@ -20,15 +20,7 @@ class ApiMixesController < ApiController
render :json => { :message => "next mix could not be found" }, :status => 403
end
end
-
- def finish
- begin
- @mix.finish
- rescue
- render :json => { :message => "mix finish failed" }, :status => 403
- end
- respond_with responder: ApiResponder, :status => 204
- end
+
def download
@mix = Mix.find(params[:id])
diff --git a/web/app/controllers/api_sessions_controller.rb b/web/app/controllers/api_sessions_controller.rb
new file mode 100644
index 000000000..b2f860747
--- /dev/null
+++ b/web/app/controllers/api_sessions_controller.rb
@@ -0,0 +1,20 @@
+class ApiSearchController < ApiController
+
+ def login
+ user = User.authenticate(params[:email], params[:password])
+
+ if user.nil?
+ render :json => {}, :status => 422
+ else
+ if jkclient_agent?
+ user.update_progression_field(:first_ran_client_at)
+ end
+
+ @session_only_cookie = !jkclient_agent? && 0 == params[:remember_me].to_i
+
+ sign_in user
+
+ render :json => {}, :status => :ok
+ end
+ end
+end
diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb
index 0565d95b5..01eb5107e 100644
--- a/web/app/controllers/api_users_controller.rb
+++ b/web/app/controllers/api_users_controller.rb
@@ -27,32 +27,6 @@ class ApiUsersController < ApiController
respond_with @user, responder: ApiResponder, :status => 200
end
- # this API call is disabled by virtue of it being commented out in routes.rb
- # the reason is that it has no captcha, and is therefore a bit abuseable
- # if someone wants to use it, please add in captcha or some other bot-protector
- def create
- # sends email to email account for confirmation
- @user = UserManager.new.signup(params[:first_name],
- params[:last_name],
- params[:email],
- params[:password],
- params[:password_confirmation],
- params[:city],
- params[:state],
- params[:country],
- params[:instruments],
- params[:photo_url],
- ApplicationHelper.base_uri(request) + "/confirm")
-
- # check for errors
- unless @user.errors.any?
- render :json => {}, :status => :ok # an empty response, but 200 OK
- else
- response.status = :unprocessable_entity
- respond_with @user, responder: ApiResponder
- end
- end
-
def update
@user = User.find(params[:id])
diff --git a/web/app/controllers/clients_controller.rb b/web/app/controllers/clients_controller.rb
index 009256e40..d8dde3f7a 100644
--- a/web/app/controllers/clients_controller.rb
+++ b/web/app/controllers/clients_controller.rb
@@ -35,7 +35,7 @@ class ClientsController < ApplicationController
if current_user
render :layout => 'client'
else
- redirect_to "/signin"
+ redirect_to root_url
end
end
diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb
index 45e019b27..019c52b99 100644
--- a/web/app/controllers/sessions_controller.rb
+++ b/web/app/controllers/sessions_controller.rb
@@ -48,15 +48,10 @@ class SessionsController < ApplicationController
# an email and whatnot.
#
# Also, should we grab their photo from facebook?
- user = UserManager.new.signup(remote_ip(),
- auth_hash[:info][:first_name],
- auth_hash[:info][:last_name],
- auth_hash[:info][:email],
- nil,
- nil,
- nil, # instruments
- nil, # photo_url
- nil)
+ user = UserManager.new.signup(remote_ip: remote_ip(),
+ first_name: auth_hash[:info][:first_name],
+ last_name: auth_hash[:info][:last_name],
+ email: auth_hash[:info][:email])
# Users who sign up using oauth are presumed to have valid email adddresses.
user.confirm_email!
@@ -72,18 +67,49 @@ class SessionsController < ApplicationController
def oauth_callback
+
+ auth_hash = request.env['omniauth.auth']
+
+ provider = auth_hash[:provider]
+
+ if provider == 'facebook'
+ fb_uid = auth_hash[:uid]
+ token = auth_hash[:credentials][:token]
+ token_expiration = Time.at(auth_hash[:credentials][:expires_at])
+ first_name = auth_hash[:extra][:raw_info][:first_name]
+ last_name = auth_hash[:extra][:raw_info][:last_name]
+ email = auth_hash[:extra][:raw_info][:email]
+ gender = auth_hash[:extra][:raw_info][:gender]
+
+ fb_signup = FacebookSignup.new
+ fb_signup.uid = fb_uid
+ fb_signup.token = token
+ fb_signup.token_expires_at = token_expiration
+ fb_signup.first_name = first_name
+ fb_signup.last_name = last_name
+ fb_signup.email = email
+ if gender == 'male'
+ fb_signup.gender = 'M'
+ elsif gender == 'female'
+ fb_signup.gender = 'F'
+ end
+ fb_signup.save!
+
+ redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}"
+ return
+ end
+
if current_user.nil?
render :nothing => true, :status => 404
return
end
- auth_hash = request.env['omniauth.auth']
#authorization = UserAuthorization.find_by_provider_and_uid(auth_hash["provider"], auth_hash["uid"])
# Always make and save a new authorization. This is because they expire, and honestly there's no cost
# to just making and saving it.
#if authorization.nil?
- authorization = current_user.user_authorizations.build :provider => auth_hash[:provider],
+ authorization = current_user.user_authorizations.build :provider => auth_hash[:provider],
:uid => auth_hash[:uid],
:token => auth_hash[:credentials][:token],
:token_expiration => Time.at(auth_hash[:credentials][:expires_at])
diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb
index e2aae2132..6c98a031d 100644
--- a/web/app/controllers/users_controller.rb
+++ b/web/app/controllers/users_controller.rb
@@ -27,6 +27,33 @@ class UsersController < ApplicationController
return
end
+ @fb_signup = load_facebook_signup(params)
+
+
+ # check if the email specified by @fb_signup already exists in the databse--if so, log them in and redirect
+ if @fb_signup && @fb_signup.email
+ user = User.find_by_email_and_email_confirmed(@fb_signup, true)
+ if user
+ # update user_authorization for user because this is fresher
+ user.update_fb_authorization(@fb_signup)
+ sign_in(user)
+ redirect_to client_url
+ return
+ end
+ end
+
+ # check if the uid specified by @fb_signup already exists in the databse--if so, log them in and redirect
+ if @fb_signup && @fb_signup.uid
+ user_authorization = UserAuthorization.find_by_uid_and_provider(@fb_signup.uid, 'facebook')
+ # update user_authorization for user because this is fresher
+ if user_authorization
+ user_authorization.user.update_fb_authorization(@fb_signup)
+ sign_in(user_authorization.user)
+ redirect_to client_url
+ return
+ end
+ end
+
@invited_user = load_invited_user(params)
if !@invited_user.nil? && @invited_user.has_required_email? && @invited_user.accepted
@@ -34,7 +61,7 @@ class UsersController < ApplicationController
render "already_signed_up", :layout => 'landing'
return
end
- @signup_postback = load_postback(@invited_user)
+ @signup_postback = load_postback(@invited_user, @fb_signup)
load_location(request.remote_ip)
@@ -42,21 +69,54 @@ class UsersController < ApplicationController
@user.musician = true # default the UI to musician as selected option
# preseed the form with the invited email as a convenience to the user
- unless @invited_user.nil?
- @user.email = @invited_user.email
+ @user.email = @invited_user.email unless @invited_user.nil?
+
+ if @fb_signup
+ @user.email = @fb_signup.email
+ @user.first_name = @fb_signup.first_name
+ @user.last_name = @fb_signup.last_name
+ @user.gender = @fb_signup.gender
end
render :layout => 'web'
end
def create
+
if current_user
redirect_to client_url
return
end
+ @fb_signup = load_facebook_signup(params)
+
+ # check if the email specified by @fb_signup already exists in the databse--if so, log them in and redirect
+ if @fb_signup && @fb_signup.email
+ user = User.find_by_email_and_email_confirmed(@fb_signup, true)
+ if user
+ # update user_authorization for user because this is fresher
+ user.update_fb_authorization(@fb_signup)
+ sign_in(user)
+ redirect_to client_url
+ return
+ end
+ end
+
+ # check if the uid specified by @fb_signup already exists in the databse--if so, log them in and redirect
+ if @fb_signup && @fb_signup.uid
+ user_authorization = UserAuthorization.find_by_uid_and_provider(@fb_signup.uid, 'facebook')
+ # update user_authorization for user because this is fresher
+ if user_authorization
+ user_authorization.user.update_fb_authorization(@fb_signup)
+ sign_in(user_authorization.user)
+ redirect_to client_url
+ return
+ end
+
+ end
+
@invited_user = load_invited_user(params)
- @signup_postback = load_postback(@invited_user)
+ @signup_postback = load_postback(@invited_user, @fb_signup)
@user = User.new
@@ -73,21 +133,20 @@ class UsersController < ApplicationController
terms_of_service = params[:jam_ruby_user][:terms_of_service].nil? ? false : true
musician = params[:jam_ruby_user][:musician]
-
- @user = UserManager.new.signup(request.remote_ip,
- params[:jam_ruby_user][:first_name],
- params[:jam_ruby_user][:last_name],
- params[:jam_ruby_user][:email],
- params[:jam_ruby_user][:password],
- params[:jam_ruby_user][:password_confirmation],
- terms_of_service,
- instruments,
- birth_date,
- location,
- musician,
- nil, # we don't accept photo url on the signup form yet
- @invited_user,
- ApplicationHelper.base_uri(request) + "/confirm")
+ @user = UserManager.new.signup(remote_ip: request.remote_ip,
+ first_name: params[:jam_ruby_user][:first_name],
+ last_name: params[:jam_ruby_user][:last_name],
+ email: params[:jam_ruby_user][:email],
+ password: params[:jam_ruby_user][:password],
+ password_confirmation: params[:jam_ruby_user][:password_confirmation],
+ terms_of_service: terms_of_service,
+ instruments: instruments,
+ birth_date: birth_date,
+ location: location,
+ musician: musician,
+ invited_user: @invited_user,
+ fb_signup: @fb_signup,
+ signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm")
# check for errors
if @user.errors.any?
@@ -308,6 +367,12 @@ class UsersController < ApplicationController
return Date.new(year.to_i, month.to_i, day.to_i)
end
+ def load_facebook_signup(params)
+ lookup_id = params[:facebook_signup]
+
+ FacebookSignup.find_by_lookup_id(lookup_id)
+ end
+
def load_invited_user(params)
# check if this an anonymous request, or result of invitation code
invitation_code = params[:invitation_code]
@@ -336,11 +401,10 @@ class UsersController < ApplicationController
@cities = @location[:state].nil? ? [] : MaxMindManager.cities(@location[:country], @location[:state])
end
- def load_postback(invited_user)
- if invited_user.nil?
- signup_path
- else
- signup_path + "?invitation_code=" + invited_user.invitation_code
- end
+ def load_postback(invited_user, fb_signup)
+ query = {}
+ query[:invitation_code] = invited_user.invitation_code if invited_user
+ query[:facebook_signup] = fb_signup.lookup_id if fb_signup
+ signup_path + "?" + params.to_query
end
end
diff --git a/web/app/views/api_claimed_recordings/show.rabl b/web/app/views/api_claimed_recordings/show.rabl
index f23967a14..c487f0d22 100644
--- a/web/app/views/api_claimed_recordings/show.rabl
+++ b/web/app/views/api_claimed_recordings/show.rabl
@@ -18,7 +18,7 @@ child(:recording => :recording) {
}
child(:mixes => :mixes) {
- attributes :id, :url, :is_completed
+ attributes :id, :mp3_url, :ogg_url :is_completed
}
child(:recorded_tracks => :recorded_tracks) {
diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl
index 54a4b5e83..3c49ffc1b 100644
--- a/web/app/views/api_music_sessions/show.rabl
+++ b/web/app/views/api_music_sessions/show.rabl
@@ -53,7 +53,7 @@ node(:claimed_recording, :if => lambda { |music_session| music_session.users.exi
}
child(:mixes => :mixes) {
- attributes :id, :url, :is_completed
+ attributes :id, :mp3_url, :ogg_url, :is_completed
}
child(:recorded_tracks => :recorded_tracks) {
diff --git a/web/app/views/clients/_shareDialog.html.erb b/web/app/views/clients/_shareDialog.html.erb
index 84f5699b5..9c411df14 100644
--- a/web/app/views/clients/_shareDialog.html.erb
+++ b/web/app/views/clients/_shareDialog.html.erb
@@ -1,6 +1,6 @@
-
-
share this
+
+
@@ -16,7 +16,7 @@
<%= image_tag "content/icon_google.png", :size => "24x24", :align => "absmiddle", :alt => "", :style => "vertical-align:middle", :class => "share-with-google" %>
-
+
diff --git a/web/app/views/layouts/web.erb b/web/app/views/layouts/web.erb
index 58c2b22a4..e167c9434 100644
--- a/web/app/views/layouts/web.erb
+++ b/web/app/views/layouts/web.erb
@@ -50,6 +50,7 @@
<%= render "clients/invitationDialog" %>
<%= render "users/signupDialog" %>
+ <%= render "users/signinDialog" %>
|