diff --git a/db/manifest b/db/manifest index 6227fe0e1..d43f203a9 100755 --- a/db/manifest +++ b/db/manifest @@ -247,4 +247,5 @@ user_model_about_changes.sql performance_samples.sql user_presences.sql discard_scores_optimized.sql -alter_type_columns.sql \ No newline at end of file +alter_type_columns.sql +user_presences_rename.sql \ No newline at end of file diff --git a/db/up/user_presences_rename.sql b/db/up/user_presences_rename.sql new file mode 100644 index 000000000..92cb4e4ca --- /dev/null +++ b/db/up/user_presences_rename.sql @@ -0,0 +1,10 @@ +drop table user_presences; + +CREATE TABLE online_presences ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + service_type VARCHAR(100) NOT NULL, + username VARCHAR(100) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index b6ba623f6..4522b6c71 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -201,7 +201,7 @@ require "jam_ruby/models/recorded_video" require "jam_ruby/models/text_message" require "jam_ruby/jam_tracks_manager" require "jam_ruby/models/performance_sample" -require "jam_ruby/models/user_presence" +require "jam_ruby/models/online_presence" include Jampb diff --git a/ruby/lib/jam_ruby/models/user_presence.rb b/ruby/lib/jam_ruby/models/online_presence.rb similarity index 75% rename from ruby/lib/jam_ruby/models/user_presence.rb rename to ruby/lib/jam_ruby/models/online_presence.rb index 5f590e429..774ee0b94 100644 --- a/ruby/lib/jam_ruby/models/user_presence.rb +++ b/ruby/lib/jam_ruby/models/online_presence.rb @@ -1,5 +1,5 @@ module JamRuby - class UserPresence < ActiveRecord::Base + class OnlinePresence < ActiveRecord::Base PERMISSION_MSG = "You do not have permission to perform this operation." @@ -12,20 +12,20 @@ module JamRuby validate :username_service_type_unique def username_service_type_unique - match = UserPresence.exists?(:username => self.username, :service_type => self.service_type) + match = OnlinePresence.exists?(:username => self.username, :service_type => self.service_type) raise ConflictError, "Username #{self.username} is already associated with a #{self.service_type} account" if match end def self.index(options = {}) raise StateError, "The user is not specified." if options[:id].blank? - UserPresence.where("user_id = ?", options[:id]) + OnlinePresence.where("user_id = ?", options[:id]) end def self.create(current_user, options = {}) auth_user(current_user, options) raise StateError, "Missing required information" if options[:service_type].blank? || options[:username].blank? - up = UserPresence.new({:user_id => current_user.id, :service_type => options[:service_type], :username => options[:username]}) + up = OnlinePresence.new({:user_id => current_user.id, :service_type => options[:service_type], :username => options[:username]}) up.save! end @@ -33,7 +33,7 @@ module JamRuby auth_user(current_user, options) raise StateError, "Missing required information" if options[:service_type].blank? || options[:username].blank? || options[:id].blank? - up = UserPresence.find(options[:id]) + up = OnlinePresence.find(options[:id]) up.service_type = options[:service_type] up.username = options[:username] up.save! @@ -42,14 +42,14 @@ module JamRuby def self.delete(current_user, options = {}) id = options[:id] raise StateError, "Missing required information" if id.blank? - user_presence = UserPresence.find(id) + online_presence = OnlinePresence.find(id) - if user_presence.user_id != current_user.id + if online_presence.user_id != current_user.id raise PermissionError, PERMISSION_MSG end - unless user_presence.nil? - UserPresence.destroy(id) + unless online_presence.nil? + OnlinePresence.destroy(id) end end diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index a553e07d4..0927bf11d 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -152,7 +152,7 @@ module JamRuby # This causes the authenticate method to be generated (among other stuff) #has_secure_password - has_many :user_presences, :class_name => "JamRuby::UserPresence" + has_many :online_presences, :class_name => "JamRuby::OnlinePresence" has_many :performance_samples, :class_name => "JamRuby::PerformanceSample" before_save :create_remember_token, :if => :should_validate_password? diff --git a/ruby/spec/jam_ruby/models/online_presence_spec.rb b/ruby/spec/jam_ruby/models/online_presence_spec.rb new file mode 100644 index 000000000..ce642ac58 --- /dev/null +++ b/ruby/spec/jam_ruby/models/online_presence_spec.rb @@ -0,0 +1,160 @@ +require 'spec_helper' + +describe OnlinePresence do + + let(:user1) { FactoryGirl.create(:user) } + let(:user2) { FactoryGirl.create(:user) } + + describe "index" do + + before(:all) do + OnlinePresence.delete_all + + user1_presence1 = OnlinePresence.new({:user_id => user1.id, :username => "myonlineusername", :service_type => "facebook"}) + user1_presence1.save! + + user1_presence2 = OnlinePresence.new({:user_id => user1.id, :username => "myonlineusername", :service_type => "twitter"}) + user1_presence2.save! + + user2_presence1 = OnlinePresence.new({:user_id => user2.id, :username => "myonlineusername", :service_type => "soundcloud"}) + user2_presence1.save! + end + + context "when request is valid" do + it "should return all records for user" do + presence = OnlinePresence.index({:id => user1.id}) + presence.count.should == 2 + + presence = OnlinePresence.index({:id => user2.id}) + presence.count.should == 1 + end + end + + context "when request is invalid" do + it "should raise error when options are missing" do + lambda{OnlinePresence.index}.should raise_error(StateError) + end + + it "should raise error when user id is missing" do + lambda{OnlinePresence.index({:id => ""})}.should raise_error(StateError) + end + end + end + + describe "create" do + + before(:all) do + OnlinePresence.delete_all + end + + context "when request is valid" do + it "should save successfully" do + OnlinePresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"}) + + # make sure we can save a second OnlinePresence for same user and type + OnlinePresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser2"}) + + OnlinePresence.index({:id => user1.id}).count.should == 2 + end + end + + context "when request is not valid" do + it "should raise PermissionError if requester id does not match id in request" do + lambda{OnlinePresence.create(user1, {:user_id => user2.id, :service_type => "soundcloud", :username => "soundclouduser2"})}.should raise_error(PermissionError) + end + + it "should raise error if service type is missing" do + lambda{OnlinePresence.create(user1, {:user_id => user1.id, :username => "soundclouduser2"})}.should raise_error(StateError) + end + + it "should raise error if username is missing" do + lambda{OnlinePresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud"})}.should raise_error(StateError) + end + + it "should not allow duplicates of the same username / service type combination" do + OnlinePresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"}) + OnlinePresence.index({:id => user1.id}).count.should == 1 + + lambda{OnlinePresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"})}.should raise_error(ConflictError) + OnlinePresence.index({:id => user1.id}).count.should == 1 + end + end + end + + describe "update" do + + before(:all) do + OnlinePresence.delete_all + @online_presence = OnlinePresence.new(:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1") + @online_presence.save! + end + + context "when request is valid" do + it "should save successfully" do + + up_list = OnlinePresence.index({:id => user1.id}) + up_list.count.should == 1 + up_list.first.service_type.should == "soundcloud" + up_list.first.username.should == "soundclouduser1" + + OnlinePresence.update(user1, {:id => @online_presence.id, :user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser2"}) + + up_list = OnlinePresence.index({:id => user1.id}) + up_list.count.should == 1 + up_list.first.service_type.should == "soundcloud" + up_list.first.username.should == "soundclouduser2" + end + end + + context "when request is not valid" do + it "should raise PermissionError if requester id does not match id in request" do + lambda{OnlinePresence.update(user1, {:user_id => user2.id, :id => @online_presence.id, :service_type => "soundcloud", :username => "soundclouduser2"})}.should raise_error(PermissionError) + end + + it "should raise error if type is missing" do + lambda{OnlinePresence.update(user1, {:user_id => user1.id, :id => @online_presence.id, :username => "soundclouduser2"})}.should raise_error(StateError) + end + + it "should raise error if username is missing" do + lambda{OnlinePresence.update(user1, {:user_id => user1.id, :id => @online_presence.id, :service_type => "soundcloud"})}.should raise_error(StateError) + end + + it "should raise error if user presence id is missing" do + lambda{OnlinePresence.update(user1, {:user_id => user1.id, :username => "soundclouduser2", :service_type => "soundcloud"})}.should raise_error(StateError) + end + end + end + + describe "destroy" do + + before(:all) do + OnlinePresence.delete_all + @online_presence = OnlinePresence.new(:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1") + @online_presence.save! + end + + context "when request is valid" do + it "should destroy successfully" do + up_list = OnlinePresence.index({:id => user1.id}) + up_list.count.should == 1 + up_list.first.service_type.should == "soundcloud" + up_list.first.username.should == "soundclouduser1" + + OnlinePresence.delete(user1, {:user_id => user1.id, :id => @online_presence.id}) + + up_list = OnlinePresence.index({:id => user1.id}) + up_list.count.should == 0 + end + end + + context "when request is not valid" do + it "should raise PermissionError if requester id does not match id in request" do + lambda{OnlinePresence.delete(user2, {:user_id => user1.id, :id => @online_presence.id})}.should raise_error(PermissionError) + end + + it "should raise error if user presence id is missing" do + lambda{OnlinePresence.delete(user1, {:user_id => user1.id})}.should raise_error(StateError) + end + end + end +end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/models/user_presence_spec.rb b/ruby/spec/jam_ruby/models/user_presence_spec.rb deleted file mode 100644 index 06f51221a..000000000 --- a/ruby/spec/jam_ruby/models/user_presence_spec.rb +++ /dev/null @@ -1,160 +0,0 @@ -require 'spec_helper' - -describe UserPresence do - - let(:user1) { FactoryGirl.create(:user) } - let(:user2) { FactoryGirl.create(:user) } - - describe "index" do - - before(:all) do - UserPresence.delete_all - - user1_presence1 = UserPresence.new({:user_id => user1.id, :username => "myonlineusername", :service_type => "facebook"}) - user1_presence1.save! - - user1_presence2 = UserPresence.new({:user_id => user1.id, :username => "myonlineusername", :service_type => "twitter"}) - user1_presence2.save! - - user2_presence1 = UserPresence.new({:user_id => user2.id, :username => "myonlineusername", :service_type => "soundcloud"}) - user2_presence1.save! - end - - context "when request is valid" do - it "should return all records for user" do - presence = UserPresence.index({:id => user1.id}) - presence.count.should == 2 - - presence = UserPresence.index({:id => user2.id}) - presence.count.should == 1 - end - end - - context "when request is invalid" do - it "should raise error when options are missing" do - lambda{UserPresence.index}.should raise_error(StateError) - end - - it "should raise error when user id is missing" do - lambda{UserPresence.index({:id => ""})}.should raise_error(StateError) - end - end - end - - describe "create" do - - before(:all) do - UserPresence.delete_all - end - - context "when request is valid" do - it "should save successfully" do - UserPresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"}) - - # make sure we can save a second UserPresence for same user and type - UserPresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser2"}) - - UserPresence.index({:id => user1.id}).count.should == 2 - end - end - - context "when request is not valid" do - it "should raise PermissionError if requester id does not match id in request" do - lambda{UserPresence.create(user1, {:user_id => user2.id, :service_type => "soundcloud", :username => "soundclouduser2"})}.should raise_error(PermissionError) - end - - it "should raise error if service type is missing" do - lambda{UserPresence.create(user1, {:user_id => user1.id, :username => "soundclouduser2"})}.should raise_error(StateError) - end - - it "should raise error if username is missing" do - lambda{UserPresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud"})}.should raise_error(StateError) - end - - it "should not allow duplicates of the same username / service type combination" do - UserPresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"}) - UserPresence.index({:id => user1.id}).count.should == 1 - - lambda{UserPresence.create(user1, {:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1"})}.should raise_error(ConflictError) - UserPresence.index({:id => user1.id}).count.should == 1 - end - end - end - - describe "update" do - - before(:all) do - UserPresence.delete_all - @user_presence = UserPresence.new(:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1") - @user_presence.save! - end - - context "when request is valid" do - it "should save successfully" do - - up_list = UserPresence.index({:id => user1.id}) - up_list.count.should == 1 - up_list.first.service_type.should == "soundcloud" - up_list.first.username.should == "soundclouduser1" - - UserPresence.update(user1, {:id => @user_presence.id, :user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser2"}) - - up_list = UserPresence.index({:id => user1.id}) - up_list.count.should == 1 - up_list.first.service_type.should == "soundcloud" - up_list.first.username.should == "soundclouduser2" - end - end - - context "when request is not valid" do - it "should raise PermissionError if requester id does not match id in request" do - lambda{UserPresence.update(user1, {:user_id => user2.id, :id => @user_presence.id, :service_type => "soundcloud", :username => "soundclouduser2"})}.should raise_error(PermissionError) - end - - it "should raise error if type is missing" do - lambda{UserPresence.update(user1, {:user_id => user1.id, :id => @user_presence.id, :username => "soundclouduser2"})}.should raise_error(StateError) - end - - it "should raise error if username is missing" do - lambda{UserPresence.update(user1, {:user_id => user1.id, :id => @user_presence.id, :service_type => "soundcloud"})}.should raise_error(StateError) - end - - it "should raise error if user presence id is missing" do - lambda{UserPresence.update(user1, {:user_id => user1.id, :username => "soundclouduser2", :service_type => "soundcloud"})}.should raise_error(StateError) - end - end - end - - describe "destroy" do - - before(:all) do - UserPresence.delete_all - @user_presence = UserPresence.new(:user_id => user1.id, :service_type => "soundcloud", :username => "soundclouduser1") - @user_presence.save! - end - - context "when request is valid" do - it "should destroy successfully" do - up_list = UserPresence.index({:id => user1.id}) - up_list.count.should == 1 - up_list.first.service_type.should == "soundcloud" - up_list.first.username.should == "soundclouduser1" - - UserPresence.delete(user1, {:user_id => user1.id, :id => @user_presence.id}) - - up_list = UserPresence.index({:id => user1.id}) - up_list.count.should == 0 - end - end - - context "when request is not valid" do - it "should raise PermissionError if requester id does not match id in request" do - lambda{UserPresence.delete(user2, {:user_id => user1.id, :id => @user_presence.id})}.should raise_error(PermissionError) - end - - it "should raise error if user presence id is missing" do - lambda{UserPresence.delete(user1, {:user_id => user1.id})}.should raise_error(StateError) - end - end - end -end \ No newline at end of file diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 0a5d20c95..2cc7cfcc4 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -490,6 +490,20 @@ return detail; } + function getUserProfile(options) { + var id = getId(options); + var profile = null; + if (id != null && typeof(id) != 'undefined') { + profile = $.ajax({ + type: "GET", + dataType: "json", + url: "/api/users/" + id + "/profile", + processData: false + }); + } + return profile; + } + function getCities(options) { var country = options['country'] var region = options['region'] diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index 34ea1154d..c4a986ad1 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -32,6 +32,17 @@ class ApiUsersController < ApiController respond_with @user, responder: ApiResponder, :status => 200 end + def profile + @profile = User.includes([{musician_instruments: :instrument}, + {band_musicians: :user}, + {genre_players: :genre}, + :bands, :instruments, :genres, + :user_presences, :performance_samples]) + .find(params[:id]) + + respond_with @profile, responder: ApiResponder, :status => 200 + end + def update @user = User.find(params[:id]) diff --git a/web/app/views/api_users/profile.rabl b/web/app/views/api_users/profile.rabl new file mode 100644 index 000000000..bdb137c20 --- /dev/null +++ b/web/app/views/api_users/profile.rabl @@ -0,0 +1,20 @@ +object @profile + +attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count, :recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :concert_count, :studio_session_count, :virtual_band, :virtual_band_commitment, :traditional_band, :traditional_band_commitment, :traditional_band_touring, :paid_sessions, :paid_sessions_hourly_rate, +:paid_sessions_daily_rate, :free_sessions, :cowriting, :cowriting_purpose + +child :user_presences => :online_presences do + attributes :id, :service_type, :username +end + +child :performance_samples => :performance_samples do + attributes :id, :url, :service_type, :claimed_recording_id, :service_id + + child :claimed_recording => :claimed_recording do + attributes :name + end +end + +child :genre_players => :genres do + attributes :genre_id, :player_type +end \ No newline at end of file diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index d402ff6a7..03e38f321 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -1,7 +1,6 @@ object @user -attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count, :recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :concert_count, :studio_session_count, :virtual_band, :virtual_band_commitment, :traditional_band, :traditional_band_commitment, :traditional_band_touring, :paid_sessions, :paid_sessions_hourly_rate, -:paid_sessions_daily_rate, :free_sessions, :cowriting, :cowriting_purpose +attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count, :recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level if @user.musician? node :location do @user.location end