diff --git a/db/manifest b/db/manifest index f5ffa9cc3..f25bfd8dd 100755 --- a/db/manifest +++ b/db/manifest @@ -257,4 +257,5 @@ add_jam_track_bitrates.sql widen_user_authorization_token.sql jam_track_version.sql recorded_jam_track_tracks.sql -jam_track_jmep_data.sql \ No newline at end of file +jam_track_jmep_data.sql +shopping_cart_anonymous.sql \ No newline at end of file diff --git a/db/up/shopping_cart_anonymous.sql b/db/up/shopping_cart_anonymous.sql new file mode 100644 index 000000000..e22cfeecd --- /dev/null +++ b/db/up/shopping_cart_anonymous.sql @@ -0,0 +1,2 @@ +ALTER TABLE shopping_carts ALTER COLUMN user_id DROP NOT NULL; +ALTER TABLE shopping_carts ADD COLUMN anonymous_user_id VARCHAR(1000); \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 67f81933b..6e9d9d726 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -97,6 +97,7 @@ require "jam_ruby/models/max_mind_release" require "jam_ruby/models/genre_player" require "jam_ruby/models/genre" require "jam_ruby/models/user" +require "jam_ruby/models/anonymous_user" require "jam_ruby/models/rsvp_request" require "jam_ruby/models/rsvp_slot" require "jam_ruby/models/rsvp_request_rsvp_slot" diff --git a/ruby/lib/jam_ruby/models/anonymous_user.rb b/ruby/lib/jam_ruby/models/anonymous_user.rb new file mode 100644 index 000000000..ff075a3e6 --- /dev/null +++ b/ruby/lib/jam_ruby/models/anonymous_user.rb @@ -0,0 +1,21 @@ +# this was added to support the idea of an anonymous user interacting with our site; needed by the ShoppingCart +# over time it might make sense to beef this up and to use it conistently in anonymous interactions + +module JamRuby + class AnonymousUser + + attr_accessor :id + + def initialize(id) + @id = id + end + + def shopping_carts + ShoppingCart.where(anonymous_user_id: @id) + end + + def destroy_all_shopping_carts + ShoppingCart.destroy_all(anonymous_user_id: @id) + end + end +end diff --git a/ruby/lib/jam_ruby/models/shopping_cart.rb b/ruby/lib/jam_ruby/models/shopping_cart.rb index da1e567f6..401278d84 100644 --- a/ruby/lib/jam_ruby/models/shopping_cart.rb +++ b/ruby/lib/jam_ruby/models/shopping_cart.rb @@ -22,7 +22,12 @@ module JamRuby def self.create user, product, quantity = 1 cart = ShoppingCart.new - cart.user = user + if user.is_a?(User) + cart.user = user + else + cart.anonymous_user_id = user.id + end + cart.cart_type = product.class::PRODUCT_TYPE cart.cart_class_name = product.class.name cart.cart_id = product.id diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index a469ab69a..02ce5486a 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -1503,6 +1503,11 @@ module JamRuby stats['audio_latency_avg'] = result['last_jam_audio_latency_avg'].to_f stats end + + def destroy_all_shopping_carts + ShoppingCart.where("user_id=?", self).destroy_all + end + private def create_remember_token self.remember_token = SecureRandom.urlsafe_base64 diff --git a/web/app/controllers/api_shopping_carts_controller.rb b/web/app/controllers/api_shopping_carts_controller.rb index 5cff85b97..3bb02701f 100644 --- a/web/app/controllers/api_shopping_carts_controller.rb +++ b/web/app/controllers/api_shopping_carts_controller.rb @@ -1,11 +1,11 @@ class ApiShoppingCartsController < ApiController - before_filter :api_signed_in_user + before_filter :api_any_user respond_to :json def index - @carts = current_user.shopping_carts + @carts = any_user.shopping_carts end def add_jamtrack @@ -16,7 +16,7 @@ class ApiShoppingCartsController < ApiController raise StateError, "Invalid JamTrack." end - @cart = ShoppingCart.create current_user, jam_track + @cart = ShoppingCart.create any_user, jam_track if @cart.errors.any? response.status = :unprocessable_entity @@ -43,7 +43,7 @@ class ApiShoppingCartsController < ApiController end def remove_cart - @cart = current_user.shopping_carts.find_by_id(params[:id]) + @cart = any_user.shopping_carts.find_by_id(params[:id]) raise StateError, "Invalid Cart." if @cart.nil? @cart.destroy @@ -51,7 +51,7 @@ class ApiShoppingCartsController < ApiController end def clear_all - ShoppingCart.where("user_id=?", current_user).destroy_all + any_user.destroy_all_shopping_carts render :json=>{}, :status=>200 end diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 29e294ac5..4a2ae2397 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -12,6 +12,8 @@ class ApplicationController < ActionController::Base gon_setup end + before_filter :set_tracking_cookie + before_filter do if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? if cookies[AffiliatePartner::PARAM_COOKIE].blank? @@ -25,6 +27,12 @@ class ApplicationController < ActionController::Base cookies[AffiliatePartner::PARAM_COOKIE] end + + # http://stackoverflow.com/questions/15807214/where-to-set-a-tracking-permanent-cookie-in-rails + def set_tracking_cookie + cookies.permanent[:user_uuid] = SecureRandom.uuid unless cookies[:user_uuid] + end + private def add_user_info_to_bugsnag(notif) # Add some app-specific data which will be displayed on a custom diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb index 6665b8c00..5232fc24c 100644 --- a/web/app/helpers/sessions_helper.rb +++ b/web/app/helpers/sessions_helper.rb @@ -26,8 +26,8 @@ module SessionsHelper !current_user.nil? end - def logged_in_not_logged_in_class - signed_in? ? "logged-in" : "not-logged-in" + def has_anonymous_user? + !anonymous_user.nil? end def current_user=(user) @@ -38,6 +38,27 @@ module SessionsHelper @current_user ||= User.find_by_remember_token(cookies[:remember_token]) end + def anonymous_user=(anonymous_user) + @anonymous_user = anonymous_user + end + + def anonymous_user + if anon_cookie + @anonymous_user ||= AnonymousUser.new(anon_cookie) + else + nil + end + end + + # tries current_user over anonymous_user + def any_user + current_user || anonymous_user + end + + def anon_cookie + @anon_cookie ||= cookies[:user_uuid] + end + def current_user?(user) user == current_user end @@ -49,13 +70,19 @@ module SessionsHelper end end - def api_signed_in_user unless signed_in? render :json => { :message => "not logged in"}, :status => 403 end end + # take either the signed in user, or if that fails, try the anonymous user + def api_any_user + unless signed_in? || has_anonymous_user? + render :json => { :message => "not logged in"}, :status => 403 + end + end + def sign_out current_user = nil cookies.delete(:remember_token, domain: Rails.application.config.session_cookie_domain) @@ -96,6 +123,11 @@ module SessionsHelper end end + def logged_in_not_logged_in_class + signed_in? ? "logged-in" : "not-logged-in" + end + + def metronome_tempos [ 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 63, 66, 69, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 126, 132, 138, 144, 152, 160, 168, 176, 184, 192, 200, 208 diff --git a/web/spec/controllers/api_shopping_carts_controller_spec.rb b/web/spec/controllers/api_shopping_carts_controller_spec.rb new file mode 100644 index 000000000..4c9f69079 --- /dev/null +++ b/web/spec/controllers/api_shopping_carts_controller_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + + + +describe ApiShoppingCartsController do + + render_views + + let(:jam_track) { FactoryGirl.create(:jam_track) } + + before(:each) do + ShoppingCart.delete_all + controller.anonymous_user.should be_nil + controller.current_user.should be_nil + end + + describe "logged in" do + + let(:user) { FactoryGirl.create(:user) } + + before(:each) do + controller.current_user = user + controller.anonymous_user = nil + end + + it "add_jamtrack" do + post :add_jamtrack, {:format => 'json', id: jam_track.id} + response.status.should == 201 + end + + it "index" do + cart = ShoppingCart.create(user, jam_track) + + get :index, {:format => 'json'} + response.status.should == 200 + response_body = JSON.parse(response.body) + response_body.length.should eq(1) + response_body[0]["id"].should eq(cart.id) + end + + it "remove_cart" do + cart = ShoppingCart.create(user, jam_track) + delete :remove_cart, {:format => 'json', id: cart.id} + response.status.should == 204 + ShoppingCart.find_by_id(cart.id).should be_nil + end + + it "clears cart" do + cart = ShoppingCart.create(user, jam_track) + delete :clear_all, {:format => 'json'} + response.status.should == 200 + ShoppingCart.find_by_id(cart.id).should be_nil + end + end + + describe "anonymous" do + + let(:user) { AnonymousUser.new('abc') } + + before(:each) do + controller.current_user = nil + controller.anonymous_user = user + end + + it "add_jamtrack" do + post :add_jamtrack, {:format => 'json', id: jam_track.id} + response.status.should == 201 + end + + it "index" do + cart = ShoppingCart.create(user, jam_track) + + get :index, {:format => 'json'} + response.status.should == 200 + response_body = JSON.parse(response.body) + response_body.length.should eq(1) + response_body[0]["id"].should eq(cart.id) + end + + it "remove_cart" do + cart = ShoppingCart.create(user, jam_track) + delete :remove_cart, {:format => 'json', id: cart.id} + response.status.should == 204 + ShoppingCart.find_by_id(cart.id).should be_nil + end + + it "clears cart" do + cart = ShoppingCart.create(user, jam_track) + delete :clear_all, {:format => 'json'} + response.status.should == 200 + ShoppingCart.find_by_id(cart.id).should be_nil + end + end + + describe "cookieless" do + + end + +end