merge develop

This commit is contained in:
Brian Smith 2014-02-04 20:21:24 -05:00
commit 9e72e6510a
81 changed files with 1360 additions and 316 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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
share_token.sql
facebook_signup.sql
audiomixer_mp3.sql

9
db/up/audiomixer_mp3.sql Normal file
View File

@ -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);

16
db/up/facebook_signup.sql Normal file
View File

@ -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);

View File

@ -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

View File

@ -13,7 +13,7 @@
<% end %>
</td>
<td width="70%"><font color="#ccc"><%= user.biography %></font><br /><br />
<a style="<%= link_style %>" href="http://<%= @host %>/#/profile/<%= user.id %>">Profile</a>&nbsp;&nbsp;<!--<a style="<%= link_style %>" href="">Friend</a>-->
<a style="<%= link_style %>" href="http://<%= @host %>/client#/profile/<%= user.id %>">Profile</a>&nbsp;&nbsp;<!--<a style="<%= link_style %>" href="">Friend</a>-->
</td>
</tr>
<tr><td colspan="3"></td></tr>

View File

@ -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 %>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/'

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -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;
});
}

View File

@ -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,

View File

@ -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,

View File

@ -88,7 +88,7 @@
events();
$('.profile').on('click', function() {
context.location = '#/profile/' + context.JK.currentUserId;
context.location = '/client#/profile/' + context.JK.currentUserId;
});
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -168,6 +168,7 @@
currentTimeMs = playbackDurationMs;
stopPlay();
endReached = true;
console.log("end reached");
}
else {
return;

View File

@ -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
});

View File

@ -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
};

View File

@ -5,14 +5,22 @@
context.JK.ShareDialog = function(app, entityId, entityType) {
var logger = context.JK.logger;
var rest = context.JK.Rest();
var dialogId = '#share-dialog'
function registerEvents(onOff) {
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() {
@ -78,69 +86,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('<div style="text-align: center; margin-top: 100px;">Loading your contacts...</div>');
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("<label><input type='checkbox' class='invitation-checkbox' data-email='" + response[i] + "' /> " + response[i] + "</label>");
}
$('.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() {
}
@ -159,9 +104,9 @@
'afterHide': afterHide
};
app.bindDialog('shareSessionRecording', dialogBindings);
app.bindDialog('shareRecording', dialogBindings);
initDialog();
// callFB(fbAppID);
};
this.initialize = initialize;

View File

@ -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);

View File

@ -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() {
@ -31,7 +40,6 @@
app.bindDialog('signup-dialog', dialogBindings);
console.log("honuth")
events();
}

View File

@ -6,6 +6,7 @@
//= require AAC_underscore
//= require globals
//= require web/signupDialog
//= require web/signinDialog
//= require invitationDialog
//= require shareDialog
//= require layout
@ -20,3 +21,4 @@
//= require web/congratulations
//= require web/sessions
//= require web/recordings
//= require web/welcome

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -9,7 +9,6 @@
#profile {
float: right;
height: 54px;
margin-top: 30px;
text-align: right;
ul {

View File

@ -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;
}
}

View File

@ -14,4 +14,5 @@
*= require web/recordings
*= require web/welcome
#= require web/sessions
*= require users/signinDialog
*/

View File

@ -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

View File

@ -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])

View File

@ -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

View File

@ -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])

View File

@ -35,7 +35,7 @@ class ClientsController < ApplicationController
if current_user
render :layout => 'client'
else
redirect_to "/signin"
redirect_to root_url
end
end

View File

@ -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])

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -1,6 +1,6 @@
<!-- Share dialog -->
<div class="dialog share-overlay" layout="dialog" layout-id="share-dialog" style="width:800px; height:auto;">
<div class="content-head"><h1>share this <span id="shareType"></span></h1></div>
<div class="dialog share-overlay" layout="dialog" layout-id="share-dialog" id="share-dialog" style="width:800px; height:auto;">
<div class="content-head"><h1> <span id="shareType"></span></h1></div>
<div class="dialog-inner">
<div class="right"> <a class="button-orange" layout-action="close">X CLOSE</a></div>
<table class="w100">
@ -15,13 +15,13 @@
<input type="checkbox" />
<%= image_tag "content/icon_google.png", :size => "24x24", :align => "absmiddle", :alt => "", :style => "vertical-align:middle" %>&nbsp;
</div>
<div class=" right mr10 mt5"><a class="button-orange" id="dialog-share-button">SHARE</a></div>
<div class=" right mr10 mt5"><a class="button-orange dialog-share-button">SHARE</a></div>
</td>
<td valign="top" width="48%">
<div class="ml10">
<h3>Share a Link:</h3><br />
<% unless share_token.blank? %>
<%= "#{root_url}#{share_token}" %>
<%= true ? '' : "#{root_url}#{share_token}" %>
<% end %>
<div class="right"><a class="button-orange">COPY LINK</a></div>
</div>

View File

@ -50,6 +50,7 @@
<%= render "clients/invitationDialog" %>
<%= render "users/signupDialog" %>
<%= render "users/signinDialog" %>
<script type="text/javascript">
$(function () {
@ -73,6 +74,9 @@
var signupDialog = new JK.SignupDialog(JK.app);
signupDialog.initialize();
var signinDialog = new JK.SigninDialog(JK.app);
signinDialog.initialize();
})
</script>

View File

@ -0,0 +1,59 @@
<div class="dialog thin-dialog overlay-small" layout-id="signin-dialog" id="signin-dialog">
<!-- ftue header -->
<div class="content-head">
<h1>sign in</h1>
</div>
<!-- inner wrapper -->
<div class="overlay-inner">
<%= link_to image_tag("content/button_facebook_signin.png", {:width => 249, :height => 46}), '/auth/facebook', class: "signin-facebook" %>
<br>
<br>
<br>
<strong class="white">Or sign in with JamKazam Account</strong>
<br>
<br>
<form id="signin-form" method="post" action="/">
<div class="field email">
<label for="email">Email Address:</label>
<input type="text" name="email"/>
</div>
<div class="field password">
<label for="password">Password:</label>
<input type="password" name="password"/>
</div>
<small><input name="remember_me" type="checkbox"> Keep me signed in</small>
<div class="login-error-msg">Invalid login</div>
<br clear="all"/>
<div align="center" class="actions">
<a href="web_home.html" class="button-grey signin-cancel">CANCEL</a>&nbsp;&nbsp;<input type="submit" value="SIGN IN" href="#" class="button-orange m0 signin-submit" />
<br>
<br>
<small><a class='forgot-password' href="/request_reset_password">Forgot Password?</a></small>
</div>
</form>
<br>
<div class="center">
<small>Don't have an account? <a href="#" class="show-signup-dialog">Sign Up</a></small>
</div>
</div>
<!-- end inner -->
<br clear="all">
</div>

View File

@ -8,7 +8,7 @@
<!-- inner wrapper -->
<div class="overlay-inner">
<%= image_tag "content/button_facebook_signup.png", {:width => 249, :height => 46 } %>
<%= link_to image_tag("content/button_facebook_signup.png", {:width => 249, :height => 46 }), '/auth/facebook', class: "signup-facebook" %>
<br>
<br><br>
@ -16,14 +16,14 @@
<br>
<br>
<div class="center"><%= link_to "SIGN UP WITH YOUR EMAIL", signup_path, class: "button-orange block" %>
<div class="center"><%= link_to "SIGN UP WITH YOUR EMAIL", signup_path, class: "button-orange block signup-email" %>
<br>
<div class="center">
<small>Already have an account? <a href="#" class='signin'>Sign In</a><br>
<small>Already have an account? <a href="#" class='show-signin-dialog'>Sign In</a><br>
<br>
<a href="#" layout-action="close">Cancel</a></small>
<a href="#" class="signup-cancel">Cancel</a></small>
</div>
</div>
<!-- end inner -->

View File

@ -13,6 +13,4 @@
Have questions about how JamKazam works?
<a href="#" id="faq-open">Here are some answers</a>.
<% end %>
<% end %>
<%= javascript_include_tag "web/welcome" %>
<% end %>

View File

@ -111,7 +111,7 @@ include JamRuby
config.websocket_gateway_connect_time_expire = 6000
end
config.websocket_gateway_internal_debug = false
config.websocket_gateway_port = 6767
config.websocket_gateway_port = 6767 + ENV['JAM_INSTANCE'].to_i
# Runs the websocket gateway within the web app
config.websocket_gateway_uri = "ws://localhost:#{config.websocket_gateway_port}/websocket"
@ -173,6 +173,7 @@ include JamRuby
config.redis_host = "localhost:6379"
config.audiomixer_path = "/var/lib/audiomixer/audiomixer/audiomixerapp"
config.ffmpeg_path = ENV['FFMPEG_PATH'] || (File.exist?('/usr/local/bin/ffmpeg') ? '/usr/local/bin/ffmpeg' : '/usr/bin/ffmpeg')
# if it looks like linux, use init.d script; otherwise use kill
config.icecast_reload_cmd = ENV['ICECAST_RELOAD_CMD'] || (File.exist?('/usr/local/bin/icecast2') ? "bash -l -c #{Shellwords.escape("sudo /etc/init.d/icecast2 reload")}" : "bash -l -c #{Shellwords.escape("kill -1 `ps -f | grep /usr/local/bin/icecast | grep -v grep | awk \'{print $2}\'`")}")
@ -194,5 +195,8 @@ include JamRuby
config.email_smtp_user_name = 'jamkazam'
config.email_smtp_password = 'jamjamblueberryjam'
config.email_smtp_starttls_auto = true
config.facebook_app_id = '468555793186398'
config.facebook_app_secret = '546a5b253972f3e2e8b36d9a3dd5a06e'
end
end

View File

@ -4,3 +4,16 @@ require 'rubygems'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
require 'rails/commands/server'
module Rails
class Server
alias :default_options_alias :default_options
def default_options
default_options_alias.merge!(
:Port => 3000 + ENV['JAM_INSTANCE'].to_i,
:pid => File.expand_path("tmp/pids/server-#{ENV['JAM_INSTANCE'].to_i}.pid"))
end
end
end

View File

@ -86,4 +86,7 @@ SampleApp::Application.configure do
config.fp_secret = 'HZBIMSOI5VAQ5LXT4XLG6XA7IE'
config.allow_force_native_client = false
config.facebook_app_id = '1412328362347190' # staging
config.facebook_app_secret = '8b1f20430356d44fb49c0a504a9ff401' # staging
end

View File

@ -59,5 +59,8 @@ SampleApp::Application.configure do
config.aws_secret_access_key = 'h0V0ffr3JOp/UtgaGrRfAk25KHNiO9gm8Pj9m6v3'
config.icecast_wait_after_reload = 0
config.facebook_app_id = '1441492266082868'
config.facebook_app_secret = '233bd040a07e47dcec1cff3e490bfce7'
end

View File

@ -1,5 +1,5 @@
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, '468555793186398', '546a5b253972f3e2e8b36d9a3dd5a06e', {name: "facebook", :scope => 'email,user_location'}
provider :facebook, Rails.application.config.facebook_app_id, Rails.application.config.facebook_app_secret, {name: "facebook", :scope => 'email,user_location'}
provider :google_oauth2, Rails.application.config.google_client_id, Rails.application.config.google_secret, {name: "google_login", approval_prompt: '', scope: 'userinfo.email, userinfo.profile, https://www.google.com/m8/feeds'}
end

View File

@ -94,6 +94,9 @@ SampleApp::Application.routes.draw do
end
scope '/api' do
match '/auths/login' => 'api_auths#login', :via => :post
# music sessions
match '/sessions/:id/participants' => 'api_music_sessions#participant_create', :via => :post
match '/participants/:id' => 'api_music_sessions#participant_show', :via => :get, :as => 'api_session_participant_detail'
@ -314,7 +317,6 @@ SampleApp::Application.routes.draw do
# Mixes
match '/mixes/schedule' => 'api_mixes#schedule', :via => :post
match '/mixes/next' => 'api_mixes#next', :via => :get
match '/mixes/:id/finish' => 'api_mixes#finish', :via => :put
match '/mixes/:id/download' => 'api_mixes#download', :via => :get
# version check for JamClient

View File

@ -9,9 +9,13 @@ IcecastConfigRetry:
class: "JamRuby::IcecastConfigRetry"
description: "Finds icecast servers that have had their config_changed, but no IcecastConfigWriter check recently"
IcecastSourceCheck:
cron: "10 * * * * *"
class: "JamRuby::IcecastSourceCheck"
description: "Finds icecast mounts that need their 'sourced' state to change, but haven't in some time"
CleanupFacebookSignup:
cron: "30 2 * * *"
class: "JamRuby::CleanupFacebookSignup"
description: "Deletes facebook_signups that are old"

View File

@ -10,8 +10,22 @@ class UserManager < BaseManager
# Note that almost everything can be nil here. This is because when users sign up via social media,
# we don't know much about them.
def signup(remote_ip, first_name, last_name, email, password = nil, password_confirmation = nil, terms_of_service = nil,
instruments = nil, birth_date = nil, location = nil, musician = nil, photo_url = nil, invited_user = nil, signup_confirm_url = nil)
def signup(options)
remote_ip = options[:remote_ip]
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]
instruments = options[:instruments]
birth_date = options[:birth_date]
location = options[:location]
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
@ -33,8 +47,20 @@ class UserManager < BaseManager
# return @user # @user.errors.any? is true now
#else
# sends email to email account for confirmation
@user = User.signup(first_name, last_name, email, password, password_confirmation, terms_of_service,
location, instruments, birth_date, musician, photo_url, invited_user, signup_confirm_url)
@user = User.signup(first_name: first_name,
last_name: last_name,
email: email,
password: password,
password_confirmation: password_confirmation,
terms_of_service: terms_of_service,
location: location,
instruments: instruments,
birth_date: birth_date,
musician: musician,
photo_url: photo_url,
invited_user: invited_user,
fb_signup: fb_signup,
signup_confirm_url: signup_confirm_url)
return @user
#end

View File

@ -6,4 +6,10 @@ stop on runlevel [016]
setuid jam-web
setgid jam-web
pre-start script
set -e
mkdir -p /var/run/jam-web
chown jam-web:jam-web /var/run/jam-web
end script
exec start-stop-daemon --start --chdir /var/lib/jam-web --exec /var/lib/jam-web/script/package/upstart-run.sh

View File

@ -14,12 +14,10 @@ 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
# make log folders for jobs
mkdir -p /var/log/any-job-worker

View File

@ -70,18 +70,6 @@ describe SessionsController do
visit '/auth/facebook'
end.should change(User, :count).by(0)
end
it "should not create a user when oauth comes in with a currently existing user" do
user = FactoryGirl.create(:user) # in the jam session
OmniAuth.config.mock_auth[:facebook][:info][:email] = user.email
OmniAuth.config.mock_auth[:facebook] = OmniAuth.config.mock_auth[:facebook]
lambda do
visit '/auth/facebook'
end.should change(User, :count).by(0)
end
end

View File

@ -308,5 +308,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

View File

@ -62,7 +62,7 @@ describe "Authentication", :js => true, :type => :feature, :capybara_feature =>
find('.userinfo .sign-out a').trigger(:click)
end
it { page.should have_title("JamKazam | Sign in") }
it { find('h1', text: 'Play music together over the Internet as if in the same room') }
end
end
end

View File

@ -83,9 +83,12 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
before do
@invited_user = FactoryGirl.create(:invited_user, :email => "noone@jamkazam.com")
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
find('#jam_ruby_user_first_name')
sleep 1 # if I don't do this, first_name and/or last name intermittently fail to fill out
UserMailer.deliveries.clear
fill_in "jam_ruby_user[first_name]", with: "Mike"
fill_in "jam_ruby_user[first_name]", with: "Mike"
fill_in "jam_ruby_user[last_name]", with: "Jones"
fill_in "jam_ruby_user[email]", with: "newuser2@jamkazam.com"
fill_in "jam_ruby_user[password]", with: "jam123"
@ -110,6 +113,8 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
@user = FactoryGirl.create(:user)
@invited_user = FactoryGirl.create(:invited_user, :sender => @user, :autofriend => true, :email => "noone@jamkazam.com")
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
find('#jam_ruby_user_first_name')
sleep 1 # if I don't do this, first_name and/or last name intermittently fail to fill out
fill_in "jam_ruby_user[first_name]", with: "Mike"
fill_in "jam_ruby_user[last_name]", with: "Jones"
@ -136,6 +141,8 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
before do
@invited_user = FactoryGirl.create(:invited_user, :email => "noone@jamkazam.com")
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
find('#jam_ruby_user_first_name')
sleep 1 # if I don't do this, first_name and/or last name intermittently fail to fill out
fill_in "jam_ruby_user[first_name]", with: "Mike"
fill_in "jam_ruby_user[last_name]", with: "Jones"
@ -155,10 +162,54 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
end
def signup_invited_user
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
find('#jam_ruby_user_first_name')
sleep 1 # if I don't do this, first_name and/or last name intermittently fail to fill out
fill_in "jam_ruby_user[first_name]", with: "Mike"
fill_in "jam_ruby_user[last_name]", with: "Jones"
@invited_user_email = "newuser#{rand(10000)}@jamkazam.com"
fill_in "jam_ruby_user[email]", with: @invited_user_email
fill_in "jam_ruby_user[password]", with: "jam123"
fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
check("jam_ruby_user[instruments][drums][selected]")
check("jam_ruby_user[terms_of_service]")
click_button "CREATE ACCOUNT"
end
def signup_good
should have_title("JamKazam")
should have_selector('div.tagline', text: "Congratulations!")
@user.friends?(User.find_by_email(@invited_user_email))
User.find_by_email(@invited_user_email).friends?(@user)
uri = URI.parse(current_url)
"#{uri.path}?#{uri.query}".should == congratulations_musician_path(:type => 'Native')
end
describe "can signup with facebook link multiple times with same invite" do
before do
@user = FactoryGirl.create(:user)
@invited_user = FactoryGirl.create(:invited_user, :sender => @user, :autofriend => true, :email => "noone@jamkazam.com", :invite_medium => InvitedUser::FB_MEDIUM)
end
# Successful sign-in goes to the client
it {
signup_invited_user
signup_good
}
it {
signup_invited_user
signup_good
}
end
describe "can signup with an email different than the one used to invite" do
before do
@invited_user = FactoryGirl.create(:invited_user, :email => "what@jamkazam.com")
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
find('#jam_ruby_user_first_name')
sleep 1 # if I don't do this, first_name and/or last name intermittently fail to fill out
UserMailer.deliveries.clear

View File

@ -0,0 +1,150 @@
require 'spec_helper'
describe "Welcome", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
before(:all) do
Capybara.javascript_driver = :poltergeist
Capybara.current_driver = Capybara.javascript_driver
Capybara.default_wait_time = 10
end
before(:each) do
page.driver.headers = { 'User-Agent' => ' JamKazam ' }
visit "/"
find('h1', text: 'Play music together over the Internet as if in the same room')
end
let(:user) { FactoryGirl.create(:user) }
let(:fb_auth) {
{ :provider => "facebook",
:uid => "1234",
:info => {:name => "John Doe",
:email => "johndoe@email.com"},
:credentials => {:token => "testtoken234tsdf", :expires_at => 2391456019},
:extra => { :raw_info => {:first_name => 'John', :last_name => 'Doe', :email => 'facebook@jamkazam.com', :gender => 'male'}} }
}
describe "signin" do
before(:each) do
find('#signin').trigger(:click)
end
it "show dialog" do
should have_selector('h1', text: 'sign in')
end
it "shows signup dialog if selected" do
find('.show-signup-dialog').trigger(:click)
find('h1', text: 'sign up for jamkazam')
end
it "forgot password" do
find('a.forgot-password').trigger(:click)
find('h1', text: 'reset your password')
end
it "closes if cancelled" do
find('a.signin-cancel').trigger(:click)
should_not have_selector('h1', text: 'sign in')
end
describe "signin natively" do
it "redirects to client on login" do
within('#signin-form') do
fill_in "email", with: user.email
fill_in "password", with: user.password
click_button "SIGN IN"
end
wait_until_curtain_gone
find('h2', text: 'musicians')
end
it "shows error if bad login" do
within('#signin-form') do
fill_in "email", with: "junk"
fill_in "password", with: user.password
click_button "SIGN IN"
end
should have_selector('h1', text: 'sign in')
find('div.login-error-msg', text: 'Invalid login')
end
end
describe "signin with facebook" do
before(:each) do
user.user_authorizations.build provider: 'facebook', uid: '1234', token: 'abc', token_expiration: 1.days.from_now
user.save!
OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(fb_auth)
end
it "click will redirect to facebook for authorization" do
find('.signin-facebook').trigger(:click)
wait_until_curtain_gone
find('h2', text: 'musicians')
end
end
end
describe "signup" do
before(:each) do
find('#signup').trigger(:click)
end
it "show dialog" do
should have_selector('h1', text: 'sign up for jamkazam')
end
it "shows signin dialog if selected" do
find('.show-signin-dialog').trigger(:click)
find('h1', text: 'sign in')
end
it "closes if cancelled" do
find('a.signup-cancel').trigger(:click)
should_not have_selector('h1', text: 'sign in')
end
describe "signup with email" do
it "click will redirect to signup page" do
find('.signup-email').trigger(:click)
find('h2', text: 'Create a JamKazam account')
end
end
describe "signup with facebook" do
before(:each) do
fb_auth[:uid] = '12345'
OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(fb_auth)
end
it "click will redirect to facebook for authorization" do
find('.signup-facebook').trigger(:click)
find('h2', text: 'Create a JamKazam account')
find_field('jam_ruby_user[first_name]').value.should eq 'John'
find_field('jam_ruby_user[last_name]').value.should eq 'Doe'
find_field('jam_ruby_user[email]').value.should eq 'facebook@jamkazam.com'
end
end
end
end

View File

@ -15,7 +15,16 @@ describe UserManager do
MaxMindIsp.delete_all # prove that city/state/country will remain nil if no maxmind data
MaxMindGeo.delete_all
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman1@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman1@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician:true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.first_name.should == "bob"
@ -33,8 +42,16 @@ describe UserManager do
end
it "signup successfully with instruments" do
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman2@jamkazam.com", "foobar", "foobar", true,
@instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.instruments.length.should == 1
@ -44,7 +61,15 @@ describe UserManager do
end
it "doesnt fail if ip address is nil" do
@user = @user_manager.signup(nil, "bob", "smith", "userman3@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(first_name: "bob",
last_name: "smith",
email: "userman3@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.city.should be_nil
@ -56,7 +81,16 @@ describe UserManager do
MaxMindManager.active_record_transaction do |manager|
manager.create_phony_database()
end
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman4@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman4@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.city.should == 'City 127'
@ -68,7 +102,17 @@ describe UserManager do
MaxMindManager.active_record_transaction do |manager|
manager.create_phony_database()
end
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman5@jamkazam.com", "foobar", "foobar", true, @instruments, nil, @location, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman5@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @location,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.city.should == 'Little Rock'
@ -80,7 +124,17 @@ describe UserManager do
MaxMindManager.active_record_transaction do |manager|
manager.create_phony_database()
end
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman6@jamkazam.com", "foobar", "foobar", true, @instruments, nil, {}, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman6@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: {},
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.city.should be_nil
@ -93,7 +147,17 @@ describe UserManager do
MaxMindManager.active_record_transaction do |manager|
manager.create_phony_database()
end
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman7@jamkazam.com", "foobar", "foobar", true, @instruments, Date.new(2001, 1, 1), nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman7@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
birth_date: Date.new(2001, 1, 1),
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
@user.errors.any?.should be_false
@user.birth_date.should == Date.new(2001, 1, 1)
@ -101,26 +165,64 @@ describe UserManager do
it "duplicate signup failure" do
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman8@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
@user.errors.any?.should be_false
# exactly the same parameters; should dup on email, and send no email
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman8@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
@user.errors.any?.should be_true
@user.errors[:email][0].should == "has already been taken"
end
it "fail on no username" do
@user = @user_manager.signup("127.0.0.1", "", "", "userman10@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm")
it "fail on no first_name/last_name" do
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "",
last_name: "",
email: "userman10@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 0
@user.errors.any?.should be_true
@user.errors[:first_name][0].should == "can't be blank"
end
it "fail on no email" do
@user = @user_manager.signup("127.0.0.1", "murp", "blurp", "", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "murp",
last_name: "blurp",
email: "",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 0
@user.errors.any?.should be_true
@user.errors[:email][0].should == "can't be blank"
@ -130,7 +232,16 @@ describe UserManager do
describe "signup_confirm" do
it "fail on no username" do
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman11@jamkazam.com", "foobar", "foobar", true, @instruments, nil, nil, true, nil, nil, "http://localhost:3000/confirm" )
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman11@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
@user = @user_manager.signup_confirm(@user.signup_token)
@user.email_confirmed.should be_true
end
@ -156,8 +267,17 @@ describe UserManager do
@invitation.accepted.should be_false
@user = @user_manager.signup("127.0.0.1", "bob", "smith", @invitation.email, "foobar", "foobar", true,
@instruments, nil, nil, true, nil, @invitation, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: @invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: @invitation,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_true
@ -176,8 +296,17 @@ describe UserManager do
UserMailer.deliveries.clear
@user = @user_manager.signup("127.0.0.1", "bob", "smith", @invitation.email, "foobar", "foobar", true,
@instruments, nil, nil, true, nil, @invitation, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: @invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: @invitation,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_true
@ -196,8 +325,17 @@ describe UserManager do
UserMailer.deliveries.clear
@user = @user_manager.signup("127.0.0.1", "bob", "smith", @invitation.email, "foobar", "foobar", true,
@instruments, nil, nil, true, nil, @invitation, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: @invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: @invitation,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_true
@ -218,8 +356,17 @@ describe UserManager do
UserMailer.deliveries.clear
@user = @user_manager.signup("127.0.0.1", "bob", "smith", "userman12@jamkazam.com", "foobar", "foobar", true,
@instruments, nil, nil, true, nil, @invitation, "http://localhost:3000/confirm")
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman12@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: @invitation,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_false
@ -229,6 +376,91 @@ describe UserManager do
@user.friends?(@some_user).should be_true
@user.friends?(@some_user).should be_true
UserMailer.deliveries.length.should == 1 # no emails should be sent, in this case
UserMailer.deliveries.length.should == 1
end
it "signup successfully with facebook signup additional info" do
fb_signup = FactoryGirl.create(:facebook_signup)
UserMailer.deliveries.clear
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: fb_signup.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_true
@user.signup_token.should be_nil
@user.user_authorizations.length.should == 1
@user.user_authorizations[0].uid = fb_signup.uid
@user.user_authorizations[0].token = fb_signup.token
@user.user_authorizations[0].token_expiration = fb_signup.token_expires_at
UserMailer.deliveries.length.should == 1
end
it "signup successfully with facebook signup additional info, but different email" do
fb_signup = FactoryGirl.create(:facebook_signup)
UserMailer.deliveries.clear
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_false
@user.email_confirmed.should be_false
@user.signup_token.should_not be_nil
@user.user_authorizations.length.should == 1
@user.user_authorizations[0].uid = fb_signup.uid
@user.user_authorizations[0].token = fb_signup.token
@user.user_authorizations[0].token_expiration = fb_signup.token_expires_at
UserMailer.deliveries.length.should == 1
end
it "fail to signup when facebook UID already taken" do
fb_signup = FactoryGirl.create(:facebook_signup)
@some_user = FactoryGirl.create(:user)
@some_user.update_fb_authorization(fb_signup)
@some_user.save!
UserMailer.deliveries.clear
@user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
@user.errors.any?.should be_true
@user.errors[:user_authorizations].should == ['is invalid']
UserMailer.deliveries.length.should == 0
end
end

View File

@ -1,5 +1,6 @@
require 'rubygems'
require 'spork'
require 'omniauth'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'
@ -25,6 +26,8 @@ include JamRuby
# put ActionMailer into test mode
ActionMailer::Base.delivery_method = :test
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you'll

View File

@ -11,7 +11,5 @@ GROUP="$NAME"
cp /var/lib/$NAME/script/package/$NAME.conf /etc/init/$NAME.conf
mkdir -p /var/lib/$NAME/log
mkdir -p /var/run/$NAME
chown -R $USER:$GROUP /var/lib/$NAME
chown -R $USER:$GROUP /var/run/$NAME

View File

@ -6,4 +6,10 @@ stop on runlevel [016]
setuid websocket-gateway
setgid websocket-gateway
pre-start script
set -e
mkdir -p /var/run/websocket-gateway
chown websocket-gateway:websocket-gateway /var/run/websocket-gateway
end script
exec start-stop-daemon --start --chdir /var/lib/websocket-gateway --exec /var/lib/websocket-gateway/script/package/upstart-run.sh